俄罗斯方块程序

游戏基本规则都实现了,先放上来,以后再完善

"""
1.本程序开发环境为python3.7,用其他版本python运行
需要修改程序

2.本程序依赖于第三方库numpy,如果没有需要自行安装
"""

from tkinter import *
from numpy import mat
import numpy as np
import time



class Block:

    coords = None
    speed = 20

    def right(self):
        translation = mat([[1,0],[1,0],[1,0],[1,0]])*self.speed
        self.coords +=translation

    def left(self):
        translation = mat([[1, 0], [1, 0], [1, 0], [1, 0]]) * self.speed
        self.coords -= translation

    def down(self):
        translation = mat([[0, 1], [0, 1], [0, 1], [0, 1]]) * self.speed
        self.coords += translation

    def rotate(self):
        translation = mat([[0,1],[-1,0]])
        core = self.coords[1]
        for i in range(len(self)):
            self.coords[i] = (self.coords[i]-core)*translation + core

    def __getitem__(self, item):
        return self.coords[item].tolist()[0]

    def __len__(self):
        return self.coords.shape[0]


class VerticalBlock(Block):

    _show = [[500, 40], [500, 60], [500, 80], [500, 100]]

    def __init__(self):
        self.coords = mat([[200,0],[200,20],[200,40],[200,60]])


class TBlock(Block):

    _show = [[480, 40], [500, 40], [500, 60], [520, 40]]

    def __init__(self):
        self.coords = mat([[180,0],[200,0],[200,20],[220,0]])


class SquareBlock(Block):

    _show = [[480, 40], [480, 60], [500, 40], [500, 60]]

    def __init__(self):
        self.coords = mat([[180,0],[180,20],[200,0],[200,20]])


class LRightBlock(Block):

    _show = [[480, 40], [500, 40], [520, 60], [520, 40]]

    def __init__(self):
        self.coords = mat([[180,0],[200,0],[220,20],[220,0]])


class LLeftBlock(Block):

    _show = [[480, 40], [500, 40], [480, 60], [520, 40]]

    def __init__(self):
        self.coords = mat([[180,0],[200,0],[180,20],[220,0]])


class ZBlock(Block):

    _show = [[480,40], [500,40], [500, 60], [520,60]]

    def __init__(self):
        self.coords = mat([[180,0],[200,0],[200,20],[220,20]])


class ZMirrorBlock(Block):

    _show = [[480, 60], [500, 60], [500, 40], [520, 40]]

    def __init__(self):
        self.coords = mat([[180,20],[200,20],[200,0],[220,0]])


class Handler:

    def __init__(self,root):
        self.root = root
        self.canvas = Canvas(root,height=600 ,width = 600)
        self.canvas.create_rectangle(0,0,400,600,fill="white")
        self.scorer = Scorer(self.canvas)
        self.canvas.bind("<Left>", self.move_left)
        self.canvas.bind("<Right>", self.move_right)
        self.canvas.bind("<Up>", self.change_shape)
        self.canvas.bind("<Down>", self.accelerate)
        self.canvas.focus_set()
        self.canvas.pack()

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.canvas.create_text(300, 300, text=f"游戏结束!您的得分为{self.scorer}", fill='red')
        mainloop()

    def create_block(self,name):
        self.block = name()
        self.create(self.block)

    def paint(self, x, y):
        return self.canvas.create_rectangle(x, y, x + 20, y + 20, fill='blue')

    def create(self,block):
        block.body = [self.paint(*block[i]) for i in range(len(block))]

    def delete(self,block):
        for s in block.body:
            self.canvas.delete(s)

    def show(self,block):
        if hasattr(self,'_show'):
            for item in self._show:
                self.canvas.delete(item)
        self._show = [self.paint(*item) for item in block._show]

    def move_right(self,event):
        if Rule.can_right(self.block):
            self.block.right()
            self.delete(self.block)
            self.create(self.block)

    def move_left(self,event):
        if Rule.can_left(self.block):
            self.block.left()
            self.delete(self.block)
            self.create(self.block)

    def change_shape(self,event):
        self.block.rotate()
        self.delete(self.block)
        self.create(self.block)

    def move_down(self):
        self.span = 0.2
        while Rule.can_down(self.block):
            self.block.down()
            self.delete(self.block)
            self.create(self.block)
            time.sleep(self.span)
            self.root.update()
        self.record(self.block)
        self.clear_full_row()

    @staticmethod
    def record(block):
        for i in range(len(block)):
            _recorder[block[i]] = block.body[i]

    def clear_full_row(self):
        rows = [self.block[i][1] for i in range(len(self.block))]
        rows.sort()
        for row in rows:
            if Rule.full_row(row):
                _recorder.clear_row(row,self.canvas)
                self.scorer + 100
        self.scorer + 10

    def accelerate(self,event):
        self.span = 0.1


class Recorder:

    container = np.zeros((30,20))

    def __setitem__(self, key, value):
        x, y = key[1] // 20, key[0] // 20
        self.container[x, y] = value

    def __getitem__(self, item):
        x, y = item[1] // 20, item[0] // 20
        return self.container[x, y]

    def __contains__(self, item):
        x, y = item[1] // 20, item[0] // 20
        return self.container[x, y]!= 0

    def items_in_row(self,x):
        row  = x // 20
        i = 0
        for j in range(20):
            i = i+1 if self.container[row,j]!= 0 else i
        return i

    def clear_row(self,x,canvas):
        row = x // 20
        for item in self.container[row,:]:
            item = int(item)
            canvas.delete(item)
        for item in self.container[:row][self.container[:row]!=0]:
            item = int(item)
            canvas.move(item,0,20)
        self.container[1:row + 1] = self.container[:row]


class Scorer:

    def __init__(self,canvas):
        self.score = 0
        self.win = canvas
        self.show_score()

    def show_score(self):
        self.text = self.win.create_text(500, 300, text=f"Current Score:{self.score}")

    def __add__(self, other):
        self.score += other
        self.win.delete(self.text)
        self.show_score()

    def __repr__(self):
        return str(self.score)


Blocks = [VerticalBlock,TBlock,SquareBlock,LRightBlock,
          LLeftBlock,ZBlock,ZMirrorBlock]

_recorder = Recorder()


class Rule:

    @staticmethod
    def can_down(block):
        for i in range(len(block)):
            if block[i][1] >= 580:
                return False
            elif (block[i][0], block[i][1]+20) in _recorder:
                return False
        return True

    @staticmethod
    def can_right(block):
        for i in range(len(block)):
            if block[i][0] >360:
                return False
            elif (block[i][0]+20, block[i][1]) in _recorder:
                return False
        return True

    @staticmethod
    def can_left(block):
        for i in range(len(block)):
            if block[i][0]<20:
                return False
            elif (block[i][0]-20, block[i][1]) in _recorder:
                return False
        return True

    @staticmethod
    def alive():
        return _recorder.items_in_row(0) == 0

    @staticmethod
    def full_row(y):
        return _recorder.items_in_row(y) == 20


if __name__=="__main__":
    root = Tk()
    block = np.random.choice(Blocks)
    with Handler(root) as handler:
        while Rule.alive():
            handler.create_block(block)
            next_block = np.random.choice(Blocks)
            handler.show(next_block)
            handler.move_down()
            block = next_block

在这里插入图片描述
-------------------2019-5-15更新

  1. 增加了进入游戏时的欢迎界面;
  2. 丰富了主界面;
  3. 修复了方块旋转时的一个BUG,增加了对可旋转条件的判断;
  4. 修改了加速键设置,由原来的按一次就一直加速变为长按加速,释放恢复原样。
"""
1.本程序开发环境为python3.7,用其他版本python2.X运行
需要修改程序

2.本程序依赖于第三方库numpy,如果没有需要自行安装
"""

from tkinter import *
from numpy import mat
import numpy as np
import time



class Block:

    coords = None
    speed = 20

    def right(self):
        translation = mat([[1,0],[1,0],[1,0],[1,0]])*self.speed
        self.coords +=translation

    def left(self):
        translation = mat([[1, 0], [1, 0], [1, 0], [1, 0]]) * self.speed
        self.coords -= translation

    def down(self):
        translation = mat([[0, 1], [0, 1], [0, 1], [0, 1]]) * self.speed
        self.coords += translation

    def rotate(self):
        translation = mat([[0,1],[-1,0]])
        core = self.coords[1]
        for i in range(len(self)):
            self.coords[i] = (self.coords[i]-core)*translation + core

    def add_body(self,body):
        self.body = body

    def __getitem__(self, item):
        return self.coords[item].tolist()[0]

    def __len__(self):
        return self.coords.shape[0]


class VerticalBlock(Block):

    _show = [[500, 40], [500, 60], [500, 80], [500, 100]]

    def __init__(self):
        self.coords = mat([[200,0],[200,20],[200,40],[200,60]])


class TBlock(Block):

    _show = [[480, 40], [500, 40], [500, 60], [520, 40]]

    def __init__(self):
        self.coords = mat([[180,0],[200,0],[200,20],[220,0]])


class SquareBlock(Block):

    _show = [[480, 40], [480, 60], [500, 40], [500, 60]]

    def __init__(self):
        self.coords = mat([[180,0],[180,20],[200,0],[200,20]])


class LRightBlock(Block):

    _show = [[480, 40], [500, 40], [520, 60], [520, 40]]

    def __init__(self):
        self.coords = mat([[180,0],[200,0],[220,20],[220,0]])


class LLeftBlock(Block):

    _show = [[480, 40], [500, 40], [480, 60], [520, 40]]

    def __init__(self):
        self.coords = mat([[180,0],[200,0],[180,20],[220,0]])


class ZBlock(Block):

    _show = [[480,40], [500,40], [500, 60], [520,60]]

    def __init__(self):
        self.coords = mat([[180,0],[200,0],[200,20],[220,20]])


class ZMirrorBlock(Block):

    _show = [[480, 60], [500, 60], [500, 40], [520, 40]]

    def __init__(self):
        self.coords = mat([[180,20],[200,20],[200,0],[220,0]])


class Recorder:

    container = np.zeros((30,20))

    def __setitem__(self, key, value):
        if isinstance(key,tuple) or isinstance(key,list):
            x = key[1] // 20
            y = key[0] // 20
            self.container[x, y] = value
        elif isinstance(key,int):
            row = key//20
            self.container[row] = value
        else:
            a = key.start//20 if key.start!=None else None
            b = key.stop//20 if key.stop!=None else None
            self.container[a:b] = value

    def __getitem__(self, item):
        if isinstance(item,tuple):
            x = item[1] // 20
            y = item[0] // 20
            return self.container[x, y]
        elif isinstance(item,int):
            row = item//20
            return self.container[row]
        else:
            a = item.start//20 if item.start!=None else None
            b = item.stop//20 if item.stop!=None else None
            return self.container[a:b]

    def __contains__(self, item):
        x, y = item[1] // 20, item[0] // 20
        return self.container[x, y]!= 0

    def items_in_row(self,x):
        row  = x // 20
        i = 0
        for j in range(20):
            i = i+1 if self.container[row,j]!= 0 else i
        return i

    def __delitem__(self, key):
        row = key//20
        self.container[1:row + 1] = self.container[:row]


class Scorer:

    def __init__(self,canvas):
        self.score = 0
        self.win = canvas
        self.show_score()

    def show_score(self):
        self.text = self.win.create_text(510, 180, text=f"{self.score}",font=('time',15))

    def __add__(self, other):
        self.score += other
        self.win.delete(self.text)
        self.show_score()

    def __repr__(self):
        return str(self.score)


Blocks = [VerticalBlock,TBlock,SquareBlock,LRightBlock,
          LLeftBlock,ZBlock,ZMirrorBlock]

_recorder = Recorder()



class Handler:

    def __init__(self,root):
        self.span = 0.2
        self.root = root
        root.bind("<Left>", self.move_left)
        root.bind("<Right>", self.move_right)
        root.bind("<Up>", self.change_shape)
        root.bind("<KeyPress-Down>", self.accelerate)
        root.bind("<KeyRelease-Down>",self.recover)
        root.focus_set()

    def __enter__(self):
        self.enter_interface()
        self.main_interface()
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.canvas.create_text(200, 300, text="GAME OVER!", fill='darkorchid',font=('Couried',30))
        mainloop()

    def enter_interface(self):
        self.canvas = Canvas(root, height=600, width=600)
        self.canvas.create_rectangle(0, 0, 600, 600, fill='black')
        text = open('./note.txt').read()
        self.canvas.create_text(300, 200, text=text, fill='white')
        self.canvas.create_text(300, 500, text='Continue', fill='white', font=('Time', 14))
        self.canvas.bind('<Button-1>', self.enter_interface_destroy)
        self.canvas.pack()
        root.wait_window(self.canvas)

    def enter_interface_destroy(self,event):
        if event.x<350 and event.x>250 and event.y>480 and event.y<520:
            self.canvas.destroy()

    def main_interface(self):
        self.canvas = Canvas(root, height=600, width=600)
        self.scorer = Scorer(self.canvas)
        self.canvas.create_rectangle(0, 0, 400, 600, fill='black')
        self.canvas.create_text(510, 20, text='The Next:', font=('Time', 15))
        self.canvas.create_text(510, 150, text='Current Score:', font=('time', 15))
        text = "Create on \r\n2019/5/15\r\nauthor:\r\nMr Lu"
        self.canvas.create_text(510, 400, text=text, fill='yellow', font=('time', 15))
        self.canvas.pack()

    def create_block(self,name):
        self.block = name()
        self.create(self.block)

    def paint(self, x, y):
        return self.canvas.create_rectangle(x, y, x + 20, y + 20, fill=self.color, width=3)

    def create(self,block):
        self.color = np.random.choice(['coral','skyblue','lightgreen'])
        block.add_body([self.paint(*block[i]) for i in range(len(block))])

    def update(self,block):
        for s in block.body:
            self.canvas.delete(s)
        block.add_body([self.paint(*block[i]) for i in range(len(block))])

    def move(self,block,v_x,v_y):
        for s in block.body:
            self.canvas.move(s, v_x, v_y)

    def show(self,block):
        if hasattr(self,'_show'):
            for item in self._show:
                self.canvas.delete(item)
        self._show = [self.paint(*item) for item in block._show]

    def move_right(self,event):
        if Rule.can_right(self.block):
            self.block.right()
            self.move(self.block, 20, 0)

    def move_left(self,event):
        if Rule.can_left(self.block):
            self.block.left()
            self.move(self.block, -20, 0)

    def change_shape(self,event):
        if Rule.can_rotate(self.block):
            self.block.rotate()
            self.update(self.block)

    def move_down(self):
        while Rule.can_down(self.block):
            self.block.down()
            self.move(self.block, 0, 20)
            time.sleep(self.span)
            self.root.update()
        self.record(self.block)
        self.clear_full_row()

    @staticmethod
    def record(block):
        for i in range(len(block)):
            _recorder[block[i]] = block.body[i]

    def clear_full_row(self):
        rows = [self.block[i][1] for i in range(len(self.block))]
        rows.sort()
        rows = set(rows)
        for row in rows:
            if Rule.full_row(row):
                self.clear_row(row)
                self.scorer + 100
        self.scorer + 10

    def clear_row(self,row):
        for item in _recorder[row]:
            item = int(item)
            self.canvas.delete(item)
        for item in _recorder[:row][_recorder[:row]!=0]:
            item = int(item)
            self.canvas.move(item,0,20)
        del _recorder[row]

    def accelerate(self,event):
        self.span = 0.1

    def recover(self,event):
        self.span = 0.2


class Rule:

    @staticmethod
    def can_down(block):
        for i in range(len(block)):
            if block[i][1] >= 580:
                return False
            elif (block[i][0], block[i][1]+20) in _recorder:
                return False
        return True

    @staticmethod
    def can_right(block):
        for i in range(len(block)):
            if block[i][0] >360:
                return False
            elif (block[i][0]+20, block[i][1]) in _recorder:
                return False
        return True

    @staticmethod
    def can_left(block):
        for i in range(len(block)):
            if block[i][0]<20:
                return False
            elif (block[i][0]-20, block[i][1]) in _recorder:
                return False
        return True

    @staticmethod
    def can_rotate(block):
        core = block[1]
        for i in range(len(block)):
            x = -block[i][1]+core[1]+core[0]
            y = block[i][0]-core[0]+core[1]
            if x < 0 or x > 380 or y > 580:
                return False
            elif (x, y) in _recorder:
                return False
        return True

    @staticmethod
    def alive():
        return _recorder.items_in_row(0) == 0

    @staticmethod
    def full_row(y):
        return _recorder.items_in_row(y) == 20


if __name__=="__main__":
    root = Tk()
    root.title("Tetris")
    root.resizable(width=False, height=False)
    block = np.random.choice(Blocks)
    with Handler(root) as handler:
        while Rule.alive():
            handler.create_block(block)
            next_block = np.random.choice(Blocks)
            handler.show(next_block)
            handler.move_down()
            block = next_block

欢迎界面
在这里插入图片描述
主界面
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值