近来学习数据结构,书中给出练习题,走出迷宫,很有意思,便摸索了两天,终于,实现了部分功能。
这个图是很直观的,入口在左上角,出口在右下角,只有白色的位置可以走,但一次只能走一格,好了,怎么实现的呢,下面谈谈我的想法吧!
由于之前弄过数独,因此对深度优先颇为喜欢,故而思考在这里能否照搬。
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的位置换成如下
程序运行结果如下
发现,结果也还不错,差强人意,至于为什么会出现这样的蛇形走位,其实是跟算法有关的,这个地方使用的是深度优先,它并没有考虑最短的问题,广度优先似乎更适合来解决这个问题,还在学习当中,等会了,再来更新对比一下。