本文主要介绍Python迷宫生成器的详细代码,对于大家来说非常详细,对于大家的学习或者工作都有一定的参考价值。有需要的朋友可以参考一下。
迷宫作为一种古老的智力游戏,千百年来散发着迷人的魅力。然而,手工设计迷宫费时费力,所以我们有必要制作一个程序:迷宫生成器…
好吧,我再也编不出来了。不过从上面的文字可以看出,我们这次的主题是用Python实现一个迷宫生成器。
先展示效果图:
让我们首先分析所需的库:
既然是生成器,那么每次生成的迷宫都是一模一样显然没有意义。因此,我们不可避免地使用随机数(随机库)。迷宫是一定要画的,所以要有一个GUI库或者绘图库。这里我用的是Pygame(Tkinter Tkinter或者Turtle其实也可以,但毕竟Pygame更方便)。有了Pygame,Sys似乎也是需要的(用来退出程序,但不实际用的话好像也不疼)。然后是Tkinter.filedialog,主要用于询问保存路径(生成的迷宫必须保存)。当然,加上一个带时间的定时器,似乎是锦上添花。
所以,有:
#编码:utf-8
导入上下文库
with contextlib.redirect_stdout(无):
导入pygame
随机导入
导入系统
导入时间
从tkinter.filedialog对话框导入*
这里需要使用Contextlib来防止Pygame被输出,因为在导入PyGame时会输出很多版本信息等内容(影响美感)。
接下来,我们需要询问一些参数:
A=int(input('列数:'))
B=int(输入('行数:'))
L=int(输入(' size:'))
Saveit=input ('save:')
然后,是时候运行生成迷宫的程序了。同时,我们有必要记录下时间(相当于启动了一个计时器):
打印('建筑.')
e=time.time()
然后迷宫正式生成。在介绍这部分代码之前,我们需要了解一下算法:
第一步是生成由迷宫单元(白色方块)和墙壁(黑格)组成的网格。一行中的迷宫单元数就是迷宫中的列数,一列中的迷宫寻找单元数就是迷宫中的行数。将左上角的迷宫单元作为起点,右下角的迷宫单元作为终点,打破起点左侧和终点右侧的墙壁,如图:
第二步是参观每个迷宫单元。将起点标记为当前迷宫单元,当存在未访问的迷宫单元时(所有曾经是当前迷宫单元的迷宫单元都被视为已访问),重复:
将周围未参观过的迷宫单元添加到表格中;如果表格中有迷宫单元:将当前迷宫单元堆叠(可以理解为将其添加到一个名为stack的表格中);从表格中随机选择一个迷宫单元;打破当前迷宫单元和所选迷宫单元之间的墙;将所选择的迷宫单元标记为当前迷宫单元;如果表中没有迷宫单元:栈顶的迷宫单元出栈(可以理解为获取并删除栈中最后一个元素);将退出的迷宫单元设置为当前迷宫单元;
在循环的最后,会出现和文章开头的效果图一样的结果。
接下来,我们将把文字算法转换成Python代码。
首先,程序不知道图片,它知道数据。所以我们需要建立一个二维列表,用一串数据来表示当前图像。当然,我们可以顺便一起完成第一步的设置:
list=[]
aa=0
需要=[]
对于范围内的j(2 * a1):
如果aa==0:
aa=1
alistone=[]
对于范围内的I(2 * B1):
alistone.append(1)
alist.append(alistone)
否则:
aa=0
alistone=[]
bb=0
对于范围内的I(2 * B1):
如果bb==0:
bb=1
alistone.append(1)
否则:
bb=0
need.append((j,I))
alistone.append(0)
alist.append(alistone)
list[0][1]=0
列表[-1][-2]=0
如你所见,此外,我们还建立了一个需求列表,其中存储了所有的迷宫单元。它的作用是判断迷宫单元是否被访问过,每次访问都会将迷宫单元从表格中删除。当表格中没有迷宫单元时,意味着所有的迷宫单元都被访问过。
x=1
y=1
need.remove((1,1))
列表=[]
而len(需要)0:
aroundit=[]
尝试:
如果x-20:
打印(1 '1 ')
列表[x-2][y]=0
如果(x-2,y)需要:
around it . append(' list[x-1][y],x=(0,x-2)')
除了:
while False:
打印()
尝试:
列表[x ^ 2][y]=0
如果(x ^ 2,y)需要:
around it . append(' list[x 1][y],x=(0,x 2)')
除了:
while False:
打印()
尝试:
列表[x][y ^ 2]=0
如果(x,y ^ 2)需要:
around it . append(' list[x][y 1],y=(0,y 2)')
除了:
while False:
打印()
尝试:
如果y-20:
打印(1 '1 ')
list[x][y-2]=0
如果(x,y-2)需要:
around it . append(' list[x][y-1],y=(0,y-2)')
除了:
while False:
打印()
如果len(aroundit)为0:
listing.append((x,y))
exec(random.choice(aroundit))
need.remove((x,y))
否则:
x,y=列表[-1]
listing.pop()
而这些内容就是第二步。我已经解释了算法。唯一稍有不同的是,这里我们没有在列表中添加相邻迷宫单元的坐标。而是将对应的破壁和标记为当前迷宫单元的代码以字符串的形式存储在表中,随机选择一个迷宫单元对应的字符串后,用exec转换成代码运行(这样可以节省一些代码)。
打印('完成!在{}秒内。格式(time.time()-e))
在打印出生成迷宫所需的时间后,我们需要将表格中的数据转换成图像。当然,在此之前,我们必须确定图片保存的位置。
if saveit=='1 ':
ccc=askdirectory()
h=' '
bbbbb=1
虽然正确:
尝试:
打开(' {}/{}{}迷宫{})。巴布亚新几内亚。格式(ccc,a,b,h),' r ')
h='({})'。格式(bbbbb)
除了:
破裂
bbbbb=1
既然在使用的时候有可能选择不保存图片,那你就先判断一下选择保存还是不保存。在这里,字符“1”的意思是保存(如果你输入了别的东西,自然不会保存)。然后我们需要让你选择保存路径(askdirectory()要求文件路径,你不需要选择文件名)。然后,我们要确定文件名:“ab maze.png”。这里,有必要确定在指定的路径中是否存在具有该名称的文件。如果有,我们需要给它加上一个序列号。总之,通过这一串代码,我们确定了迷宫的路径文件名。
pygame.init()
icon=py game . image . load(' maze . png ')
pygame.display.set_icon(icon)
screen=pygame.display.Info()
screen=py game . display . set _ mode((l *(2 * a1),l*(2*b 1)))
Pygame.display.set_caption('迷宫')
screen.fill(“白色”)
c=pygame。Surface((l,l),flags=pygame。HWSURFACE)
c.fill(color='white ')
d=pygame。Surface((l,l),flags=pygame。HWSURFACE)
d.fill(color='black ')
对于范围内的I(2 * a1):
对于范围内的j(2 * B1):
如果list[i][j]==0:
screen.blit(c,(i*l,j*l))
elif list[I][j]==1:
screen.blit(d,(i*l,j*l))
pygame.display.flip()
if saveit=='1 ':
Pygame.image.save (screen,' {}/{} {}迷宫{}。巴布亚新几内亚。格式(ccc,a,b,h))
虽然正确:
对于pygame.event.get()中的事件:
if event.type==pygame。退出:
pygame.quit()
sys.exit()
代码中用到的图片“maze.png”(名字不太对,下载后要改名):
下面是Pygame的基本设置,把表格内容可视化。每个数字代表一个正方形,数字的值决定了正方形的颜色。数字在表格中的位置决定了正方形的位置。这样,我们就完全把桌子变成了图像。当然,我们还需要用pygame.image.save()函数将图片保存为图片文件。
这样,这个生成器似乎完成了。
它运行良好,但当迷宫比较复杂时,暴露出一个问题(下图是100100的迷宫):
由于正确路径过于曲折,在复杂度较高时,这个迷宫的难度会变得极高!
难度高,在某方面上讲,的确是好事。但当你向你的朋友们展示这个迷宫时,如果你自己也无法得出正确的路径,这不是很扫兴吗?
因此,一个寻路算法变得非常有必要。
寻路算法的大体思路:
在生成的迷宫中,白格为路,黑格为墙。将起点设置为当前位置,重复执行直到终点成为当前位置:
将当前位置标记为正确路径;将周围未标记的路加入一个表格;如果表格不空:将当前位置入栈;从表格中随机选择一条路,并将其设为当前位置;如果表格是空的:栈顶的路出栈;将其设为当前位置;
通过这个算法,我们可以试出正确的路径(如图):
代码的实现:
x2=0
y2=1
列表2=[]
而不是(列表[-1][-2]==2):
列表[x2][y2]=3
大约2=[]
尝试:
如果x2-10:
打印(1 '1 ')
如果列表[x2-1][y2]==0:
around2.append('x2=x2-1 ')
除了:
while False:
打印()
尝试:
如果列表[x2 1][y2]==0:
around2.append('x2=x2 1 ')
除了:
while False:
打印()
尝试:
如果列表[x2][y2 1]==0:
around2.append('y2=y2 1 ')
除了:
while False:
打印()
尝试:
如果y2-10:
打印(1 '1 ')
如果列表[x2][y2-1]==0:
around2.append('y2=y2-1 ')
除了:
while False:
打印()
如果len(约2)0:
清单2 .追加((x2,y2))
exec(random.choice(around2))
否则:
列表[x2][y2]=2
x2,y2=列表2[-1]
listing2.pop()
列表[-1][-2]=3
对于范围内的I(len(list)):
对于范围内的j(len(list[0]):
如果列表[i][j]==2:
列表[i][j]=0
同时,图像绘制的过程也要作出一些改动,以显示正确路径:
if saveit=='1 ':
ccc=askdirectory()
h=' '
bbbbb=1
虽然正确:
尝试:
打开(' {}/{}{)迷宫{}.巴布亚新几内亚。格式(ccc,a,b,h),' r ')
打开(' {}/{}{)迷宫(正确线路){}.巴布亚新几内亚。格式(ccc,a,b,h),' r ')
h='({})' .格式(bbbbb)
除了:
破裂
bbbbb=1
pygame.init()
icon=pygame.image.load('迷宫. png’)
pygame.display.set_icon(icon)
screen=pygame.display.Info()
屏幕=py游戏。展示。set _ mode((l *(2 * a1),l*(2*b 1)))
pygame.display.set_caption('迷宫)
screen.fill("白色")
if saveit=='1 ':
c=pygame .Surface((l,l),flags=pygame .HWSURFACE)
c.fill(color='white ')
d=pygame .Surface((l,l),flags=pygame .HWSURFACE)
d.fill(color='black ')
f=pygame .Surface((l,l),flags=pygame .HWSURFACE)
f.fill(color='白色)
对于范围内的I(2 * a1):
对于范围内的j(2 * B1):
如果list[i][j]==0:
screen.blit(c,(i * l,j * l))
elif列表[I][j]==1:
screen.blit(d,(i * l,j * l))
否则:
screen.blit(f,(i * l,j * l))
pygame.image.save(screen,' {}/{}{}迷宫{}.巴布亚新几内亚。格式(ccc,a,b,h))
c=pygame .Surface((l,l),flags=pygame .HWSURFACE)
c.fill(color='white ')
d=pygame .Surface((l,l),flags=pygame .HWSURFACE)
d.fill(color='black ')
f=pygame .Surface((l,l),flags=pygame .HWSURFACE)
f.fill(color='red ')
对于范围内的I(2 * a1):
对于范围内的j(2 * B1):
如果list[i][j]==0:
screen.blit(c,(i * l,j * l))
elif列表[I][j]==1:
screen.blit(d,(i * l,j * l))
否则:
screen.blit(f,(i * l,j * l))
pygame.image.save(screen,' {}/{}{}迷宫(正确线路){}.巴布亚新几内亚。格式(ccc,a,b,h))
c=pygame .Surface((l,l),flags=pygame .HWSURFACE)
c.fill(color='white ')
d=pygame .Surface((l,l),flags=pygame .HWSURFACE)
d.fill(color='black ')
f=pygame .Surface((l,l),flags=pygame .HWSURFACE)
f.fill(color='白色)
对于范围内的I(2 * a1):
对于范围内的j(2 * B1):
如果list[i][j]==0:
screen.blit(c,(i*l,j*l))
elif列表[I][j]==1:
screen.blit(d,(i*l,j*l))
否则:
screen.blit(f,(i*l,j*l))
pygame.display.flip()
aaaaaa=0
虽然正确:
对于pygame.event.get()中的事件:
if event.type==pygame .退出:
pygame.quit()
sys.exit()
if event.type==pygame .鼠标按钮按下:
如果aaaaaa==1:
aaaaaa=0
c=pygame .Surface((l,l),flags=pygame .HWSURFACE)
c.fill(color='white ')
d=pygame .Surface((l,l),flags=pygame .HWSURFACE)
d.fill(color='black ')
f=pygame .Surface((l,l),flags=pygame .HWSURFACE)
f.fill(color='白色)
对于范围内的I(2 * a1):
对于范围内的j(2 * B1):
如果list[i][j]==0:
screen.blit(c,(i * l,j * l))
elif列表[I][j]==1:
screen.blit(d,(i * l,j * l))
否则:
screen.blit(f,(i * l,j * l))
pygame.display.flip()
否则:
aaaaaa=1
c=pygame .Surface((l,l),flags=pygame .HWSURFACE)
c.fill(color='white ')
d=pygame .Surface((l,l),flags=pygame .HWSURFACE)
d.fill(color='black ')
f=pygame .Surface((l,l),flags=pygame .HWSURFACE)
f.fill(color='red ')
对于范围内的I(2 * a1):
对于范围内的j(2 * B1):
如果list[i][j]==0:
screen.blit(c,(i * l,j * l))
elif列表[I][j]==1:
screen.blit(d,(i * l,j * l))
否则:
screen.blit(f,(i * l,j * l))
pygame.display.flip()
通过这些改动,显示正确路径的效果就实现了。生成完成以后,窗口上显示的是没有正确路径的迷宫,而点击窗口后,正确的路径就会显示(再次点击隐藏)。
刚刚那张100100的迷宫,其正确路径是:
可以看出,本文中所用的算法生成的迷宫,其正确路径还是非常曲折的(难度很高)。你何不将其发给你的朋友,让其破解一下呢?
完整的代码:
#编码:utf-8
导入上下文库
with contextlib.redirect_stdout(无):
导入pygame
随机导入
导入系统
导入时间
从tkinter.filedialog对话框导入*
a=int(input('列数:'))
b=int(input('行数:'))
l=int(input('大小:'))
saveit=input('是否保存:')
打印('生成中.')
e=time.time()
list=[]
aa=0
需要=[]
对于范围内的j(2 * a1):
如果aa==0:
aa=1
alistone=[]
对于范围内的I(2 * B1):
alistone.append(1)
alist.append(alistone)
否则:
aa=0
alistone=[]
bb=0
对于范围内的I(2 * B1):
如果bb==0:
bb=1
alistone.append(1)
否则:
bb=0
need.append((j,I))
alistone.append(0)
alist.append(alistone)
list[0][1]=0
列表[-1][-2]=0
x=1
y=1
need.remove((1,1))
列表=[]
而len(需要)0:
aroundit=[]
尝试:
如果x-20:
打印(1 '1 ')
列表[x-2][y]=0
如果(x-2,y)需要:
围绕着它。append(' list[x-1][y],x=(0,x-2)')
除了:
while False:
打印()
尝试:
列表[x ^ 2][y]=0
如果(x ^ 2,y)需要:
围绕着它。append(' list[x 1][y],x=(0,x 2)')
除了:
while False:
打印()
尝试:
列表[x][y ^ 2]=0
如果(x,y ^ 2)需要:
围绕着它。append(' list[x][y 1],y=(0,y 2)')
除了:
while False:
打印()
尝试:
如果y-20:
打印(1 '1 ')
list[x][y-2]=0
如果(x,y-2)需要:
围绕着它。append(' list[x][y-1],y=(0,y-2)')
除了:
while False:
打印()
如果len(大约)为0:
listing.append((x,y))
exec(random.choice(aroundit))
need.remove((x,y))
否则:
x,y=列表[-1]
listing.pop()
x2=0
y2=1
列表2=[]
而不是(列表[-1][-2]==2):
列表[x2][y2]=3
大约2=[]
尝试:
如果x2-10:
打印(1 '1 ')
如果列表[x2-1][y2]==0:
around2.append('x2=x2-1 ')
除了:
while False:
打印()
尝试:
如果列表[x2 1][y2]==0:
around2.append('x2=x2 1 ')
除了:
while False:
打印()
尝试:
如果列表[x2][y2 1]==0:
around2.append('y2=y2 1 ')
除了:
while False:
打印()
尝试:
如果y2-10:
打印(1 '1 ')
如果列表[x2][y2-1]==0:
around2.append('y2=y2-1 ')
除了:
while False:
打印()
如果len(约2)0:
清单2 .追加((x2,y2))
exec(random.choice(around2))
否则:
列表[x2][y2]=2
x2,y2=列表2[-1]
listing2.pop()
列表[-1][-2]=3
对于范围内的I(len(list)):
对于范围内的j(len(list[0]):
如果列表[i][j]==2:
列表[i][j]=0
打印('完成!用时{}秒。格式(time.time()-e))
if saveit=='1 ':
ccc=askdirectory()
h=' '
bbbbb=1
虽然正确:
尝试:
打开(' {}/{}{)迷宫{}.巴布亚新几内亚。格式(ccc,a,b,h),' r ')
打开(' {}/{}{)迷宫(正确线路){}.巴布亚新几内亚。格式(ccc,a,b,h),' r ')
h='({})' .格式(bbbbb)
除了:
破裂
bbbbb=1
pygame.init()
icon=pygame.image.load('迷宫. png’)
pygame.display.set_icon(icon)
screen=pygame.display.Info()
屏幕=py游戏。展示。set _ mode((l *(2 * a1),l*(2*b 1)))
pygame.display.set_caption('迷宫)
screen.fill("白色")
if saveit=='1 ':
c=pygame .Surface((l,l),flags=pygame .HWSURFACE)
c.fill(color='white ')
d=pygame .Surface((l,l),flags=pygame .HWSURFACE)
d.fill(color='black ')
f=pygame .Surface((l,l),flags=pygame .HWSURFACE)
f.fill(color='白色)
对于范围内的I(2 * a1):
对于范围内的j(2 * B1):
如果list[i][j]==0:
screen.blit(c,(i * l,j * l))
elif列表[I][j]==1:
screen.blit(d,(i * l,j * l))
否则:
screen.blit(f,(i * l,j * l))
pygame.image.save(screen,' {}/{}{}迷宫{}.巴布亚新几内亚。格式(ccc,a,b,h))
c=pygame .Surface((l,l),flags=pygame .HWSURFACE)
c.fill(color='white ')
d=pygame .Surface((l,l),flags=pygame .HWSURFACE)
d.fill(color='black ')
f=pygame .Surface((l,l),flags=pygame .HWSURFACE)
f.fill(color='red ')
对于范围内的I(2 * a1):
对于范围内的j(2 * B1):
如果list[i][j]==0:
screen.blit(c,(i * l,j * l))
elif列表[I][j]==1:
screen.blit(d,(i * l,j * l))
否则:
screen.blit(f,(i * l,j * l))
pygame.image.save(screen,' {}/{}{}迷宫(正确线路){}.巴布亚新几内亚。格式(ccc,a,b,h))
c=pygame .Surface((l,l),flags=pygame .HWSURFACE)
c.fill(color='white ')
d=pygame .Surface((l,l),flags=pygame .HWSURFACE)
d.fill(color='black ')
f=pygame .Surface((l,l),flags=pygame .HWSURFACE)
f.fill(color='白色)
对于范围内的I(2 * a1):
对于范围内的j(2 * B1):
如果list[i][j]==0:
screen.blit(c,(i*l,j*l))
elif列表[I][j]==1:
screen.blit(d,(i*l,j*l))
否则:
screen.blit(f,(i*l,j*l))
pygame.display.flip()
aaaaaa=0
虽然正确:
对于pygame.event.get()中的事件:
if event.type==pygame .退出:
pygame.quit()
sys.exit()
if event.type==pygame .鼠标按钮按下:
如果aaaaaa==1:
aaaaaa=0
c=pygame .Surface((l,l),flags=pygame .HWSURFACE)
c.fill(color='white ')
d=pygame .Surface((l,l),flags=pygame .HWSURFACE)
d.fill(color='black ')
f=pygame .Surface((l,l),flags=pygame .HWSURFACE)
f.fill(color='白色)
对于范围内的I(2 * a1):
对于范围内的j(2 * B1):
如果list[i][j]==0:
screen.blit(c,(i * l,j * l))
elif列表[I][j]==1:
screen.blit(d,(i * l,j * l))
否则:
screen.blit(f,(i * l,j * l))
pygame.display.flip()
否则:
aaaaaa=1
c=pygame .Surface((l,l),flags=pygame .HWSURFACE)
c.fill(color='white ')
d=pygame .Surface((l,l),flags=pygame .HWSURFACE)
d.fill(color='black ')
f=pygame .Surface((l,l),flags=pygame .HWSURFACE)
f.fill(color='red ')
对于范围内的I(2 * a1):
对于范围内的j(2 * B1):
如果list[i][j]==0:
screen.blit(c,(i * l,j * l))
elif列表[I][j]==1:
screen.blit(d,(i * l,j * l))
否则:
screen.blit(f,(i * l,j * l))
pygame.display.flip()
代码的结束,对于程序也许仅仅只是开始;学习的暂时告一段落,从不影响生活的继续。生命无止境,贵在一颗永远向上的心。
到此这篇关于计算机编程语言迷宫生成器的文章就介绍到这了,更多相关计算机编程语言迷宫生成器内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。