本文主要介绍如何教你如何用python开发一个数字推送游戏。文章中有非常详细的代码示例,对喜欢玩游戏或者正在学习python游戏开发的朋友很有帮助。有需要的朋友可以参考一下。
目录
1、布局设计2、算法设计2.1创建并初始化数组2.2移动算法2.3是否成功检测算法3、实现3.1框架构建3.2数字方块实现3.3将数字转换成方块并添加到布局3.4初始化布局3.5关键检测3.6试用测试3.7改进4、完成代码5、总结今年年初,《最强大脑》新一季上线。第一集选的时候,大家做了一个数字游戏,取名《数字华容道》。当时,何猷君以20多秒的成绩获得了该项目的冠军。看完这个游戏,我决定写一个《数字华容道》的程序。时隔半年,终于想起来了,今天也要体会到了。
n字谜是一种智力游戏,常见的类型有十五位数字谜和八位数字谜。十五数推游戏的棋盘上会有十五个方格和一个等于一个方格的空间(用于移动方格)。当十五个数字按顺序排序,最后一个格子是空的,就说明挑战成功了。
本文使用PyQt5进行设计和实现。PyQt5是程序的一种呈现方式,最重要的是算法。学会算法后,完全可以用PyGame或者Tkinter来实现。
PyQt5安装:pip安装PyQt5
本文的使用环境:
系统:Windows 10 64位Python版本:3.6
1、布局设计
制作一个数字华容道的简版,版面设计如图:
图中灰色部分用QWidget作为整个游戏的载体;黄色部分使用QGridLayout作为数字方块的布局;红色部分使用QLabel作为数字方块。
2、算法设计
如上图所示,这个游戏需要15个方块,每个方块代表一个数字。我们可以用一个二维列表来存储方块上的数字。实际上,我们需要创建一个4x4的列表来存储从0到15的数字,0代表空的位置。
2.1 创建并初始化数组
创建阵列的方法:
创建一个长度为16的数组,在相应的位置存储0 ~ 15;有毛病
随机导入
#用于存储位置信息的二维数组
blocks=[]
#生成随机数组,0表示空位置
arr=范围(16)
数字=random.sample(arr,16)
对于范围(4)中的行:
blocks.append([])
对于范围(4)中的列:
块[行]。追加(数字[行*4列])
#打印结果
对于范围(4)中的I:
打印(块[i])
[出局]
[2, 5, 7, 9]
[11, 8, 4, 12]
[6, 13, 10, 15]
[1, 14, 0, 3]
[0.1秒内完成]
2.2 移动算法
如果如左图所示移动前面的数字位置,当按下左箭头时,将变成如右图所示:
可以看出,(1,2)和(1,3)中的数是互换的,即0和8互换;如果如右图所示再次按下左箭头,所有数字都不会改变,因为数字0的右边没有数字。
综上所述:如果数字0位于(行,列)且列3,那么按下左箭头后,位于(行,列)和(行,列1)的数组互换,同样可以得到:
如果数字0的位置是(row,column)且列0,那么按右箭头键后,(row,column)和(row,column-1)位置的数组交换;
如果数字0的位置是(row,column)且row3,那么按下向上箭头后,(row,column)和(row 1,column)位置的数组互换;
如果数字0的位置是(row,column)且row0,那么按下向下箭头后,(row,column)和(row-1,column)位置的数组互换;
将移动算法封装到如下函数中:
#移动
# zero_row表示数字0所在二维数组的行下标,zero_column表示数字0所在二维数组的列下标。
定义移动(方向):
If(direction=='UP'): # on
if zero_row!=3:
块[零行][零列]=块[零行1][零列]
块[零_行1][零_列]=0
zero_row=1
if(direction=='DOWN'): #下
if zero_row!=0:
块[零行][零列]=块[零行-1][零列]
区块[零行-1][零列]=0
zero_row -=1
如果(方向=='左'):#左
如果零_列!=3:
块[零行][零列]=块[零行][零列1]
块[零行][零列1]=0
零列=1
如果(方向=='右'):#右
如果零_列!=0:
块[零行][零列]=块[零行][零列- 1]
区块[零行][零列- 1]=0
零列-=1
2.3 是否胜利检测算法
检测是否胜利其实很简单:前15个位置分别对应,最后一个为0即为胜利,不过为了避免不必要的计算,我们先检测最后一个是否为0 ,如果不为0 前面的就不用比较了。具体代码实现如下:
# 检测是否完成
极好的检查结果():
# 先检测最右下角是否为0
如果区块[3][3]!=0:
返回错误的
对于范围(4)中的行:
对于范围(4)中的列:
# 运行到此处说名最右下角已经为0,通过即可
如果行==3,列==3:
及格
# 值是否对应
否则如果块[行][列]!=行* 4列1:
返回错误的
返回真实的
3、实现
下面讲解所有功能模块的实现。
3.1 框架搭建
创建QWidget作为整个游戏的载体:
导入系统
来自PyQt5 .QtWidgets导入QWidget,QApplication
班号华荣(QWidget):
''' 华容道主体'''
def __init__(self):
超级()。__init__()
self.initUI()
def initUI(self):
# 设置宽和高
self.setFixedSize(400,400)
# 设置标题
self.setWindowTitle('数字华容道)
# 设置背景颜色
自我。设置样式表('背景色:灰色;')
self.show()
if __name__=='__main__ ':
app=QA应用程序(sys。argv)
ex=NumberHuaRong()
sys.exit(app.exec_())
运行结果如下图所示:
3.2 数字方块实现
前面已经提到,用一个二维数组来存放0~16 个数字,最终我们要转换成一个数字方块,单独创建一个类:
类块(QLabel):
''' 数字方块'''
def __init__(self,number):
超级()。__init__()
self.number=数字
self.setFixedSize(80,80)
# 设置字体
font=QFont()
font.setPointSize(30)
font.setBold(True)
self.setFont(字体)
# 设置字体颜色
pa=QPalette()
pa.setColor(QPalette .WindowText,Qt.white)
self.setPalette(pa)
# 设置文字位置
自我设置校准(Qt .对齐中心)
# 设置背景颜色\圆角和文本内容
如果self.number==0:
自我。设置样式表('背景色:白色;'边框半径:10px’)
否则:
自我。设置样式表('背景色:红色;'边框半径:10px’)
self.setText(str(self.number))
该类继承自QLablel,初始化需要传入一个参数数字,数字就是数字方块上显示的数字。
3.3 将数字转换成方块添加到布局
布局采用QGridLayout创建一个4X4的self.gltMain,将16个街区添加到self.gltMain:
def updatePanel(自身):
对于范围(4)中的行:
对于范围(4)中的列:
自我。glt main。添加小部件(阻止(自身。块[行][列])、行、列)
self.setLayout(self.gltMain)
3.4 初始化布局
初始化布局包括随机数据的产生与将数字转换成方块添加到布局:
# 初始化布局
def onInit(self):
# 产生随机数组,0 代表空的位置
arr=范围(16)
self.numbers=random.sample(arr,16)
# 将数字方块添加到布局
对于范围(4)中的行:
self.blocks.append([])
对于范围(4)中的列:
temp=自身。数字[行* 4列]
如果温度==0:
self.zero_row=row
self.zero_column=列
self.blocks[row]。追加(临时)
self.gltMain.addWidget(块(临时),行,列)
3.5 按键检测
QWidget有一个keyPressEvent事件句柄,我们只需要重新实现这个方法:
#测试按钮
def keyPressEvent(self,Event):
key=event.key()
if(key==Qt。Key_Up或key==Qt。Key_W):
self.move(方向。向上)
if(key==Qt。Key_Down或key==Qt。密钥):
self.move(方向。向下)
if(key==Qt。Key_Left或key==Qt。Key_A):
self.move(方向。左)
if(key==Qt。Key_Right或key==Qt。Key_D):
self.move(方向。右)
self.updatePanel()
if self.checkResult():
if messagebox . ok==qmessagebox . information(self,'挑战结果','祝贺您完成挑战!'):
self.onInit()
检测到按键被按下后,判断键值是“”还是“WSAD”,做出相应的动作。移动后刷新布局(updatePannel),最后检查挑战是否完成。如果挑战完成,会弹出一个提示框。如果点击OK按钮,游戏重新开始(onInit)。
3.6 试玩测试
至此,所有功能模块已经介绍完毕。不要担心完整的代码。让我们运行这个程序,看看有没有错误。
玩了几个游戏,发现并不是所有的游戏都能还原,比如下面这个:
如图,方块14和15的位置颠倒了,所以无论如何都要恢复。这是随机发生的。到底是怎么回事?在网上搜了一下,确实只有两位数反了的话,是无论如何也恢复不了的。这是什么造成的?还记得我们的二维数组是怎么生成的吗?它是随机的,也就是说它可能随机到无法恢复。
如何避免这种情况?初始化数组时,所有的位置都是正确的数字,然后用move来移动和加扰。
3.7 改进完善
由于每个功能模块都作为一个方法单独编写,我们只需要修改onInit方法。
#初始化布局
def onInit(self):
#生成一个顺序数组
self.numbers=list(范围(1,16))
self.numbers.append(0)
#向二维数组中添加一个数字
对于范围(4)中的行:
self.blocks.append([])
对于范围(4)中的列:
temp=self . numbers[行* 4列]
如果温度==0:
self.zero_row=row
self.zero_column=列
self.blocks[row]。追加(临时)
#打乱阵列
对于范围内的I(500):
random_num=random.randint(0,3)
self.move(方向(random_num))
self.updatePanel()
老师用[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0]组成一个顺序数组,然后把它变成一个二维数组块,再移动500次,最后加入到布局中。
4、完整代码
导入系统
随机导入
从枚举导入意图
来自PyQt5。QtWidgets导入QLabel,QWidget,QApplication,QGridLayout,QMessageBox
来自PyQt5。QtGui导入QFont,QPalette
来自PyQt5。QtCore导入
#使用枚举类来指示方向
类别方向(内部):
向上=0
向下=1
左=2
右=3
班号华荣(QWidget):
'''华容路主体' ' '
def __init__(self):
超级()。__init__()
self.blocks=[]
self.zero_row=0
self.zero_column=0
self.gltMain=QGridLayout()
self.initUI()
def initUI(self):
#设置盒子间隔
self.gltMain.setSpacing(10)
self.onInit()
#设置布局
self.setLayout(self.gltMain)
#设置宽度和高度
self.setFixedSize(400,400)
#设置标题
Self.setWindowTitle('数字华容道')
#设置背景颜色
self . set style sheet(' background-color:gray;')
self.show()
#初始化布局
def onInit(self):
#生成一个顺序数组
self.numbers=list(范围(1,16))
self.numbers.append(0)
# 将数字添加到二维数组
对于范围(4)中的行:
self.blocks.append([])
对于范围(4)中的列:
temp=自身。数字[行* 4列]
如果温度==0:
self.zero_row=row
self.zero_column=列
self.blocks[row].追加(临时)
# 打乱数组
对于范围内的我(500):
random_num=random.randint(0,3)
自我移动(方向(random_num))
self.updatePanel()
# 检测按键
def keyPressEvent(self,Event):
key=event.key()
if(key==Qt .向上键或key==Qt .Key_W):
自我移动(方向。向上)
if(key==Qt .向下键或key==Qt .密钥):
自我移动(方向。向下)
if(key==Qt .向左键或key==Qt .Key_A):
自我移动(方向。左)
if(key==Qt .钥匙_右或key==Qt .Key_D):
自我移动(方向。右)
self.updatePanel()
if self.checkResult():
如果QMessageBox .ok==qmessagebox。信息(自我,挑战结果', '恭喜您完成挑战!'):
self.onInit()
# 方块移动算法
定义移动(自身,方向):
如果(方向==方向。向上):#上
if self.zero_row!=3:
自我。块[自我。zero _ row][自我。zero _ column]=自身。块[自我。zero _ row 1][自己。零_列]
自我。块[自我。zero _ row 1][自己。zero _ column]=0
self.zero_row=1
如果(方向==方向。向下):#下
if self.zero_row!=0:
自我。块[自我。zero _ row][自我。zero _ column]=自身。阻挡[自我。zero _ row-1][自我。零_列]
自我。块[自我。zero _ row-1][自我。zero _ column]=0
self.zero_row -=1
如果(方向==方向。左):#左
if self.zero_column!=3:
自我。块[自我。zero _ row][自我。zero _ column]=自身。阻挡[自我。zero _ row][自我。零_列1]
自我。块[自我。zero _ row][自我。零_列1]=0
self.zero_column=1
如果(方向==方向。右):#右
if self.zero_column!=0:
自我。块[自我。zero _ row][自我。zero _ column]=自身。阻挡[自我。zero _ row][自我。zero _ column-1]
自我。块[自我。zero _ row][自我。零_列-1]=0
self.zero_column -=1
def updatePanel(自身):
对于范围(4)中的行:
对于范围(4)中的列:
自我。glt main。添加小部件(阻止(自身。块[行][列])、行、列)
self.setLayout(self.gltMain)
# 检测是否完成
定义检查结果(自身):
# 先检测最右下角是否为0
如果self.blocks[3][3]!=0:
返回错误的
对于范围(4)中的行:
对于范围(4)中的列:
# 运行到此处说名最右下角已经为0,通过即可
如果行==3,列==3:
及格
#值是否对应
elif self。区块[行][列]!=行* 4列1:
返回错误的
返回真实的
类块(QLabel):
''' 数字方块'''
def __init__(self,number):
超级()。__init__()
self.number=数字
self.setFixedSize(80,80)
# 设置字体
font=QFont()
font.setPointSize(30)
font.setBold(True)
self.setFont(字体)
# 设置字体颜色
pa=QPalette()
pa.setColor(QPalette .WindowText,Qt.white)
self.setPalette(pa)
# 设置文字位置
自我设置校准(Qt .对齐中心)
# 设置背景颜色\圆角和文本内容
如果self.number==0:
自我。设置样式表('背景色:白色;'边框半径:10px’)
否则:
自我。设置样式表('背景色:红色;'边框半径:10px’)
self.setText(str(self.number))
if __name__=='__main__ ':
app=QA application(sys . argv)
ex=NumberHuaRong()
sys.exit(app.exec_())
5、总结
这样做的过程中遇到的最大的坑就是随机数组无法恢复。另外我在玩这个游戏的时候已经找到了还原定律,让我可以在测试的时候完成测试,否则根本测试不出来,这就挑战了成功的一步。
另外要对《最强大脑》做一个点评:这个项目根本就是偏的。玩过的人会很快,没玩过的人要很长时间才能找到规律。我用手机玩4X4用了33秒,我佩服程序的冠军(就算我玩了)。
这就是这篇教你如何用python开发数字推送游戏的文章。关于python开发数字推送游戏的更多信息,请搜索我们之前的文章或者继续浏览下面的相关文章。希望大家以后能多多支持我们!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。