目录
以下为个人拙见和粗略思考,如有宝贵建议或想法欢迎您留言或私信交流!
-
算法前提
首先说明,该算法可进行寻路的迷宫样式需要为二维数组形式的迷宫,其中以0表示道路,以1表示墙壁,且路宽为1。如下图1。该图转化为迷宫地图可以看作图2。
图1 图2
符合上述条件的迷宫或处理成上述的迷宫便可进行该算法的本种实现。
-
算法思路
该算法总结经验于广度优先搜索和使用水找出迷宫出路的物理实验。
-
广度优先算法(BFS)
该算法致力于找出一个迷宫中从A到B的最短路径,思想上是每次寻得一个路口时(第一个路口除外)或走到死路时就返回到上一个路口,并选择另一方向进行探索。这样做的好处在于能尽可能大范围的探索迷宫,以来找到可能的最短路径,但同样的这样的方式带来了更大的计算量和计算时间。其算法的实现和缺点的解决在此不做具体阐述。
-
迷宫灌水
这是一个物理实验,只要迷宫的大小、密封性等符合条件,由于水的流动性和迷宫死路导致的气压,水就可以从入口进入并找到最短的出迷宫的道路。在这个实验里我们看到的反而是在迷宫气密性不足时水会尽力探索迷宫,并且所有道路都几乎同时探索的特性。水可以找到最短出路的迷宫如下图3。水可能无法顺利找到最短出路如下图4。
图3 图4
-
本算法思路
该算法的目的在于能否减少BFS的计算量达到快速并且有效的寻找最短迷宫解的方式,那么水的这种同时流淌探索的特性可以很好的解决,同时再从迷宫的终点开始“注水”,再利用迷宫中0与1的特性,便可以实现。
在这个算法中,水便是迷宫中的某个点距离目标点的走的步数长度,因为道路均为0,可以设目标点为2,则目标点周围上下左右四个内的全部0都赋值为3,代表多一格。再将所有赋为3的点的上下左右的为0的点赋值为4,以此类推,直到赋值进行到起点为止。然后再从起点开始,根据倒序寻找出一条唯一的且最短的迷宫解。
-
算法实现
import copy
#迷宫
maze= [
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
[1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1],
[1,0,1,0,1,1,1,0,1,0,1,0,1,1,1,0,1,0,1,1,1],
[1,0,1,0,1,0,0,0,1,0,0,0,0,0,1,0,1,0,0,0,1],
[1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,0,1,1,1,0,1],
[1,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,1,0,0,0,1],
[1,1,1,0,1,0,1,0,1,1,1,1,1,0,1,1,1,0,1,1,1],
[1,0,0,0,1,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,1],
[1,0,1,1,1,0,1,0,1,1,1,1,1,1,1,0,1,1,1,0,1],
[1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,1],
[1,0,1,1,1,0,1,1,1,1,1,1,1,0,1,0,1,1,1,0,1],
[1,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,1,0,0,0,1],
[1,1,1,0,1,1,1,0,1,1,1,1,1,0,1,0,1,0,1,1,1],
[1,0,0,0,1,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,1],
[1,0,1,1,1,0,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1],
[1,0,0,0,1,0,1,0,0,0,0,0,1,0,0,0,1,0,1,0,1],
[1,1,1,0,1,0,1,1,1,0,1,0,1,0,1,1,1,0,1,0,1],
[1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1],
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
]
#基础参数设置
start=(19,1)
end=(1,19)
head=['right']
end_h,end_l=end
#迷宫建立
maze_value=copy.deepcopy(maze)
maze_value[end_h][end_l] = 2
list_value_now=[end]
s_h,s_l = start
# print(s_h,s_l)
value = 3
while True:
for value_now in list_value_now:
v_h,v_l=value_now
# print(v_h,v_l)
if maze_value[v_h + 1][v_l] == 0:
maze_value[v_h + 1][v_l] = value
if maze_value[v_h][v_l - 1] == 0:
maze_value[v_h][v_l - 1] = value
if maze_value[v_h][v_l + 1] == 0:
maze_value[v_h][v_l + 1] = value
if maze_value[v_h - 1][v_l] == 0:
maze_value[v_h -1][v_l] = value
# print(maze_value)
list_value_now=[]
for i in range(21):
for j in range(21):
if maze_value[i][j] == value:
list_value_now.append((i,j))
value=value+1
if maze_value[19][1] !=0:
break
print("value OK")
# print(maze_value)
list_run=[start]
list_run_crossing=[]
list_run_value=[]
while True:
now = list_run[-1]
if now == end:
print(list_run)
print(list_run_crossing)
break
n_h,n_l = now
# print(n_h,n_l)
list_run_value.append(maze_value[n_h - 1][n_l])
list_run_value.append(maze_value[n_h][n_l - 1])
list_run_value.append(maze_value[n_h + 1][n_l])
list_run_value.append(maze_value[n_h][n_l + 1])
# print(list_run_value)
# print(maze_value[n_h][n_l])
for j in range(4):
if list_run_value[j] - maze_value[n_h][n_l] == -1:
flag_run = j
# print(flag_run)
list_run_value=[]
if head[-1] == 'right':
if flag_run == 0:
list_run.append((n_h - 1,n_l))
head.append('up')
if maze[n_h][n_l +1] + maze[n_h + 1][n_l] + maze[n_h - 1][n_l] + maze[n_h][n_l-1] <= 1:
list_run_crossing.append("2")
if flag_run == 1:
list_run.append((n_h,n_l - 1))
head.append('left')
if maze[n_h][n_l +1] + maze[n_h + 1][n_l] + maze[n_h - 1][n_l] + maze[n_h][n_l-1] <= 1:
list_run_crossing.append("3")
if flag_run == 2:
list_run.append((n_h + 1,n_l))
head.append('down')
if maze[n_h][n_l +1] + maze[n_h + 1][n_l] + maze[n_h - 1][n_l] + maze[n_h][n_l-1] <= 1:
list_run_crossing.append("4")
if flag_run == 3:
list_run.append((n_h,n_l + 1))
head.append('right')
if maze[n_h][n_l +1] + maze[n_h + 1][n_l] + maze[n_h - 1][n_l] + maze[n_h][n_l-1] <= 1:
list_run_crossing.append("1")
continue
if head[-1] == 'up':
if flag_run == 0:
list_run.append((n_h - 1,n_l))
head.append('up')
if maze[n_h][n_l +1] + maze[n_h + 1][n_l] + maze[n_h - 1][n_l] + maze[n_h][n_l-1] <= 1:
list_run_crossing.append("1")
if flag_run == 1:
list_run.append((n_h,n_l - 1))
head.append('left')
if maze[n_h][n_l +1] + maze[n_h + 1][n_l] + maze[n_h - 1][n_l] + maze[n_h][n_l-1] <= 1:
list_run_crossing.append("2")
if flag_run == 2:
list_run.append((n_h + 1,n_l))
head.append('down')
if maze[n_h][n_l +1] + maze[n_h + 1][n_l] + maze[n_h - 1][n_l] + maze[n_h][n_l-1] <= 1:
list_run_crossing.append("3")
if flag_run == 3:
list_run.append((n_h,n_l + 1))
head.append('right')
if maze[n_h][n_l +1] + maze[n_h + 1][n_l] + maze[n_h - 1][n_l] + maze[n_h][n_l-1] <= 1:
list_run_crossing.append("4")
continue
if head[-1] == 'down':
if flag_run == 0:
list_run.append((n_h - 1,n_l))
head.append('up')
if maze[n_h][n_l +1] + maze[n_h + 1][n_l] + maze[n_h - 1][n_l] + maze[n_h][n_l-1] <= 1:
list_run_crossing.append("3")
if flag_run == 1:
list_run.append((n_h,n_l - 1))
head.append('left')
if maze[n_h][n_l +1] + maze[n_h + 1][n_l] + maze[n_h - 1][n_l] + maze[n_h][n_l-1] <= 1:
list_run_crossing.append("4")
if flag_run == 2:
list_run.append((n_h + 1,n_l))
head.append('down')
if maze[n_h][n_l +1] + maze[n_h + 1][n_l] + maze[n_h - 1][n_l] + maze[n_h][n_l-1] <= 1:
list_run_crossing.append("1")
if flag_run == 3:
list_run.append((n_h,n_l + 1))
head.append('right')
if maze[n_h][n_l +1] + maze[n_h + 1][n_l] + maze[n_h - 1][n_l] + maze[n_h][n_l-1] <= 1:
list_run_crossing.append("2")
continue
if head[-1] == 'left':
if flag_run == 0:
list_run.append((n_h - 1,n_l))
head.append('up')
if maze[n_h][n_l +1] + maze[n_h + 1][n_l] + maze[n_h - 1][n_l] + maze[n_h][n_l-1] <= 1:
list_run_crossing.append("4")
if flag_run == 1:
list_run.append((n_h,n_l - 1))
head.append('left')
if maze[n_h][n_l +1] + maze[n_h + 1][n_l] + maze[n_h - 1][n_l] + maze[n_h][n_l-1] <= 1:
list_run_crossing.append("1")
if flag_run == 2:
list_run.append((n_h + 1,n_l))
head.append('down')
if maze[n_h][n_l +1] + maze[n_h + 1][n_l] + maze[n_h - 1][n_l] + maze[n_h][n_l-1] <= 1:
list_run_crossing.append("2")
if flag_run == 3:
list_run.append((n_h,n_l + 1))
head.append('right')
if maze[n_h][n_l +1] + maze[n_h + 1][n_l] + maze[n_h - 1][n_l] + maze[n_h][n_l-1] <= 1:
list_run_crossing.append("3")
continue
-
算法输出
该算法最终可以输出:
1.迷宫解的走法坐标信息2.一个普通小车的迷宫解走法信息(如左转右转)3.一个普通小车在所有拐点(如普通直角转弯、路口)的走法信息。
个人拙见,欢迎留言私信交流。