《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