python如何写个俄罗斯方块


Posted in Python onNovember 06, 2020

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

以上就是python写个俄罗斯方块的详细内容,更多关于python 俄罗斯方块的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
python实现调用其他python脚本的方法
Oct 05 Python
Python中使用Flask、MongoDB搭建简易图片服务器
Feb 04 Python
python爬虫入门教程--快速理解HTTP协议(一)
May 25 Python
Python应用库大全总结
May 30 Python
Python 200行代码实现一个滑动验证码过程详解
Jul 11 Python
python tkinter窗口最大化的实现
Jul 15 Python
Django错误:TypeError at / 'bool' object is not callable解决
Aug 16 Python
Python全栈之列表数据类型详解
Oct 01 Python
Python 迭代,for...in遍历,迭代原理与应用示例
Oct 12 Python
Django User 模块之 AbstractUser 扩展详解
Mar 11 Python
Python多进程multiprocessing、进程池用法实例分析
Mar 24 Python
Python动态导入模块:__import__、importlib、动态导入的使用场景实例分析
Mar 30 Python
基于Python实现全自动下载抖音视频
Nov 06 #Python
Python3读写ini配置文件的示例
Nov 06 #Python
Python Serial串口基本操作(收发数据)
Nov 06 #Python
python基于exchange函数发送邮件过程详解
Nov 06 #Python
Python Unittest原理及基本使用方法
Nov 06 #Python
python中的yield from语法快速学习
Nov 06 #Python
Python通过字典映射函数实现switch
Nov 06 #Python
You might like
php获取后台Job管理的实现代码
2011/06/10 PHP
PHP中对缓冲区的控制实现代码
2013/09/29 PHP
php发送post请求的三种方法
2014/02/11 PHP
php实现网站顶踩功能的完整前端代码
2015/07/19 PHP
PHP微信网页授权的配置文件操作分析
2019/05/29 PHP
php正则表达式使用方法整理集合
2020/01/31 PHP
Aster vs KG BO3 第三场2.19
2021/03/10 DOTA
JavaScript中为元素加上name属性的方法
2011/05/09 Javascript
javascript实现控制文字大中小显示
2015/04/28 Javascript
jquery实现倒计时功能
2015/12/28 Javascript
实例讲解避免javascript冲突的方法
2016/01/03 Javascript
深入理解jQuery之事件移除
2016/06/02 Javascript
浅谈Node.js:Buffer模块
2016/12/05 Javascript
jquery实现刷新随机变化样式特效(tag标签样式)
2017/02/03 Javascript
JavaScript实现获取远程的html到当前页面中
2017/03/26 Javascript
knockoutjs模板实现树形结构列表
2017/07/31 Javascript
Vee-Validate的使用方法详解
2017/09/22 Javascript
vue组件jsx语法的具体使用
2018/05/21 Javascript
详解性能更优越的小程序图片懒加载方式
2018/07/18 Javascript
解决vue单页面修改样式无法覆盖问题
2019/08/05 Javascript
layer.msg()去掉默认时间,实现手动关闭的方法
2019/09/12 Javascript
layui table 获取分页 limit的方法
2019/09/20 Javascript
vue+vant-UI框架实现购物车的复选框全选和反选功能
2019/11/05 Javascript
用Python实现筛选文件脚本的方法
2018/10/27 Python
如何通过python画loss曲线的方法
2019/06/26 Python
学python最电脑配置有要求么
2020/07/05 Python
python list的index()和find()的实现
2020/11/16 Python
上班睡觉检讨书
2014/01/09 职场文书
手机促销活动方案
2014/02/05 职场文书
更夫岗位责任制
2014/02/11 职场文书
简单的离婚协议书范本
2014/11/16 职场文书
淘宝客服专员岗位职责
2015/04/07 职场文书
特此通知格式
2015/04/27 职场文书
工作转正自我鉴定范文
2019/06/21 职场文书
导游词之岳阳楼
2019/09/25 职场文书
python实现的web监控系统
2021/04/27 Python