作为一项古老的智力游戏,千百年来迷宫都散发着迷人的魅力 。但是,手工设计迷宫费时又耗(脑)力,于是,我们有必要制作一个程序:迷宫生成器……
好吧,我编不下去了 。但是 , 从上面的文字中,我们可以看出,我们此次的主题是:用实现一个迷宫生成器 。
首先展示一下效果图:
我们先分析一下所需的库:
既然是生成器,每次生成的迷宫一模一样显然是说不过去的 。因此 , 我们不可避免地要使用随机数(库) 。迷宫一定是要绘制的,所以需要有一个GUI库或绘图库,这里我使用(或其实都可以做到,但毕竟比较顺手) 。与搭配,Sys似乎也是需要的(用于退出程序,但其实不使用似乎也无伤大雅) 。然后是.,主要用于询问保存路径(生成的迷宫总得保存吧) 。当然,用Time加一个计时器似乎是锦上添花 。
于是 , 就有:
#coding:utf-8import contextlibwith contextlib.redirect_stdout(None):import pygameimport randomimport sysimport timefrom tkinter.filedialog import *
这里要说明的是 , 由于导入时会输出版本信息等很多内容(这很影响美感) , 我们需要使用阻止它输出 。
接下来 , 我们需要询问一些参数:
a=int(input("列数:"))b=int(input("行数:"))l=int(input("大?。?))saveit=input("是否保存:")
然后 , 就要运行生成迷宫的程序了 。同时 , 我们有必要计录一下时间(相当于开启计时器):
print("生成中...")e = time.time()
然后就是正式生成迷宫 。在介绍这部分代码之前,我们需要了解一下算法:
第一步,生成一个由迷宫单元(白格)和墙(黑格)组成的网格 。一行中迷宫单元的数量为迷宫的列数,一列找迷宫单元的数量为迷宫的行数 。令左上角的迷宫单元为起点,右下角的迷宫单元为终点 , 打破起点左边与终点右边的墙,如图所示:
第二步,访问各迷宫单元 。将起点标记为当前迷宫单元 , 当存在未被访问的迷宫单元(凡是曾经成为过当前迷宫单元的迷宫单元,都视为已访问)时,重复执行:
在循环结束以后,就会出现像文章开头效果图一样的结果 。
接下来,我们就要将文字化的算法转化为的代码 。
首先,程序是不认识图片的,它认识的是数据 。所以我们需要设置一个二维列表,以此来用一串数据表示当前的图像 。当然,我们可以顺便将第一步的设置一起完成:
alist = []aa=0need=[]for j in range(2*a+1):if aa==0:aa = 1alistone = []for i in range(2*b+1):alistone.append(1)alist.append(alistone)else:aa=0alistone = []bb=0for i in range(2*b+1):if bb==0:bb=1alistone.append(1)else:bb = 0need.append((j,i))alistone.append(0)alist.append(alistone)alist[0][1]=0alist[-1][-2]=0
可以看到,除此以外我们还建立了一个列表need,里面存储了所有的迷宫单元 。它的作用就是判断迷宫单元是否被访问,每次访问都会将迷宫单元从表格中删除 , 当表格中没有迷宫单元时 , 就说明所有迷宫单元都被访问了 。
x=1y=1need.remove((1, 1))listing=[]while len(need)>0:aroundit=[]try:if x-2<0:print(1+"1")alist[x-2][y]=0if (x-2,y) in need:aroundit.append("alist[x-1][y],x=(0,x-2)")except:while False:print()try:alist[x+2][y]=0if (x+2,y) in need:aroundit.append("alist[x+1][y],x=(0,x+2)")except:while False:print()try:alist[x][y+2]=0if (x,y+2) in need:aroundit.append("alist[x][y+1],y=(0,y+2)")except:while False:print()try:if y-20:listing.append((x,y))exec(random.choice(aroundit))need.remove((x, y))else:x,y=listing[-1]listing.pop()
而这些内容,就是第二步 。其算法我已经解释过,唯一一个微小的不同是,在此处我们并没有在列表中加入相邻迷宫单元的坐标 , 而是将其对应的破墙和标记为当前迷宫单元的代码以字符串的形式存储在表格中,并在随机选择出某个迷宫单元所对应的字符串后,使用exec将其转换为代码并运行(这可以节省一些代码) 。
print("完成!用时{}秒".format(time.time()-e))
打印完生成迷宫的用时后,我们需要将表格中的数据转化为图像了 。当然,在此之前,我们要先确定图片保存的位置 。
if saveit=="1":ccc = askdirectory()h=""bbbbb=1while True:try:open("{}/{}×{}迷宫{}.png".format(ccc,a,b,h),"r")h="({})".format(bbbbb)except:breakbbbbb+=1

文章插图

文章插图
由于使用时有可能选择不保存图片 , 因此要先判断你的选择是保存还是不保存 。这里字符“1”表示保存(输入其他,自然就是不保存了) 。然后我们需要让你选择保存路径(()询问的是文件路径,不需要选择文件名) 。然后,我们要确定文件名称:“a×b迷宫.png” 。这里需要判断指定路径是否存在此名称的文件,如果存在,则我们需要在后面加上序号 。总而言之,通过这串代码,我们已经将迷宫的路径+文件名确定了 。
pygame.init()icon=pygame.image.load("迷宫.png")pygame.display.set_icon(icon)screen=pygame.display.Info()screen = pygame.display.set_mode((l*(2*a+1),l*(2*b+1)))pygame.display.set_caption('迷宫')screen.fill("white")c = pygame.Surface((l, l), flags=pygame.HWSURFACE)c.fill(color='white')d = pygame.Surface((l, l), flags=pygame.HWSURFACE)d.fill(color='black')for i in range(2*a+1):for j in range(2*b+1):if alist[i][j]==0:screen.blit(c, (i*l, j*l))elif alist[i][j]==1:screen.blit(d, (i*l, j*l))pygame.display.flip()if saveit=="1":pygame.image.save(screen, "{}/{}×{}迷宫{}.png".format(ccc, a, b, h))while True:for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()sys.exit()
代码中使用的图片“迷宫.png”(名称不太对,下载以后要重新命名一下):
这里主要是的基本设置文章生成器哪个好,并将表格内容图像化 。每一个数字代表一个方块,而数字的值则决定了方块的颜色,数字在表格中的位置决定了方块的位置 。就这样,我们呢将表格完全转化成了图像 。当然,我们还需要用.image.save()函数将图像保存为图片文件 。
这样,这个生成器似乎完成了 。
它运行良好,但当迷宫比较复杂时,暴露出一个问题(下图是100×100的迷宫):
由于正确路径过于曲折 , 在复杂度较高时 , 这个迷宫的难度会变得极高!
难度高,在某方面上讲文章生成器哪个好,的确是好事 。但当你向你的朋友们展示这个迷宫时,如果你自己也无法得出正确的路径,这不是很扫兴吗?
因此 , 一个寻路算法变得非常有必要 。
寻路算法的大体思路:
在生成的迷宫中 , 白格为路,黑格为墙 。将起点设置为当前位置,重复执行直到终点成为当前位置:
如果表格是空的:
通过这个算法,我们可以试出正确的路径(如图):
代码的实现:
x2=0y2=1listing2=[]while not(alist[-1][-2]==2):alist[x2][y2]=3around2=[]try:if x2-1<0:print(1+"1")if alist[x2-1][y2]==0:around2.append("x2=x2-1")except:while False:print()try:if alist[x2+1][y2]==0:around2.append("x2=x2+1")except:while False:print()try:if alist[x2][y2+1]==0:around2.append("y2=y2+1")except:while False:print()try:if y2-10:listing2.append((x2,y2))exec(random.choice(around2))else:alist[x2][y2]=2x2,y2=listing2[-1]listing2.pop()alist[-1][-2]=3for i in range(len(alist)):for j in range(len(alist[0])):if alist[i][j]==2:alist[i][j]=0
同时 , 图像绘制的过程也要作出一些改动,以显示正确路径:
if saveit=="1":ccc = askdirectory()h=""bbbbb=1while True:try:open("{}/{}×{}迷宫{}.png".format(ccc,a,b,h),"r")open("{}/{}×{}迷宫(正确线路){}.png".format(ccc,a,b,h),"r")h="({})".format(bbbbb)except:breakbbbbb+=1pygame.init()icon=pygame.image.load("迷宫.png")pygame.display.set_icon(icon)screen=pygame.display.Info()screen = pygame.display.set_mode((l*(2*a+1),l*(2*b+1)))pygame.display.set_caption('迷宫')screen.fill("white")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='white')for i in range(2 * a + 1):for j in range(2 * b + 1):if alist[i][j] == 0:screen.blit(c, (i * l, j * l))elif alist[i][j] == 1:screen.blit(d, (i * l, j * l))else:screen.blit(f, (i * l, j * l))pygame.image.save(screen, "{}/{}×{}迷宫{}.png".format(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')for i in range(2 * a + 1):for j in range(2 * b + 1):if alist[i][j] == 0:screen.blit(c, (i * l, j * l))elif alist[i][j] == 1:screen.blit(d, (i * l, j * l))else:screen.blit(f, (i * l, j * l))pygame.image.save(screen, "{}/{}×{}迷宫(正确线路){}.png".format(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='white')for i in range(2*a+1):for j in range(2*b+1):if alist[i][j]==0:screen.blit(c, (i*l, j*l))elif alist[i][j]==1:screen.blit(d, (i*l, j*l))else:screen.blit(f,(i*l, j*l))pygame.display.flip()aaaaaaa = 0while True:for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()sys.exit()if event.type == pygame.MOUSEBUTTONDOWN:if aaaaaaa == 1:aaaaaaa = 0c = 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='white')for i in range(2 * a + 1):for j in range(2 * b + 1):if alist[i][j] == 0:screen.blit(c, (i * l, j * l))elif alist[i][j] == 1:screen.blit(d, (i * l, j * l))else:screen.blit(f, (i * l, j * l))pygame.display.flip()else:aaaaaaa = 1c = 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')for i in range(2 * a + 1):for j in range(2 * b + 1):if alist[i][j] == 0:screen.blit(c, (i * l, j * l))elif alist[i][j] == 1:screen.blit(d, (i * l, j * l))else:screen.blit(f, (i * l, j * l))pygame.display.flip()
通过这些改动 , 显示正确路径的效果就实现了 。生成完成以后,窗口上显示的是没有正确路径的迷宫,而点击窗口后,正确的路径就会显示(再次点击隐藏) 。
刚刚那张100×100的迷宫,其正确路径是:
可以看出,本文中所用的算法生成的迷宫,其正确路径还是非常曲折的(难度很高) 。你何不将其发给你的朋友 , 让其破解一下呢?
完整的代码:
#coding:utf-8import contextlibwith contextlib.redirect_stdout(None):import pygameimport randomimport sysimport timefrom tkinter.filedialog import *a=int(input("列数:"))b=int(input("行数:"))l=int(input("大?。?))saveit=input("是否保存:")print("生成中...")e = time.time()alist = []aa=0need=[]for j in range(2*a+1):if aa==0:aa = 1alistone = []for i in range(2*b+1):alistone.append(1)alist.append(alistone)else:aa=0alistone = []bb=0for i in range(2*b+1):if bb==0:bb=1alistone.append(1)else:bb = 0need.append((j,i))alistone.append(0)alist.append(alistone)alist[0][1]=0alist[-1][-2]=0x=1y=1need.remove((1, 1))listing=[]while len(need)>0:aroundit=[]try:if x-2<0:print(1+"1")alist[x-2][y]=0if (x-2,y) in need:aroundit.append("alist[x-1][y],x=(0,x-2)")except:while False:print()try:alist[x+2][y]=0if (x+2,y) in need:aroundit.append("alist[x+1][y],x=(0,x+2)")except:while False:print()try:alist[x][y+2]=0if (x,y+2) in need:aroundit.append("alist[x][y+1],y=(0,y+2)")except:while False:print()try:if y-20:listing.append((x,y))exec(random.choice(aroundit))need.remove((x, y))else:x,y=listing[-1]listing.pop()x2=0y2=1listing2=[]while not(alist[-1][-2]==2):alist[x2][y2]=3around2=[]try:if x2-1<0:print(1+"1")if alist[x2-1][y2]==0:around2.append("x2=x2-1")except:while False:print()try:if alist[x2+1][y2]==0:around2.append("x2=x2+1")except:while False:print()try:if alist[x2][y2+1]==0:around2.append("y2=y2+1")except:while False:print()try:if y2-10:listing2.append((x2,y2))exec(random.choice(around2))else:alist[x2][y2]=2x2,y2=listing2[-1]listing2.pop()alist[-1][-2]=3for i in range(len(alist)):for j in range(len(alist[0])):if alist[i][j]==2:alist[i][j]=0print("完成!用时{}秒".format(time.time()-e))if saveit=="1":ccc = askdirectory()h=""bbbbb=1while True:try:open("{}/{}×{}迷宫{}.png".format(ccc,a,b,h),"r")open("{}/{}×{}迷宫(正确线路){}.png".format(ccc,a,b,h),"r")h="({})".format(bbbbb)except:breakbbbbb+=1pygame.init()icon=pygame.image.load("迷宫.png")pygame.display.set_icon(icon)screen=pygame.display.Info()screen = pygame.display.set_mode((l*(2*a+1),l*(2*b+1)))pygame.display.set_caption('迷宫')screen.fill("white")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='white')for i in range(2 * a + 1):for j in range(2 * b + 1):if alist[i][j] == 0:screen.blit(c, (i * l, j * l))elif alist[i][j] == 1:screen.blit(d, (i * l, j * l))else:screen.blit(f, (i * l, j * l))pygame.image.save(screen, "{}/{}×{}迷宫{}.png".format(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')for i in range(2 * a + 1):for j in range(2 * b + 1):if alist[i][j] == 0:screen.blit(c, (i * l, j * l))elif alist[i][j] == 1:screen.blit(d, (i * l, j * l))else:screen.blit(f, (i * l, j * l))pygame.image.save(screen, "{}/{}×{}迷宫(正确线路){}.png".format(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='white')for i in range(2*a+1):for j in range(2*b+1):if alist[i][j]==0:screen.blit(c, (i*l, j*l))elif alist[i][j]==1:screen.blit(d, (i*l, j*l))else:screen.blit(f,(i*l, j*l))pygame.display.flip()aaaaaaa = 0while True:for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()sys.exit()if event.type == pygame.MOUSEBUTTONDOWN:if aaaaaaa == 1:aaaaaaa = 0c = 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='white')for i in range(2 * a + 1):for j in range(2 * b + 1):if alist[i][j] == 0:screen.blit(c, (i * l, j * l))elif alist[i][j] == 1:screen.blit(d, (i * l, j * l))else:screen.blit(f, (i * l, j * l))pygame.display.flip()else:aaaaaaa = 1c = 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')for i in range(2 * a + 1):for j in range(2 * b + 1):if alist[i][j] == 0:screen.blit(c, (i * l, j * l))elif alist[i][j] == 1:screen.blit(d, (i * l, j * l))else:screen.blit(f, (i * l, j * l))pygame.display.flip()
文章来自
【Python迷宫生成器】本文到此结束,希望对大家有所帮助 。
- 小米生态VS乐视生态:向客厅生态延展 谁能圈住未来
- 魔兽世界:宏命令生成器 方便制作合适你的宏命令
- 在线生成 参考文献格式生成器
- 没有之一! 介绍一款最好用的在线logo生成器
- 心态好是最好的养生 ?如何保健养生心态
- ?容易招男生喜欢的女孩,这10种女人更容易让男人爱上
- 初中生毕业可以上哪些技校 什么专业最吃香
- 适合初中生上的正规技校有哪些
- ?如何约女生出来吃饭
- 心理学家:这四类父母容易造成孩子产生自卑