效果展示
基本思想
不论是DFS,BFS还是RFS,这些算法生成的迷宫本质上是一个二维矩阵网络形式的生成树,也就是说其中没有回路,同时从右上角的起点到迷宫中的每一点都有且仅有一条路径,当然,到终点的路径也是唯一的。
这是一张用于生成迷宫的地图,左上角是淡黄色的是起点,右下角橙红色的是终点。黑色的是墙壁,我们在此基础上使用BFS算法从起点开始不断打通墙壁,直到在规则内无墙壁可以继续打通,则迷宫生成。下面来制定迷宫生成的基本规则:
- 只遍历(偶数,偶数)坐标的墙壁,如果需要打通,则顺带打通两点之间带奇数坐标的墙壁。
🌟BFS算法
BFS在迷宫生成中的原理
从当前通路的末端遍历该层每一个可扩展点的每一条可能拓展路径进行扩展(遍历过程中的每一次选取都是随机的),如果该层遍历结束,就进行下一层的遍历。
第一层:
第二层:
第三层
第四层
函数
def BFScreatwall(chess_number):
'''
生成迷宫,有路为0,墙为1,输入棋盘大小,为奇数
return:一个储存全局地图信息的二维数组,0为无墙,1为有墙
'''
wallcell=[]
maze_creator_process=[]
neighborcell=[[]]
maincell=[]
#初始状态下,迷宫内所有点都是墙壁,只有满足条件,节点才会由墙壁变成通路,而且节点和相邻选中非节点之间的阻碍打破
wallcell=[[1]*chess_number for i in range(chess_number)]
wallcell[start_posx][start_posy]=0
maze_creator_process.append(deepcopy(wallcell))
neighborcell[0].append(startpos)
con=1 #循环旗帜
while con:
thislayer=1
neighborcell.append([])
layer=len(neighborcell)-2
while thislayer:
#对一层来说,先获得这一层所有格子的坐标,再获得下一层可能的所有格子坐标
nextcell=[]
x=[]
y=[]
#下面遍历该层所有格子的横纵坐标,得到下层目前所有符合要求的格子横纵坐标集合,因为每个格子有四个方向可以延伸,所以分上下左右四种情况进行讨论,如果超出范围或该位置格子已存在则不能向此方向延伸。
for i in neighborcell[layer]:
x.append(i[0])
y.append(i[1])
if x[-1]-2>=1 and wallcell[x[-1]-2][y[-1]] ==1 and wallcell[x[-1]-1][y[-1]] == 1 and wallcell[x[-1]-3][y[-1]]==1 and wallcell[x[-1]-2][y[-1]+1]==1 and wallcell[x[-1]-2][y[-1]-1]==1:
nextcell.append([x[-1]-2,y[-1]])
if x[-1]+2<=chess_number-2 and wallcell[x[-1]+2][y[-1]] ==1 and wallcell[x[-1]+1][y[-1]] == 1 and wallcell[x[-1]+3][y[-1]]==1 and wallcell[x[-1]+2][y[-1]+1]==1 and wallcell[x[-1]+2][y[-1]-1]==1:
nextcell.append([x[-1]+2,y[-1]])
if y[-1]-2>=1 and wallcell[x[-1]][y[-1]-2]==1 and wallcell[x[-1]][y[-1]-3] ==1 and wallcell[x[-1]][y[-1]-1] == 1 and wallcell[x[-1]-1][y[-1]-2]==1 and wallcell[x[-1]+1][y[-1]-2]==1:
nextcell.append([x[-1],y[-1]-2])
if y[-1]+2<=chess_number-2 and wallcell[x[-1]][y[-1]+2] ==1 and wallcell[x[-1]][y[-1]+1] == 1 and wallcell[x[-1]][y[-1]+3]==1 and wallcell[x[-1]-1][y[-1]+2]==1 and wallcell[x[-1]+1][y[-1]+2]==1:
nextcell.append([x[-1],y[-1]+2])
try:
#随机选一个符合要求的邻居作为下一层真正的邻居
num=random.randint(0,len(nextcell)-1)
neighborcell[layer+1].append([nextcell[num][0],nextcell[num][1]])
#邻居和改邻居与上一层之间的墙均需要被打通,往上下左右四个方向打通,所以分四种情况
wallcell[nextcell[num][0]][nextcell[num][1]]=0
for i in range(len(neighborcell[layer])):
if nextcell[num]==[x[i]-2,y[i]]:
wallcell[x[i]-1][y[i]]=0
break
elif nextcell[num]==[x[i]+2,y[i]]:
wallcell[x[i]+1][y[i]]=0
break
elif nextcell[num]==[x[i],y[i]-2]:
wallcell[x[i]][y[i]-1]=0
break
elif nextcell[num]==[x[i],y[i]+2]:
wallcell[x[i]][y[i]+1]=0
break
maze_creator_process.append(deepcopy(wallcell))
except:
#这一层中已经不存在可能的探索路径
thislayer=0
#当所有的偶数格子(横纵坐标都是偶数)被打通,结束遍历
odd1=0
con=0
for y in wallcell:
if odd1%2==1:
odd2=0
for x in y:
if odd2%2==1:
if x==1:
con=1
break
odd2+=1
if con==1:
break
odd1+=1
return wallcell,maze_creator_process