,,教你如何用python开发一款数字推盘小游戏

,,教你如何用python开发一款数字推盘小游戏

本文主要介绍如何教你如何用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的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: