python如何写个俄罗斯方块

作者:Python技术 时间:2022-07-23 19:49:38 

俄罗斯方块是俄罗斯人发明的一款休闲类的小游戏,这款小游戏可以说是很多人童年的主打电子游戏了,本文我们使用 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()

看一下效果:

python如何写个俄罗斯方块

分数的显示就是利用上面 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

python如何写个俄罗斯方块

我们知道方块是不断自动下落的,因此需要一个计时器来控制,主要实现代码如下:


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()

我们来看一下最终实现效果:

python如何写个俄罗斯方块

是不是有内味了。

总结

本文我们使用 PyQt5 库写了一个俄罗斯方块小游戏,如果你对 PyQt5 库感兴趣的话,可以尝试使用一下。

示例代码:py-tetris

来源:http://www.justdopython.com/2020/05/24/tetris/?utm_source=tuicool&utm_medium=referral

标签:python,俄罗斯方块
0
投稿

猜你喜欢

  • 有关JS中Event对象的几点总结

    2009-03-06 12:36:00
  • 提升Python程序运行效率的6个方法

    2023-08-23 08:36:46
  • WEB页面工具之语言XML的定义

    2008-05-29 11:29:00
  • 请给PNG8一个机会

    2009-09-16 14:22:00
  • Ajax的错误处理机制探讨

    2007-09-07 09:53:00
  • 如何用表单在线建立目录?

    2010-06-16 09:49:00
  • 当设计师遭遇HTML5

    2011-08-05 18:59:53
  • 思考如何提高交互设计水平?

    2009-12-08 12:18:00
  • 超半数中文网页一年内将“消失”

    2008-03-08 12:49:00
  • js实现单机双人象棋设计分析

    2008-05-20 12:57:00
  • python 爬取疫情数据的源码

    2022-05-22 13:21:54
  • 解析PHP中一些可能会被忽略的问题

    2023-09-05 14:07:37
  • python解析yaml文件过程详解

    2023-09-30 13:13:51
  • asp的access数据库备份 压缩 恢复及清理数据库函数

    2008-10-31 12:36:00
  • 在 Python 应用中使用 MongoDB的方法

    2023-09-13 21:53:11
  • sqlserver 导出插入脚本代码

    2012-01-29 18:04:43
  • 使用css2.1实现多重背景、多重边框效果[译]

    2010-08-23 16:32:00
  • iframe全跨域高度自适应解决方案

    2008-12-21 16:16:00
  • 如何用SA-FileUp上传一个单纯的HTML文件?

    2010-05-18 18:29:00
  • php输出xml必须header的解决方法

    2023-09-11 20:00:16
  • asp之家 网络编程 m.aspxhome.com