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 中的列表解析和生成表达式
Mar 10 Python
Python实现windows下模拟按键和鼠标点击的方法
Mar 13 Python
python实现获取客户机上指定文件并传输到服务器的方法
Mar 16 Python
python中list常用操作实例详解
Jun 03 Python
将Emacs打造成强大的Python代码编辑工具
Nov 20 Python
python与C互相调用的方法详解
Jul 14 Python
Python走楼梯问题解决方法示例
Jul 25 Python
python 对多个csv文件分别进行处理的方法
Jan 07 Python
Python中那些 Pythonic的写法详解
Jul 02 Python
python分割一个文本为多个文本的方法
Jul 22 Python
重写django的model下的objects模型管理器方式
May 15 Python
python 爬虫如何正确的使用cookie
Oct 27 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 网页游戏开发入门教程一(webgame+design)
2009/10/26 PHP
深入php-fpm的两种进程管理模式详解
2013/06/03 PHP
PHP+Ajax实现验证码的实时验证
2016/07/20 PHP
php处理单文件、多文件上传代码分享
2016/08/24 PHP
PHP正则匹配到2个字符串之间的内容方法
2018/12/24 PHP
JavaScript中的16进制字符(改进)
2011/11/21 Javascript
关于query Javascript CSS Selector engine
2013/04/12 Javascript
Jquery模仿Baidu、Google搜索时自动补充搜索结果提示
2013/12/26 Javascript
javascript定义变量时带var与不带var的区别分析
2015/01/12 Javascript
Javascript基础教程之数据类型转换
2015/01/18 Javascript
Bootstrap BootstrapDialog使用详解
2017/02/17 Javascript
详解Vue.js组件可复用性的混合(mixin)方式和自定义指令
2017/09/06 Javascript
Angular4实现图片上传预览路径不安全的问题解决
2017/12/25 Javascript
微信 jssdk 签名错误invalid signature的解决方法
2019/01/14 Javascript
websocket4.0+typescript 实现热更新的方法
2019/08/14 Javascript
Vue数字输入框组件的使用方法
2019/10/19 Javascript
vue data引入本地图片的两种方式小结
2019/11/13 Javascript
Angular短信模板校验代码
2020/09/23 Javascript
从零学python系列之教你如何根据图片生成字符画
2014/05/23 Python
在Python上基于Markov链生成伪随机文本的教程
2015/04/17 Python
Python实现模拟登录及表单提交的方法
2015/07/25 Python
浅谈Python爬取网页的编码处理
2016/11/04 Python
解决python 无法加载downsample模型的问题
2018/10/25 Python
python标记语句块使用方法总结
2019/08/05 Python
python3 实现的对象与json相互转换操作示例
2019/08/17 Python
python多线程实现TCP服务端
2019/09/03 Python
Python爬虫获取页面所有URL链接过程详解
2020/06/04 Python
python里的单引号和双引号的有什么作用
2020/06/17 Python
几个常见的软件测试问题
2016/09/07 面试题
公务员个人自我评价分享
2013/11/06 职场文书
廉洁教育学习材料
2014/05/19 职场文书
会计学专业自荐信
2014/06/25 职场文书
大学生安全责任书
2014/07/25 职场文书
2016幼儿园毕业感言
2015/12/08 职场文书
SQL之各种join小结详细讲解
2021/08/04 MySQL
Win11快速关闭所有广告推荐
2022/04/19 数码科技