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实现抓取网页生成Excel文件的方法示例
Aug 05 Python
Python编程实现正则删除命令功能
Aug 30 Python
遗传算法python版
Mar 19 Python
如何使用 Pylint 来规范 Python 代码风格(来自IBM)
Apr 06 Python
python中plot实现即时数据动态显示方法
Jun 22 Python
Python for循环中的陷阱详解
Jul 13 Python
在windows下使用python进行串口通讯的方法
Jul 02 Python
python tkinter组件摆放方式详解
Sep 16 Python
简单了解python中的与或非运算
Sep 18 Python
浅谈pandas.cut与pandas.qcut的使用方法及区别
Mar 03 Python
Python读写操作csv和excle文件代码实例
Mar 16 Python
在PyCharm中安装PaddlePaddle的方法
Feb 05 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数字格式化
2006/12/06 PHP
PHP常用函数小技巧
2008/09/11 PHP
php面向对象全攻略 (九)访问类型
2009/09/30 PHP
php的curl封装类用法实例
2014/11/07 PHP
php实现读取和写入tab分割的文件
2015/06/01 PHP
php防止sql注入的方法详解
2017/02/20 PHP
php生成随机数/生成随机字符串的方法小结【5种方法】
2020/05/27 PHP
JavaScript 全角转半角部分
2009/10/28 Javascript
js 关键词高亮(根据ID/tag高亮关键字)案例介绍
2013/01/21 Javascript
深入理解JavaScript高级之词法作用域和作用域链
2013/12/10 Javascript
高效Web开发的10个jQuery代码片段
2016/07/22 Javascript
KnockoutJS 3.X API 第四章之表单value绑定
2016/10/10 Javascript
vue.js 初体验之Chrome 插件开发实录
2017/05/13 Javascript
js实现QQ面板拖拽效果(慕课网DOM事件探秘)(全)
2017/09/19 Javascript
vue实现提示保存后退出的方法
2018/03/15 Javascript
实现一个 Vue 吸顶锚点组件方法
2019/07/10 Javascript
vue路由传参的基本实现方式小结【三种方式】
2020/02/05 Javascript
[00:43]FTP典藏礼包 DOTA2三大英雄霸气新套装
2014/03/21 DOTA
Python对小数进行除法运算的正确方法示例
2014/08/25 Python
Python连接PostgreSQL数据库的方法
2016/11/28 Python
python实现蒙特卡罗方法教程
2019/01/28 Python
使用Python画股票的K线图的方法步骤
2019/06/28 Python
opencv导入头文件时报错#include的解决方法
2019/07/31 Python
python selenium循环登陆网站的实现
2019/11/04 Python
解决pycharm最左侧Tool Buttons显示不全的问题
2019/12/17 Python
python删除某个目录文件夹的方法
2020/05/26 Python
Python使用eval函数执行动态标表达式过程详解
2020/10/17 Python
移动Web—CSS为Retina屏幕替换更高质量的图片
2012/12/24 HTML / CSS
什么是虚拟内存?虚拟内存有什么优势?
2012/02/19 面试题
解释一下ruby中的特殊方法与特殊类
2013/02/26 面试题
新闻专业毕业生英文求职信
2014/03/19 职场文书
幼儿园感恩节活动方案
2014/10/06 职场文书
2014年班级工作总结
2014/11/14 职场文书
小学班主任经验交流材料
2014/12/16 职场文书
社区活动总结
2015/02/04 职场文书
我的生日感言
2015/08/03 职场文书