给一个二维列表,表示迷宫(0表示通道,1表示围墙)。给出算法,求一条走出迷宫的路径。
栈——深度优先搜索(一条路走到黑)
- 也叫回溯法
- 思路:从一个节点开始,任意找下一个能走的点,当找不到能走的点时,退回上一个点寻找是否有前途方向的点。使用栈存储当前路径。
maze=[
[1,1,1,1,1,1,1,1,1,1],
[1,0,0,1,0,0,0,1,0,1],
[1,0,0,1,0,0,0,1,0,1],
[1,0,0,0,0,1,1,0,0,1],
[1,0,1,1,1,0,0,0,0,1],
[1,0,0,0,1,0,0,0,0,1],
[1,0,1,0,0,0,1,0,0,1],
[1,0,1,1,1,0,1,1,0,1],
[1,1,0,0,0,0,0,0,0,1],
[1,1,1,1,1,1,1,1,1,1]
]
#封装一个列表表示四个位置表达式
dirs=[
lambda x,y:(x+1,y),
lambda x,y:(x-1,y),
lambda x,y:(x,y-1),
lambda x,y:(x,y+1)
]
def maze_path(x1,y1,x2,y2):#x1,y1表示起点位置,x2,y2表示终点位置
stack=[]#空栈
stack.append((x1,y1))
while(len(stack)>0):#当栈不空时
curNode=stack[-1]#当前节点
if curNode[0]==x2 and curNode[1]==y2:
#走到终点了
for p in stack:
print(p)
return True
#(x,y)四个方向:上:(x-1,y),下:(x+1,y),左:(x,y-1),右:(x,y+1)
for dir in dirs:
nextNode=dir(curNode[0],curNode[1])
#如果下一个节点能走
if maze[nextNode[0]][nextNode[1]]==0:
stack.append(nextNode)
maze[nextNode[0]][nextNode[1]]=2#2表示该位置已经走过
break#能找到一个就break
else:#如果没有找到出栈再找
maze[nextNode[0]][nextNode[1]]=2
stack.pop()
else:
print("没有路")
return False
maze_path(1,1,8,8)
问题:路径不一定是最短的
队列——广度优先搜索
思路:从一个节点开始,寻找所有接下来能继续走的点,继续不断寻找,知道找到出口。使用队列存储当前正在考虑的节点
from collections import deque
maze=[
[1,1,1,1,1,1,1,1,1,1],
[1,0,0,1,0,0,0,1,0,1],
[1,0,0,1,0,0,0,1,0,1],
[1,0,0,0,0,1,1,0,0,1],
[1,0,1,1,1,0,0,0,0,1],
[1,0,0,0,1,0,0,0,0,1],
[1,0,1,0,0,0,1,0,0,1],
[1,0,1,1,1,0,1,1,0,1],
[1,1,0,0,0,0,0,0,0,1],
[1,1,1,1,1,1,1,1,1,1]
]
#封装一个列表表示四个位置表达式
dirs=[
lambda x,y:(x+1,y),
lambda x,y:(x-1,y),
lambda x,y:(x,y-1),
lambda x,y:(x,y+1)
]
def print_r(path):
real_path=[]
i=len(path)-1
while i>=0:
real_path.append(path[i][0:2])
i=path[i][2]
real_path.reverse()
for node in real_path:
print(node)
def maze_path_queue(x1,y1,x2,y2):
#定义一个队列
queue=deque()
path=[]
queue.append((x1,y1,-1))#起点进队,-1表示吧位置x1,y1带进来的节点的位置
while len(queue)>0:#当队列不空时循环
cur_node=queue.popleft()
path.append(cur_node)
if cur_node[0]==x2 and cur_node[1]==y2:
#到达终点
print(path)
return True
for dir in dirs:
#如果有几个方向可以走,就把所有的都加到队列里
next_node=dir(cur_node[0],cur_node[1])
if maze[next_node[0]][next_node[1]]==0:
queue.append((next_node[0],next_node[1],len(path)-1))#len(path)-1表示cur_node的位置
maze[next_node[0]][next_node[1]]=2#走过以后标记为2
return False
maze_path_queue(1,1,8,8)