前言
本文的文字及圖片來源於網絡,僅供學習、交流使用,不具有任何商業用途,版權歸原作者所有,如有問題請及時聯繫我們以作處理。
作者:python技術
PS:如有需要Python學習資料的小夥伴可以加點擊下方鏈接自行獲取http://t.cn/A6Zvjdun
俄羅斯方塊是俄羅斯人發明的一款休閒類的小遊戲,這款小遊戲可以說是很多人童年的主打電子遊戲了,本文我們使用 Python 來實現這款小遊戲。
遊戲的基本規則是:移動、旋轉和擺放遊戲自動輸出的各種方塊,使之排列成完整的一行或多行並且消除得分。
實現
我們實現俄羅斯方塊,主要用到的是 PyQt5 庫,安裝使用 pip install PyQt5 即可,遊戲的組成比較簡單,主要包括:主界面、各種方塊和計分板,下面我們來看一下具體實現。
首先,我們來畫一個主界面,主要實現代碼如下:
class MainBoard(QFrame):
msg = pyqtSignal(str)
BoardWidth = 10
BoardHeight = 20
Speed = 300
def __init__(self, parent):
super().__init__(parent)
self.initBoard()
def initBoard(self):
self.timer = QBasicTimer()
self.isWaitingAfterLine = False
self.curX = 0
self.curY = 0
self.numLinesRemoved = 0
self.board = []
self.setFocusPolicy(Qt.StrongFocus)
self.isStarted = False
self.isPaused = False
self.clearBoard()
看一下效果:
分數的顯示就是利用上面 msg 的 emit() 方法實現的。
我們接着畫各種方塊,方塊的形狀主要包括:T、Z、L、I、O 等,主要實現代碼如下:
class ShapeForm(object):
NoShape = 0
ZShape = 1
SShape = 2
LineShape = 3
TShape = 4
SquareShape = 5
LShape = 6
MirroredLShape = 7
class Shape(object):
coordsTable = (
((0, 0), (0, 0), (0, 0), (0, 0)),
((0, -1), (0, 0), (-1, 0), (-1, 1)),
((0, -1), (0, 0), (1, 0), (1, 1)),
((0, -1), (0, 0), (0, 1), (0, 2)),
((-1, 0), (0, 0), (1, 0), (0, 1)),
((0, 0), (1, 0), (0, 1), (1, 1)),
((-1, -1), (0, -1), (0, 0), (0, 1)),
((1, -1), (0, -1), (0, 0), (0, 1))
)
def __init__(self):
self.coords = [[0,0] for i in range(4)]
self.pieceShape = ShapeForm.NoShape
self.setShape(ShapeForm.NoShape)
def shape(self):
return self.pieceShape
def setShape(self, shape):
table = Shape.coordsTable[shape]
for i in range(4):
for j in range(2):
self.coords[i][j] = table[i][j]
self.pieceShape = shape
看一下效果:
我們知道方塊是不斷自動下落的,因此需要一個計時器來控制,主要實現代碼如下:
def timerEvent(self, event):
if event.timerId() == self.timer.timerId():
if self.isWaitingAfterLine:
self.isWaitingAfterLine = False
self.newPiece()
else:
self.oneLineDown()
else:
super(MainBoard, self).timerEvent(event)
在方塊下落的過程中,我們需要通過鍵盤來控制方塊的形狀以及左右移動,因此,我們需要一個按鍵事件來控制它,主要實現代碼如下:
def keyPressEvent(self, event):
if not self.isStarted or self.curPiece.shape() == ShapeForm.NoShape:
super(MainBoard, self).keyPressEvent(event)
return
key = event.key()
if key == Qt.Key_P:
self.pause()
return
if self.isPaused:
return
elif key == Qt.Key_Left:
self.tryMove(self.curPiece, self.curX - 1, self.curY)
elif key == Qt.Key_Right:
self.tryMove(self.curPiece, self.curX + 1, self.curY)
elif key == Qt.Key_Down:
self.tryMove(self.curPiece.rotateRight(), self.curX, self.curY)
elif key == Qt.Key_Up:
self.tryMove(self.curPiece.rotateLeft(), self.curX, self.curY)
elif key == Qt.Key_Space:
self.dropDown()
elif key == Qt.Key_D:
self.oneLineDown()
else:
super(MainBoard, self).keyPressEvent(event)
當方塊落到底部後,需要來檢測是否有構成一條直線的,因此我們需要有一個方法來找到所有能消除的行並且消除它們,主要實現代碼如下:
def removeFullLines(self):
numFullLines = 0
rowsToRemove = []
for i in range(MainBoard.BoardHeight):
n = 0
for j in range(MainBoard.BoardWidth):
if not self.shapeAt(j, i) == ShapeForm.NoShape:
n = n + 1
if n == 10:
rowsToRemove.append(i)
rowsToRemove.reverse()
for m in rowsToRemove:
for k in range(m, MainBoard.BoardHeight):
for l in range(MainBoard.BoardWidth):
self.setShapeAt(l, k, self.shapeAt(l, k + 1))
numFullLines = numFullLines + len(rowsToRemove)
if numFullLines > 0:
self.numLinesRemoved = self.numLinesRemoved + numFullLines
self.msg.emit(str(self.numLinesRemoved))
self.isWaitingAfterLine = True
self.curPiece.setShape(ShapeForm.NoShape)
self.update()
我們來看一下最終實現效果:
是不是有內味了。