Python迷宫生成器

迷宫作为一种古老的智力游戏,几千年来一直散发着迷人的魅力。然而,手工设计迷宫费时费力,因此有必要编制一个程序:迷宫生成器。

[En]

As an ancient mind game, the maze has exuded charming charm for thousands of years. However, designing the maze by hand is time-consuming and labor-consuming, so it is necessary to make a program: maze generator.

好吧,我编不下去了。但是,从上面的文字中,我们可以看出,我们此次的主题是:用Python实现一个迷宫生成器。

首先展示一下效果图:

Python迷宫生成器

让我们首先分析一下所需的库:

[En]

Let’s first analyze the required libraries:

既然是生成器,每次生成的迷宫一模一样显然是说不过去的。因此,我们不可避免地要使用随机数(Random库)。迷宫一定是要绘制的,所以需要有一个GUI库或绘图库,这里我使用Pygame(Tkinter或Turtle其实都可以做到,但毕竟Pygame比较顺手)。与Pygame搭配,Sys似乎也是需要的(用于退出程序,但其实不使用似乎也无伤大雅)。然后是Tkinter.filedialog,主要用于询问保存路径(生成的迷宫总得保存吧)。当然,用Time加一个计时器似乎是锦上添花。

于是,就有:

#coding:utf-8
import contextlib
with contextlib.redirect_stdout(None):
    import pygame
import random
import sys
import time
from tkinter.filedialog import *

这里要说明的是,由于导入Pygame时会输出版本信息等很多内容(这很影响美感),我们需要使用Contextlib阻止它输出。

接下来,我们需要询问一些参数:

[En]

Next, we need to ask some parameters:

a=int(input("列数:"))
b=int(input("行数:"))
l=int(input("大小:"))
saveit=input("是否保存:")

然后就是运行生成迷宫的程序的时候了。同时,我们需要记录时间(相当于启动定时器):

[En]

Then it’s time to run the program that generates the maze. At the same time, it is necessary for us to record the time (equivalent to starting the timer):

print("生成中...")
e = time.time()

然后是迷宫的正式生成。在介绍这部分代码之前,我们需要了解算法:

[En]

Then there is the formal generation of the maze. Before we introduce this part of the code, we need to understand the algorithm:

第一步是生成一个由迷宫细胞(白色网格)和墙壁(黑色网格)组成的网格。一列迷宫单元的个数是迷宫的列数,一列的迷宫单元的个数是迷宫的行数。以左上角的迷宫单元为起点,右下角的迷宫单元为终点,打破起点左侧和终点右侧的墙,如图所示:

[En]

The first step is to generate a grid of labyrinth cells (white grid) and walls (black grid). The number of maze units in a row is the number of columns in the maze, and the number of maze units in a column is the number of rows in the maze. Make the maze unit in the upper left corner as the starting point and the labyrinth unit in the lower right corner as the end, and break the wall to the left of the starting point and to the right of the end, as shown in the figure:

Python迷宫生成器

第二步是参观每个迷宫单元。将起点标记为当前迷宫单元,并在存在未访问的迷宫单元时重复此操作(已作为当前迷宫单元的所有迷宫单元均被视为已访问过):

[En]

The second step is to visit each maze unit. Mark the starting point as the current maze unit, and repeat when there is an unaccessed maze unit (all labyrinth units that have been the current maze unit are considered to have been visited):

  • 将周围未访问的迷宫单元添加到表格中
    [En]

    add the surrounding unvisited maze cells to the table*

  • 如果表格中有迷宫单元:
  • 将当前迷宫单元入栈(可以理解为将其加入一个叫做栈的表格);
  • 从表格中随机选择一个迷宫单元;
  • 打破当前迷宫单元与选择的迷宫单元之间的墙;
  • 将选择的迷宫单元标记为当前迷宫单元;
  • 如果表格中没有迷宫单元格:
    [En]

    if there are no maze cells in the table:*

  • 栈顶迷宫单元出栈(可以理解为将栈中的最后一个元素获取并删除);
  • 将出栈的迷宫单元设为当前迷宫单元;

在循环结束时,结果与文章开头的效果图相同。

[En]

At the end of the loop, the result is the same as the effect diagram at the beginning of the article.

接下来,我们就要将文字化的算法转化为Python的代码。

首先,程序不能识别图片,它能识别数据。因此,我们需要设置一个二维列表来用一串数据来表示当前图像。当然,我们可以通过以下方式一起完成第一步的设置:

[En]

First of all, the program does not recognize pictures, it knows data. So we need to set up a two-dimensional list to represent the current image with a string of data. Of course, we can complete the settings of the first step together by the way:

alist = []
aa=0
need=[]
for j in range(2*a+1):
    if aa==0:
        aa = 1
        alistone = []
        for i in range(2*b+1):
            alistone.append(1)
        alist.append(alistone)
    else:
        aa=0
        alistone = []
        bb=0
        for i in range(2*b+1):
            if bb==0:
                bb=1
                alistone.append(1)
            else:
                bb = 0
                need.append((j,i))
                alistone.append(0)
        alist.append(alistone)
alist[0][1]=0
alist[-1][-2]=0

可以看到,除此以外我们还建立了一个列表need,里面存储了所有的迷宫单元。它的作用就是判断迷宫单元是否被访问,每次访问都会将迷宫单元从表格中删除,当表格中没有迷宫单元时,就说明所有迷宫单元都被访问了。

x=1
y=1
need.remove((1, 1))
listing=[]
while len(need)>0:
    aroundit=[]
    try:
        if x-2<0:
            print(1+"1")
        alist[x-2][y]=0
        if (x-2,y) in need:
            aroundit.append("alist[x-1][y],x=(0,x-2)")
    except:
        while False:
            print()
    try:
        alist[x+2][y]=0
        if (x+2,y) in need:
            aroundit.append("alist[x+1][y],x=(0,x+2)")
    except:
        while False:
            print()
    try:
        alist[x][y+2]=0
        if (x,y+2) in need:
            aroundit.append("alist[x][y+1],y=(0,y+2)")
    except:
        while False:
            print()
    try:
        if y-2<0:
            print(1+"1")
        alist[x][y-2]=0
        if (x,y-2) in need:
            aroundit.append("alist[x][y-1],y=(0,y-2)")
    except:
        while False:
            print()
    if len(aroundit)>0:
        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))

打印生成迷宫所需的时间后,我们需要将表中的数据转换为图像。当然,在此之前,我们必须确定图片保存在哪里。

[En]

After printing the time it takes to generate the maze, we need to convert the data in the table into images. Of course, before that, we have to determine where the picture is saved.

if saveit=="1":
    ccc = askdirectory()
    h=""
    bbbbb=1
    while True:
        try:
            open("{}/{}×{}迷宫{}.png".format(ccc,a,b,h),"r")
            h="({})".format(bbbbb)
        except:
            break
        bbbbb+=1

由于使用时有可能选择不保存图片,因此要先判断你的选择是保存还是不保存。这里字符”1″表示保存(输入其他,自然就是不保存了)。然后我们需要让你选择保存路径(askdirectory()询问的是文件路径,不需要选择文件名)。然后,我们要确定文件名称:”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”(名称不太对,下载以后要重新命名一下):

这里主要是Pygame的基本设置,并将表格内容图像化。每一个数字代表一个方块,而数字的值则决定了方块的颜色,数字在表格中的位置决定了方块的位置。就这样,我们呢将表格完全转化成了图像。当然,我们还需要用pygame.image.save()函数将图像保存为图片文件。

如此一来,发电机似乎就完成了。

[En]

In this way, the generator seems to be complete.

它工作得很好,但当迷宫变得更加复杂时,一个问题就暴露了出来(下图是一个100×100的迷宫):

[En]

It works well, but when the maze is more complex, a problem is exposed (the following picture is a 100 × 100 maze):

Python迷宫生成器

因为正确的道路太曲折了,当复杂性高的时候,这个迷宫的难度就会变得非常高!

[En]

Because the correct path is too tortuous, when the complexity is high, the difficulty of this maze will become extremely high!

这是困难的,在某些方面,这确实是一件好事。但当你带你的朋友走迷宫时,如果你自己找不到正确的道路,那不是很令人失望吗?

[En]

It is difficult, and in some ways, it is indeed a good thing. But when you show your friends the maze, isn’t it disappointing if you can’t figure out the right path yourself?

因此,一种寻路算法变得非常必要。

[En]

Therefore, a pathfinding algorithm becomes very necessary.

寻路算法的大体思路:

在生成的迷宫中,白色网格是道路,黑色网格是墙。将起点设置为当前位置并重复,直到终点成为当前位置:

[En]

In the generated maze, the white grid is the road and the black grid is the wall. Set the start point to the current location and repeat until the end point becomes the current location:

  • 将当前位置标记为正确路径
    [En]

    Mark the current location as the correct path*

  • 将周围未标记的道路添加到表格中
    [En]

    add the surrounding unmarked roads to a table*

  • 如果表格不空:
  • 将当前位置入栈;
  • 从表格中随机选择一条路,并将其设为当前位置;
  • 如果表格是空的:
  • 栈顶的路出栈;
  • 将其设为当前位置;

通过这个算法,我们可以尝试找到正确的路径(见图):

[En]

Through this algorithm, we can try to find the correct path (see figure):

Python迷宫生成器

代码的实现:

x2=0
y2=1
listing2=[]
while not(alist[-1][-2]==2):
    alist[x2][y2]=3
    around2=[]
    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-1<0:
            print(1+"1")
        if alist[x2][y2-1]==0:
            around2.append("y2=y2-1")
    except:
        while False:
            print()
    if len(around2)>0:
        listing2.append((x2,y2))
        exec(random.choice(around2))
    else:
        alist[x2][y2]=2
        x2,y2=listing2[-1]
        listing2.pop()
alist[-1][-2]=3
for i in range(len(alist)):
    for j in range(len(alist[0])):
        if alist[i][j]==2:
            alist[i][j]=0

同时,图像绘制过程需要做一些更改,以显示正确的路径:

[En]

At the same time, the image drawing process needs to make some changes to show the correct path:

if saveit=="1":
    ccc = askdirectory()
    h=""
    bbbbb=1
    while True:
        try:
            open("{}/{}×{}迷宫{}.png".format(ccc,a,b,h),"r")
            open("{}/{}×{}迷宫(正确线路){}.png".format(ccc,a,b,h),"r")
            h="({})".format(bbbbb)
        except:
            break
        bbbbb+=1
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")
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 = 0
while 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 = 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='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 = 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')
                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()

通过这些改变,达到了显示正确路径的效果。生成完成后,窗口显示一个没有正确路径的迷宫,当您点击窗口时,将显示正确的路径(再次单击隐藏)。

[En]

With these changes, the effect of displaying the correct path is achieved. After the generation is complete, the window shows a maze without the correct path, and when you click on the window, the correct path will be displayed (click hide again).

刚刚那张100×100的迷宫,其正确路径是:

Python迷宫生成器

由此可见,本文采用的算法生成的迷宫的正确路径仍然非常曲折(非常困难)。你为什么不把它寄给你的朋友,让它破解呢?

[En]

It can be seen that the correct path of the maze generated by the algorithm used in this paper is still very tortuous (very difficult). Why don’t you send it to your friend and let it crack it?

完整的代码:

#coding:utf-8
import contextlib
with contextlib.redirect_stdout(None):
    import pygame
import random
import sys
import time
from tkinter.filedialog import *
a=int(input("列数:"))
b=int(input("行数:"))
l=int(input("大小:"))
saveit=input("是否保存:")
print("生成中...")
e = time.time()
alist = []
aa=0
need=[]
for j in range(2*a+1):
    if aa==0:
        aa = 1
        alistone = []
        for i in range(2*b+1):
            alistone.append(1)
        alist.append(alistone)
    else:
        aa=0
        alistone = []
        bb=0
        for i in range(2*b+1):
            if bb==0:
                bb=1
                alistone.append(1)
            else:
                bb = 0
                need.append((j,i))
                alistone.append(0)
        alist.append(alistone)
alist[0][1]=0
alist[-1][-2]=0
x=1
y=1
need.remove((1, 1))
listing=[]
while len(need)>0:
    aroundit=[]
    try:
        if x-2<0:
            print(1+"1")
        alist[x-2][y]=0
        if (x-2,y) in need:
            aroundit.append("alist[x-1][y],x=(0,x-2)")
    except:
        while False:
            print()
    try:
        alist[x+2][y]=0
        if (x+2,y) in need:
            aroundit.append("alist[x+1][y],x=(0,x+2)")
    except:
        while False:
            print()
    try:
        alist[x][y+2]=0
        if (x,y+2) in need:
            aroundit.append("alist[x][y+1],y=(0,y+2)")
    except:
        while False:
            print()
    try:
        if y-2<0:
            print(1+"1")
        alist[x][y-2]=0
        if (x,y-2) in need:
            aroundit.append("alist[x][y-1],y=(0,y-2)")
    except:
        while False:
            print()
    if len(aroundit)>0:
        listing.append((x,y))
        exec(random.choice(aroundit))
        need.remove((x, y))
    else:
        x,y=listing[-1]
        listing.pop()
x2=0
y2=1
listing2=[]
while not(alist[-1][-2]==2):
    alist[x2][y2]=3
    around2=[]
    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-1<0:
            print(1+"1")
        if alist[x2][y2-1]==0:
            around2.append("y2=y2-1")
    except:
        while False:
            print()
    if len(around2)>0:
        listing2.append((x2,y2))
        exec(random.choice(around2))
    else:
        alist[x2][y2]=2
        x2,y2=listing2[-1]
        listing2.pop()
alist[-1][-2]=3
for i in range(len(alist)):
    for j in range(len(alist[0])):
        if alist[i][j]==2:
            alist[i][j]=0
print("完成!用时{}秒".format(time.time()-e))
if saveit=="1":
    ccc = askdirectory()
    h=""
    bbbbb=1
    while True:
        try:
            open("{}/{}×{}迷宫{}.png".format(ccc,a,b,h),"r")
            open("{}/{}×{}迷宫(正确线路){}.png".format(ccc,a,b,h),"r")
            h="({})".format(bbbbb)
        except:
            break
        bbbbb+=1
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")
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 = 0
while 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 = 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='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 = 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')
                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()

程序更新——2.0版本:

#coding:utf-8
import contextlib
with contextlib.redirect_stdout(None):
    import pygame
import random
import sys
import time
from tkinter.filedialog import *
while True:
    a = int(input("列数:"))
    b = int(input("行数:"))
    l = int(input("大小:"))
    saveit = input("是否保存:")
    print("生成中...")
    e = time.time()
    alist = []
    aa = 0
    need = []
    for j in range(2 * a + 1):
        if aa == 0:
            aa = 1
            alistone = []
            for i in range(2 * b + 1):
                alistone.append(1)
            alist.append(alistone)
        else:
            aa = 0
            alistone = []
            bb = 0
            for i in range(2 * b + 1):
                if bb == 0:
                    bb = 1
                    alistone.append(1)
                else:
                    bb = 0
                    need.append((j, i))
                    alistone.append(0)
            alist.append(alistone)
    alist[0][1] = 0
    alist[-1][-2] = 0
    x = 1
    y = 1
    need.remove((1, 1))
    listing = []
    while len(need) > 0:
        aroundit = []
        try:
            if x - 2 < 0:
                print(1 + "1")
            alist[x - 2][y] = 0
            if (x - 2, y) in need:
                aroundit.append("alist[x-1][y],x=(0,x-2)")
        except:
            while False:
                print()
        try:
            alist[x + 2][y] = 0
            if (x + 2, y) in need:
                aroundit.append("alist[x+1][y],x=(0,x+2)")
        except:
            while False:
                print()
        try:
            alist[x][y + 2] = 0
            if (x, y + 2) in need:
                aroundit.append("alist[x][y+1],y=(0,y+2)")
        except:
            while False:
                print()
        try:
            if y - 2 < 0:
                print(1 + "1")
            alist[x][y - 2] = 0
            if (x, y - 2) in need:
                aroundit.append("alist[x][y-1],y=(0,y-2)")
        except:
            while False:
                print()
        if len(aroundit) > 0:
            listing.append((x, y))
            exec(random.choice(aroundit))
            need.remove((x, y))
        else:
            x, y = listing[-1]
            listing.pop()
    x2 = 0
    y2 = 1
    listing2 = []
    while not (alist[-1][-2] == 2):
        alist[x2][y2] = 3
        around2 = []
        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 - 1 < 0:
                print(1 + "1")
            if alist[x2][y2 - 1] == 0:
                around2.append("y2=y2-1")
        except:
            while False:
                print()
        try:
            if x2 - 1 < 0:
                print(1 + "1")

            if alist[x2 - 1][y2] == 0:
                around2.append("x2=x2-1")
        except:
            while False:
                print()
        if len(around2) > 0:
            listing2.append((x2, y2))
            exec(around2[0])
        else:
            alist[x2][y2] = 2
            x2, y2 = listing2[-1]
            listing2.pop()
    alist[-1][-2] = 3
    for i in range(len(alist)):
        for j in range(len(alist[0])):
            if alist[i][j] == 2:
                alist[i][j] = 0
    print("完成!用时{}秒".format(time.time() - e))
    if saveit == "1":
        ccc = askdirectory()
        h = ""
        bbbbb = 1
        while True:
            try:
                open("{}/{}×{}迷宫{}.png".format(ccc, a, b, h), "r")
                open("{}/{}×{}迷宫(正确线路){}.png".format(ccc, a, b, h), "r")
                h = "({})".format(bbbbb)
            except:
                break
            bbbbb += 1
    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")
    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 = 0
    kkk=0
    while True:
        if kkk==1:
            break
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                print()
                kkk=1
            if event.type == pygame.MOUSEBUTTONDOWN:
                if aaaaaaa == 1:
                    aaaaaaa = 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='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 = 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')
                    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()

原本的迷宫生成器每次打开只能生成一个迷宫,而每次打开程序都会有加载时间,效率不高。新修改的生成器,可以在上一个迷宫关闭后回到询问信息的程序,以此实现在以此打开程序后重复生成迷宫(这样的话,其实Sys库便不需要使用了,但在代码中我并未给予删除)。

另外,原有寻路算法随机性大,容易走弯路,速度较慢。同时,更新寻路算法,采用先向右优先,然后向下,再向上,最后向左优先的方式。寻路方向的优先安排使寻路更具针对性,更容易更快、更有效地到达目的地。

[En]

In addition, the original pathfinding algorithm is random, easy to take detours, and the speed is relatively slow. At the same time, update the pathfinding algorithm, using priority to the right, then down, up again, and finally to the left priority. The priority arrangement of the pathfinding direction makes the pathfinding more targeted and makes it easier to reach the destination faster and more effectively.

Original: https://www.cnblogs.com/godforever/p/16458100.html
Author: GodForever
Title: Python迷宫生成器

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/499115/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球