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 getopt模块处理命令行选项实例
May 13 Python
Python实现的简单hangman游戏实例
Jun 28 Python
Tensorflow简单验证码识别应用
May 25 Python
python用pickle模块实现“增删改查”的简易功能
Jun 07 Python
python 删除列表里所有空格项的方法总结
Apr 18 Python
pytorch 数据集图片显示方法
Jul 26 Python
python将.ppm格式图片转换成.jpg格式文件的方法
Oct 27 Python
Python 单元测试(unittest)的使用小结
Nov 14 Python
python将txt等文件中的数据读为numpy数组的方法
Dec 22 Python
钉钉群自定义机器人消息Python封装的实例
Feb 20 Python
python循环嵌套的多种使用方法解析
Nov 29 Python
python tkinter 设置窗口大小不可缩放实例
Mar 04 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
日本十大科幻动漫 宇宙骑士垫底,第一已成经典
2020/03/04 日漫
不用数据库的多用户文件自由上传投票系统(3)
2006/10/09 PHP
PHP中MD5函数使用实例代码
2008/06/07 PHP
ThinkPHP删除栏目(实现批量删除栏目)
2017/06/21 PHP
PHP编程中的Session阻塞问题与解决方法分析
2017/08/07 PHP
由prototype_1.3.1进入javascript殿堂-类的初探
2006/11/06 Javascript
使Ext的Template可以解析二层的json数据的方法
2007/12/22 Javascript
xml 封装与解析(javascript和C#中)
2009/07/26 Javascript
javascript实现点击后变换按钮显示文字的方法
2015/05/13 Javascript
javascript实现模拟时钟的方法
2015/05/13 Javascript
iframe跨域通信封装详解
2015/08/11 Javascript
基于JavaScript实现跳转提示页面
2016/09/24 Javascript
jQuery中 $ 符号的冲突问题及解决方案
2016/11/04 Javascript
Angular4学习之Angular CLI的安装与使用教程
2018/01/04 Javascript
JS 中可以提升幸福度的小技巧(可以识别更多另类写法)
2018/07/28 Javascript
继承行为在 ES5 与 ES6 中的区别详解
2019/12/24 Javascript
JavaScript 替换所有匹配内容及正则替换方法
2020/02/12 Javascript
vue Treeselect 树形下拉框:获取选中节点的ids和lables操作
2020/08/15 Javascript
vue3 watch和watchEffect的使用以及有哪些区别
2021/01/26 Vue.js
python 图片验证码代码分享
2012/07/04 Python
Pyramid添加Middleware的方法实例
2013/11/27 Python
程序员写Python时的5个坏习惯,你有几条?
2018/11/26 Python
对Python3 goto 语句的使用方法详解
2019/02/16 Python
python设置环境变量的原因和方法
2019/06/24 Python
python的一些加密方法及python 加密模块
2019/07/11 Python
python  logging日志打印过程解析
2019/10/22 Python
使用pyecharts1.7进行简单的可视化大全
2020/05/17 Python
Pytorch 使用 nii数据做输入数据的操作
2020/05/26 Python
约瑟夫·特纳男装:Joseph Turner
2017/10/10 全球购物
惠普香港官方商店:HP香港
2019/04/30 全球购物
Happy Plugs官网:瑞典无线耳机品牌
2020/07/16 全球购物
英文求职信写作小建议
2014/02/16 职场文书
消防安全宣传标语
2014/06/07 职场文书
经济贸易系求职信
2014/08/04 职场文书
银行转正自我鉴定
2014/09/29 职场文书
优秀英文求职信范文
2015/03/19 职场文书