《Python3编程实战Tetris机器人》python
游戏逻辑控制类,是界面与Tetris类之间的粘合者,接受界面的鼠标及键盘事件,操做Tetris类,实现游戏逻辑。单个方块的操做,在Tetris中已经实现,game类主要是实现消行算法、新方块的产生、游戏速度控制等。linux
消层算法简单的处理就是发现一行,消除一行。本项目使用一点技巧,先找出全部可消除行,把行号存入数组中,一次性消除。游戏速度的控制,使用定时器来实现,但发现python的定时器与其它语言有些差异,会不断产生新的定时器对象,开始感受有些不对劲,但也没有重视。后来确认,这会产生内存泄漏,后使用tkinter.after替换了。git
SCORES = (0,1,3,7,10) # 消层分值设定 STEPUPSCORE = 50 # 每增加50分,速度加快一个等级 STEPUPINTERVAL = 100 # 每增加一个等级,定时器间隔时间减小100毫秒
game.gameRunningStatusgithub
def start(self): self.gameRunningStatus = 1 self.gameSpeedInterval = 1000 # 初始游戏速度 self.gameSpeed = 1 # 游戏速度等级 self.gameLevels = 0 # 消层数 self.gameScores = 0 # 总得分 self.app.updateGameInfo(1,0,0) # 初始化界面信息 self.canvas.delete(ALL) # 清空游戏空间 self.nextCanvas.delete(ALL) # 下一方块空间清空 initGameRoom() # 初始化游戏空间数据 self.tetris = Tetris(self.canvas, 4, 0, random.randint(0,6)) # 随机生成第一个方块 for i in range(random.randint(0,4)): # 旋转随机次数,方块出场式 self.tetris.rotate() self.nextTetris = Tetris(self.nextCanvas, 1, 1, random.randint(0,6)) # 随机生成下一方块 for i in range(random.randint(0,4)): # 下一方块初始形态(随机) self.nextTetris.rotate() self.tick = Timer(self.gameSpeedInterval / 1000, self.tickoff) # 控制游戏速度定时器 self.tick.start()
游戏控制主要函数,在方块下落到底部后,进行消层、统计得分、速度等级断定、游戏是否结束断定以及将下一方块移入游戏空间并再生成一个方块显示在下一方块显示空间中。算法
def generateNext(self): cleanLevels = self.clearRows() # 统计可消除层数 if cleanLevels > 0: # 有可消层,计算分值 self.gameLevels += cleanLevels self.gameScores += SCORES[cleanLevels] if self.gameScores / STEPUPSCORE >= self.gameSpeed: self.gameSpeed += 1 self.gameSpeedInterval -= STEPUPINTERVAL self.app.updateGameInfo(self.gameSpeed, self.gameLevels, self.gameScores) self.tetris = Tetris(self.canvas, 4, 0, self.nextTetris.getTetrisShape()) # 复制nexTetris到游戏空间 for i in range(self.nextTetris.getRotateCount()): if not self.tetris.rotate(): break if self.tetris.canPlace(4, 0): # 断定游戏是否结束 self.nextCanvas.delete(ALL) # 游戏未结束,生成新的方块放入下一方块空间 self.nextTetris = Tetris(self.nextCanvas, 1, 1, random.randint(0,6)) for i in range(random.randint(0,4)): self.nextTetris.rotate() else: # 游戏结束 self.gameRunningStatus = 0 self.canvas.create_text(150, 200, text = "Game is over!", fill="white", font = "Times 28 italic bold") self.app.setStartButtonText("Start") print("game is over!")
clearRows函数查找能消除的层,将其消除,返回可消除层总数。编程
def clearRows(self): occupyLines = [] # 存储可消除层行号 h = 20 while h > 0: allOccupy = 0 for i in range(1, 11): if GameRoom[h][i]: allOccupy += 1 # block统计 if allOccupy == 10: # 行满 occupyLines.append(h) # 存储行号 elif allOccupy == 0: # 有一个空位,跳过些行 break h -= 1 if len(occupyLines) > 0: # 有可消层 self.doCleanRows(occupyLines) # 消除可消层 return len(occupyLines)
消层函数,根据clearRows函数统计的可消层行号,消除游戏空间的满行。算法的难点在于要同时控制两个变量,一个是从下到上遍历游戏空间,另外一方面要将满行以上的空间数据下移,下移的步长为已经消除的行数。canvas
def doCleanRows(self, lines): index = 0 # 存储已经消除了多少行 h = lines[index] # 满行行号数据 while h >= 0: # 只须要从最下面一满行开始便可 if index < len(lines) and h == lines[index]: # 找到一可消行 index += 1 # 已消行总数加1 for j in range(1, 11): GameRoom[h][j] = 0 # 游戏空间数据消行 for b in self.canvas.find_closest(\ # Canvas元件消除 j * BLOCKSIDEWIDTH - HALFBLOCKWIDTH, \ h * BLOCKSIDEWIDTH - HALFBLOCKWIDTH): self.canvas.delete(b) else: # 移动游戏空间数据 count = 0 # 空位统计,全空,能够提早结束循环 for j in range(1, 11): if GameRoom[h][j] == 1: count += 1 GameRoom[h + index][j] = GameRoom[h][j] # 注意index变量,这是移动步长,与已经消除行数有关 GameRoom[h][j] = 0 for b in self.canvas.find_closest(j * BLOCKSIDEWIDTH - HALFBLOCKWIDTH, h * BLOCKSIDEWIDTH - HALFBLOCKWIDTH): self.canvas.move(b, 0, index * BLOCKSIDEWIDTH) if count == 0: # 发现整行位全空,提早退出 break h -= 1
方块控制已经在Tetris类实现,在game类中,只是转发事件到当前方块便可。惟一多了一个moveDownEnd - 方块直落函数。segmentfault
def moveDownEnd(self): while self.moveDown(): # 循环下落,直到不能再落 pass
游戏速度控制实现很容易,只须要定时触发一次down函数就能够了。windows
def tickoff(self): if self.gameRunningStatus == 1: self.moveDown() self.tick = Timer(self.gameSpeedInterval / 1000, self.tickoff) self.tick.start()
定时器的使用会引入新线程,会出现资源冲突问题,下单将解决线程冲突。数组
https://gitee.com/zhoutk/ptetris 或 https://github.com/zhoutk/ptetris
1. install python3, git 2. git clone https://gitee.com/zhoutk/ptetris (or download and unzip source code) 3. cd ptetris 4. python3 tetris This project surpport windows, linux, macOs on linux, you must install tkinter first, use this command: sudo apt install python3-tk
已经实现了C++版,项目地址:
https://gitee.com/zhoutk/qtetris