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进行行为驱动开发的入门教程
Apr 23 Python
Python的Flask框架中使用Flask-Migrate扩展迁移数据库的教程
Jun 14 Python
python win32 简单操作方法
May 25 Python
对numpy的array和python中自带的list之间相互转化详解
Apr 13 Python
python3爬虫之设计签名小程序
Jun 19 Python
10分钟教你用python动画演示深度优先算法搜寻逃出迷宫的路径
Aug 12 Python
Python FTP文件定时自动下载实现过程解析
Nov 12 Python
Python迭代器模块itertools使用原理解析
Dec 11 Python
Jupyter notebook 远程配置及SSL加密教程
Apr 14 Python
Django REST Swagger实现指定api参数
Jul 07 Python
用OpenCV进行年龄和性别检测的实现示例
Jan 29 Python
Python如何使用神经网络进行简单文本分类
Feb 25 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
DISCUZ 论坛管理员密码忘记的解决方法
2009/05/14 PHP
php数组函数序列之end() - 移动数组内部指针到最后一个元素,并返回该元素的值
2011/10/31 PHP
PHP中图片等比缩放的实例
2013/03/24 PHP
CI框架的安全性分析
2016/05/18 PHP
基于jQuery试卷自动排版系统
2010/07/18 Javascript
javascript showModalDialog 内跳转页面的问题
2010/11/25 Javascript
JQuery 获取json数据$.getJSON方法的实例代码
2013/08/02 Javascript
javascript页面渲染速度测试脚本分享
2014/04/15 Javascript
JavaScript中的方法重载实例
2015/03/16 Javascript
jQuery实现自定义事件的方法
2015/04/17 Javascript
jQuery 遍历函数详解
2015/07/05 Javascript
jQuery实现页面顶部下拉广告
2016/12/30 Javascript
JS使用插件cryptojs进行加密解密数据实例
2017/05/11 Javascript
JavaScript递归函数解“汉诺塔”算法代码解析
2018/07/05 Javascript
Vue的生命周期操作示例
2019/09/17 Javascript
在Vue项目中,防止页面被缩放和放大示例
2019/10/28 Javascript
js new Date()实例测试
2019/10/31 Javascript
微信小程序开发(二):页面跳转并传参操作示例
2020/06/01 Javascript
SpringBoot+Vue开发之Login校验规则、实现登录和重置事件
2020/10/19 Javascript
Python中用Ctrl+C终止多线程程序的问题解决
2013/03/30 Python
Python简单读写Xls格式文档的方法示例
2018/08/17 Python
python中单例常用的几种实现方法总结
2018/10/13 Python
python numpy数组的索引和切片的操作方法
2018/10/20 Python
python交互界面的退出方法
2019/02/16 Python
Windows下Pycharm远程连接虚拟机中Centos下的Python环境(图文教程详解)
2020/03/19 Python
阳光体育:Sunny Sports(购买露营和远足设备)
2018/08/07 全球购物
客户经理岗位职责
2013/12/08 职场文书
市场开发与营销专业求职信范文
2014/05/01 职场文书
机械工程及其自动化专业求职信
2014/08/08 职场文书
执法作风整顿剖析材料
2014/10/11 职场文书
学生会辞职信
2015/03/02 职场文书
汶川大地震感悟
2015/08/10 职场文书
2016年社区中秋节活动总结
2016/04/05 职场文书
蓝天保卫战收官在即 :15行业将开展环保分级评价
2019/07/19 职场文书
Python中快速掌握Data Frame的常用操作
2021/03/31 Python
Python实现Excel文件的合并(以新冠疫情数据为例)
2022/03/20 Python