目 录
1. 迷宫问题描述
问题背景:
给你一个 m x n 的迷宫矩阵 maze (下标从 0 开始),矩阵中有空格子(用 '.' 表示)和墙体(用 '+' 表示)。同时给你迷宫的入口 entrance ,用 entrance = [entrancerow, entrancecol] 表示你一开始所在格子的行和列。每一步操作,你可以往 上,下,左 或者 右 移动一个格子。你不能进入墙所在的格子,你也不能离开迷宫。
求解目标:
你的目标是找到通往指定出口的路径 path 列表。出口是 maze 边界 上的 空格子,由用户指定。如果找不到,则返回空列表。
2. 迷宫问题代码实现
import copy
# 给你一个 m x n 的迷宫矩阵 maze (下标从 0 开始),
# 矩阵中有空格子(用 '.' 表示)和墙体(用 '+' 表示)。
test_maze=[["+",".","+",".",".","+",".",".","+",".",".",".","+","+",".",".",".",".","+","."],\
[".","+","+",".","+",".",".",".","+","+","+",".","+",".",".","+",".","+","+","."],\
["+",".",".",".",".","+",".",".",".",".",".",".",".",".","+",".",".","+","+","."],\
[".",".",".","+","+",".",".",".","+",".","+",".",".","+",".",".","+",".",".","."],\
["+",".",".",".",".",".","+",".",".","+",".",".","+","+",".","+","+",".",".","."],\
[".","+",".",".",".",".","+",".","+",".",".",".",".",".",".","+",".","+","+","+"],\
[".",".",".","+",".",".","+",".","+","+",".","+",".",".",".",".",".","+",".","."],\
[".",".",".",".",".","+","+","+",".",".",".","+",".","+","+","+","+",".",".","."],\
[".",".","+",".",".","+",".","+",".",".","+",".",".",".",".",".",".",".","+","."],\
[".",".",".",".",".",".","+",".","+",".",".",".","+",".","+",".",".",".","+","."],\
[".","+",".","+",".",".","+",".","+",".",".","+",".","+",".",".",".",".",".","+"],\
[".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".","."],\
["+","+","+","+",".",".","+",".",".",".","+",".",".","+","+","+",".",".",".","."],\
[".",".","+","+",".","+",".",".",".",".",".","+","+",".",".","+",".",".",".","."],\
[".",".",".","+",".",".",".",".",".",".",".","+",".",".",".",".","+",".",".","."],\
[".","+","+",".",".","+",".",".",".",".","+","+",".","+","+",".",".",".","+","."],\
["+",".",".",".",".",".","+",".",".",".",".","+",".",".",".",".",".",".",".","."],\
[".",".",".",".","+",".",".",".","+",".",".","+",".",".",".",".",".",".",".","."]]
# m,n 分别是迷宫的行数、列数
m,n=len(test_maze),len(test_maze[0])
# 上下左右四个方向的偏移值
moves=[[-1,0],[1,0],[0,-1],[0,1]]
# 判断 pos 所在位置是否可以同行
# 同行的标准是在迷宫内,且不触及墙体
def passable(maze,pos):
if( -1<pos[0]<m and -1<pos[1]<n and maze[pos[0]][pos[1]]=="."):
return(True)
else:
return(False)
def remark(maze,pos):
maze[pos[0]][pos[1]]="d"
# 在 start、end 直接搜索一条通常的路,不要求最短
def find_passable_path(maze,pos,end):
path=[pos]
# remark 是为了标记此处已经到达,避免反复到同一个地方,形成死循环
remark(maze,pos)
# 如果已经到达出口处
if(pos==end):
return(path)
# 下一个地址是依据上下左右的顺序,依次去判断下一个地址能否到出口
for i in range(len(moves)):
next_pos=[pos[0]+moves[i][0],pos[1]+moves[i][1]]
# 如果下一个地址是通常的,既没有被标记,也没有触及墙体
if(passable(maze,next_pos)):
# 获得下一个地址到出口的路径
extend_path=find_passable_path(maze,next_pos,end)
# 如果得到的路径不为空,表示可以抵达出口
if(len(extend_path)>0):
path+=extend_path
#找到了一条路径,就此返回,不再等待其他路径
return(path)
# 这个很重要,当递归找不到出口时候,返回的 path 是空列表
return([])
3. 测试代码以及结果
3.1 测试代码实现
# 这个函数是为了测试用的,它会将搜索的路径用标号显示出来,
# 从而大家可以一目了然是否正确
def show_path(maze,path):
count=0
# 为了不影响原来的迷宫,深拷贝一个一模一样的迷宫,在此的基础上显示路径
show_maze=copy.deepcopy(maze)
for pos in path:
# 这是一行测试代码,在展示路径时候,顺便检查一下路径是否正确
# 如果路径上的位置原来就不通畅,那么则提示出来
if(not passable(show_maze,pos)):
print("Something is Wrong with {0}".format(pos))
else:
count+=1
show_maze[pos[0]][pos[1]]=str(count)
i=0
for row in show_maze:
print("{0} ==>".format(i),end=" ")
for tmp in row:
print(tmp.center(4),end=" ")
print()
i+=1
# 下面是测试代码
#为了做多次测试,不想影响原来的迷宫,所以进行深拷贝
def test_code(start,end):
global test_maze
copied_maze=copy.deepcopy(test_maze)
path=find_passable_path(copied_maze,start,end)
if(len(path)>0):
print("------------------------------------------- Found Path ------------------------------------------".center(100))
print(path)
print("------------------------------------------- To Show Path ------------------------------------------".center(100))
show_path(test_maze,path)
else:
print("------------------------------------------- Not found path------------------------------------------".center(100))
# 显示初始的迷宫状态
print("--------------------------------------Show Original Maze--------------------------------------".center(100))
show_path(copied_maze,[])
先看看初始的迷宫状态
3.2 测试用例结果
3.2.1 用例 1 以及结果
print("*"*60+" Test Case 1 "+"*"*60)
start=[11,0]
end=[17, 17]
test_code(start,end)
3.2.2 用例 2 以及结果
print("*"*60+" Test Case 2 "+"*"*60)
start=[11,0]
end=[0, 17]
test_code(start,end)
3.2.3 用例 3 以及结果
print("*"*60+" Test Case 3 "+"*"*60)
start=[0,6]
end=[0, 17]
test_code(start,end)
3.2.4 用例 4 以及结果
print("*"*60+" Test Case 4 "+"*"*60)
start=[0,3]
end=[17, 17]
test_code(start,end)
3.2.5 用例 5 以及结果
print("*"*60+" Test Case 5 "+"*"*60)
start=[17,3]
end=[1, 0]
test_code(start,end)