近来学习数据结构,书中给出练习题,走出迷宫,很有意思,便摸索了两天,终于,实现了部分功能。
这个图是很直观的,入口在左上角,出口在右下角,只有白色的位置可以走,但一次只能走一格,好了,怎么实现的呢,下面谈谈我的想法吧!
由于之前弄过数独,因此对深度优先颇为喜欢,故而思考在这里能否照搬。
1 为了易于处理,我将上图的迷宫表示成了数字矩阵的格式,就像下面这样
其中的数字0代表该位置不可走,1代表能走的位置,8代表入口,888代表出口。
2 当位于入口的位置时,这时需要判断下一步可以走哪里,这可以定义函数来实现;而为了不出现来回两步走的情况,这里采用的思想为前进一步的同时,删除来向的位置,比如说如果走到8的右边,那么,我就同时把原来位置的数换为-8,表示已走过。
3 2中的方法虽然可以避免来回死循环,但同时又产生了一个严重的问题,当自断来路而导致无路可走时怎么办,就像下面这样
当我自断来路后,却发现当走到如图红点的位置时,就没法走了,但当走进死胡同时,我要需要能够原路返回,因此,套路和数独中一样,我用列表把走的位置的信息记录下来,这样就能实现原路返回。
下面贴代码了
import numpy as np
#迷宫中0的位置代表墙,不能走
#8代表入口,1代表可走位置
#88代表出口
migong = '''
0 0 0 0 0 0 0 0 0 0
0 8 1 0 1 1 1 0 0 0
0 1 1 0 1 1 1 0 1 0
0 1 1 1 1 0 0 1 1 0
0 1 0 0 0 1 1 1 1 0
0 1 1 1 0 1 0 1 1 0
0 1 0 1 1 1 0 1 1 0
0 1 0 0 0 1 0 1 1 0
0 0 1 1 1 1 1 1 888 0
0 0 0 0 0 0 0 0 0 0'''
data = np.array(migong.split(), dtype = int).reshape((10,10))
def direction_set(data):
"""
函数功能,找到data中未被走过的地方,并同时记录该地方能够走的地方
"""
dir_set = {}
v, h = np.where(data > 0)
for i,j in zip(v, h):
key = str(i) + str(j)
if data[i, j+1] > 0: #该地方东邻块是否能走
dir_set[key] = [(i, j+1)]
if data[i+1, j] > 0: #该地方南邻块是否能走
if key in dir_set:
dir_set[key] += [(i+1, j)]
else:
dir_set[key] = [(i+1, j)]
#data[i, j-1]
if data[i, j-1] > 0: #该地方西邻块是否能走
if key in dir_set:
dir_set[key] += [(i, j-1)]
else:
dir_set[key] = [(i, j-1)]
#data[i-1, j]
if data[i-1, j] > 0: #该地方北邻块是否能走
if key in dir_set:
dir_set[key] += [(i-1, j)]
else:
dir_set[key] = [(i-1, j)]
return dir_set
step = [] #记录走的状态
key_old = '11' #起始位置
print(data, '\n')
while True:
#print(data)
direct_set = direction_set(data)
if key_old == '88': #当到达出口的位置,就不用继续往别处走
print(data) #打印出路线,其中走过的位置都用-8标示出来了
print([i for i,j in step])
break
if key_old in direct_set:
step += [(key_old, direct_set[key_old])]
data[int(key_old[0]), int(key_old[1])] = -8
coors = direct_set[key_old][0]
key_old = str(coors[0]) + str(coors[1])
else:
for i in range(len(step)):
huish = step.pop()
key = huish[0]
values = huish[1]
if len(values) == 1:
data[int(key[0]), int(key[1])] = 1
#print(data)
else:
key_old = str(values[1][0]) + str(values[1][1])
step += [(key, values[1:])]
#print(data)
break
运行结果如下
可以看到程序运行后确实找到了一条路径能够出去,下面把888的位置换一下,看是否能重新找到一条路径,注意如果换了出口的话,程序里面的判断什么时候退出就要更换一下,这点很重要。如888的位置换成如下
程序运行结果如下
发现,结果也还不错,差强人意,至于为什么会出现这样的蛇形走位,其实是跟算法有关的,这个地方使用的是深度优先,它并没有考虑最短的问题,广度优先似乎更适合来解决这个问题,还在学习当中,等会了,再来更新对比一下。