演算法:棧與佇列的經典案例,模擬迷宮演算法
阿新 • • 發佈:2018-12-04
模擬迷宮
# 1代表牆壁0代表通道
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起點 x2終點"""
stack = [(x1, y1)]
# 棧不空就迴圈(棧空代表沒有路了)
while len(stack) > 0:
curNode = stack[-1] # 當前節點位置
if curNode[0] == x2 and curNode[1] == y2:
print('找到迷宮出路')
for p in stack:
print(p)
break
# 下一個點 上(x-1,y)、下(x+1,y)、左(x,y-1)、右(x,y+1)
for di in dirs:
nextNode = di(curNode[0], curNode[1])
# 如果下一個節點能走
if maze[nextNode[0]][nextNode[1]] == 0:
# 能走就加到棧裡
stack.append(nextNode)
maze[nextNode[0]][nextNode[1]] = 2 # 隨便標記一個數代表之前走過
break
else:
# 如果一個都找不到就回退
maze[curNode[0]][curNode[1]] = 2 # 這個位置也要標記為走過了
stack.pop() # 出棧
else:
print('該迷宮沒有出路')
return False
# 測試效果
maze_path(1, 1, 8, 8)
佇列思路 == 深度優先搜尋
from collections import deque
# 封裝四個方向列表
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為記錄而已
# 佇列空代表沒有路
while len(queue) > 0:
cur_Node = queue.popleft() # 從左邊出去
path.append(cur_Node) # 加入
if cur_Node[0] == x2 and cur_Node[1] == y2:
print('找到迷宮出路')
print_r(path)
return True
for di in dirs:
# 下一個節點
next_node = di(cur_Node[0], cur_Node[1])
# 如果可以走就進隊
if maze[next_node[0]][next_node[1]] == 0:
# len(path)-1) 表示 cur_Node在當前的下標
queue.append((next_node[0], next_node[1], len(path) - 1))
maze[next_node[0]][next_node[1]] = 2 # 標記已走過
return False
# 測試效果
maze_path_queue(1, 1, 8, 8)