最近看到一个新问题,老鼠走迷宫,原题是c版本的,想写成python版本。一个简单迷宫的实现,当中还有很多问题,一步一步来吧,人笨慢慢学习。
说明:
老鼠走迷宫是递归求解的基本题型,我们在二维阵列中使用2表示迷宫墙壁,使用1表示老鼠行走的路径,试以程
式求出由入口至出口的路径。
解法:
老鼠的走法有上,下,左,右四个方向,在每前进一格之后就选一个方向前进,无法前进时退回上一步选择下一个可前
进方向,如此在阵列中依序测试四个方向,知道走到出口为至。这是返回的基本题,请直接看程式应就可以理解
*/
从网上搜了一下,网上很多版本,大多都是反复递归,出栈和调用,比较复杂,慢慢学习吧,上一个简单版本,思路来自sinly100,看原版请移步。
看代码切记一行行读下去,看代码每一行的作用对象,理解含义,平时一目十行的阅读方式不是初学者的方法。
这是一个5 * 5数组排列:
我们设计一个迷宫:
注意此迷宫就一条通路,我们先来检验一下自己的设计思路。
1、用一个列表source存储迷宫图,一个列表route_stack存储路线图,一个列表route_history存储走过的点,起点(0,0),终点(4,4);
2、老鼠在每个点都有上下左右四种方案可选,因此我们需要设计4种上下左右四种方法;
3、最后做一个循环,如果当前点不是(4,4)的话就依次执行上下左右四种方法,但是也是一些必要的限制条件:
(1)、比如尝试走过的点不会再尝试走;
(2)、在四周的围墙,无法再执行越过围墙的操作。
上代码(代码里面有注释):
#!/user/bin/env.python
# _*_ coding:utf-8 _*_
# _author:poiuyds
"""
此方法不一定是最优化的解,在仅存在一种解法时正确,当存在多种解法时明显不是
"""
# 路线图
route_stack = [[0, 0]]
# 走过的点
route_history = [[0, 0]]
# 迷宫图
source = [[0, 0, 1, 0, 1],
[1, 0, 0, 0, 1],
[0, 0, 1, 1, 0],
[0, 1, 0, 0, 0],
[0, 0, 0, 1, 0] ]
# for i in source:
# print(i)
# for j in i:
# print(j)
# 上行函数
def up(location):
# 横坐标为0,无法再向上走
if location[0] == 0:
return False
else:
# 纵坐标不变,横坐标减1(向上)
new_location = [location[0]-1, location[1]]
# 已经尝试过的点不会尝试第二次
if new_location in route_history:
return False
# 碰到墙不走
elif source[new_location[0]][new_location[1]] == 1:
return False
else:
route_stack.append(new_location)
route_history.append(new_location)
return True
# 下行函数
def down(location):
# 横坐标为4,将不会下行
if location[0] == 4:
return False
else:
new_location = [location[0]+1, location[1]]
if new_location in route_history:
return False
elif source[new_location[0]][new_location[1]] == 1:
return False
else:
route_stack.append(new_location)
route_history.append(new_location)
return True
# 左行函数
def left(location):
# 纵坐标为0,不会左行
if location[1] == 0:
return False
else:
new_location = [location[0], location[1]-1]
if new_location in route_history:
return False
elif source[new_location[0]][new_location[1]] == 1:
return False
else:
route_stack.append(new_location)
route_history.append(new_location)
return True
# 右行函数
def right(location):
# 纵坐标为0,不会右行
if location[1] == 4:
return False
else:
new_location = [location[0], location[1]+1]
if new_location in route_history:
return False
elif source[new_location[0]][new_location[1]] == 1:
return False
else:
route_stack.append(new_location)
route_history.append(new_location)
return True
# 出发点
lo = [0, 0]
# 主函数
while route_stack[-1] != [4, 4]:
if up(lo):
lo = route_stack[-1]
# continue语句用来告诉Python跳过当前循环的剩余语句,然后继续进行下一轮循环
continue
if down(lo):
lo = route_stack[-1]
continue
if left(lo):
lo = route_stack[-1]
continue
if right(lo):
lo = route_stack[-1]
continue
# 将正确的路线点依次弹出
route_stack.pop()
# 将弹出点赋给lo继续下一次尝试
lo = route_stack[-1]
print(route_stack)
运行结果:
[[0, 0], [0, 1], [1, 1], [2, 1], [2, 0], [3, 0], [4, 0], [4, 1], [4, 2], [3, 2], [3, 3], [3, 4], [4, 4]]
我们再换一个迷宫尝试一下(存在多种方案),验证一下此解法是否最优解
运行结果:
[
[0, 0], [1, 0], [2, 0], [3, 0], [4, 0], [4, 1], [4, 2],
[5, 2], [5, 3], [5, 4], [4, 4], [3, 4], [3, 5], [3, 6],
[2, 6], [2, 7], [3, 7], [4, 7], [5, 7], [6, 7], [7, 7]
]
换成直观的路径图:
可以明显看出来,此方案明显不是最短路径。
然后,我们分析一下代码的运行顺序,可以看出,我们这种方法明显的缺陷就是这一部分:
if up(lo):
lo = route_stack[-1]
# continue语句用来告诉Python跳过当前循环的剩余语句,然后继续进行下一轮循环
continue
if down(lo):
lo = route_stack[-1]
continue
if left(lo):
lo = route_stack[-1]
continue
if right(lo):
lo = route_stack[-1]
continue
该代码是按照up、down、left、right的顺序依次尝试,当有一条通路ok时,就不会尝试别的顺序了。如果按照此种方法想要尝试出最短路径,那么我们需要尝试4*4共16种方案。
才疏学浅,最短路径的算法暂时还不会写,日后学习到了有思路的时候一定补上,如果有思路的大佬请指点一下萌新。