我写了一个程序,递归地解决了一个迷宫。它打开一个包含迷宫的文本文件,将其转换为列表列表,然后尝试以递归方式解决它。 这是解决迷宫的部分:
def search(x,y, mazeList):
# returns True if it has found end of maze
if mazeList[x][y] == 'E':
return True
# returns False if it encounters a wall
elif mazeList[x][y] == '-':
return False
elif mazeList[x][y] == '+':
return False
elif mazeList[x][y] == "|":
return False
# returns False if it finds a visited path
elif mazeList[x][y] == '*':
return False
# marks path with '*'
mazeList[x][y] = '*'
# recursive search
if ((search(x+1, y, mazeList))
or (search(x, y-1, mazeList))
or (search(x-1, y, mazeList))
or (search(x, y+1, mazeList))):
return True
return False
在迷宫中,' - ','+'和'|'弥补迷宫的墙壁,空的空间可以导航,'E'是迷宫的终点。它从迷宫的左下方开始,然后从那里开始。我希望用*标记正确的路径,但是它标记了*所采用的每条路径,即使它是错误的路径,也可以从中回溯。
那么如何编辑我的代码,以便最终只有从开始到结束的正确路径标有*
答案 0 :(得分:2)
您可以尝试使用与用于制作访问路径的“*”不同的符号重写“返回途中”的路径。
示例:替换
if mazeList[x][y] == 'E':
return True
带
if mazeList[x][y] == 'E':
mazeList[x][y] = 'o'
return True
和
if ((search(x+1, y, mazeList))
or (search(x, y-1, mazeList))
or (search(x-1, y, mazeList))
or (search(x, y+1, mazeList))):
return True
与
if ((search(x+1, y, mazeList))
or (search(x, y-1, mazeList))
or (search(x-1, y, mazeList))
or (search(x, y+1, mazeList))):
mazeList[x][y] = 'o'
return True
希望这条路可以写成o。虽然没有测试
答案 1 :(得分:2)
简而言之,只要return True
,就将单元格标记为属于正确的路径。你必须用星星以外的东西来标记它。此外,一旦你找到了一个给你真实的方向,就不要尝试其他方向。 (更新:Python确实支持短路布尔评估,但以下代码不依赖它。)。所以你可以这样写:
dx = [1, -1, 0, 0] # better define dx and dy globally
dy = [0, 0, 1, -1]
for i in range(4):
if search(x+dx[i], y+dy[i], mazeList):
mazeList[x][y] = '!'
return True
return False
第一部分可以更简洁:
if mazeList[x][y] == 'E':
return True
elif mazeList[x][y] != ' ':
return False
else:
或者,您可以使用mazeList[x][y] in ['+', '-']
。
一般情况下,当你做某种Depth-first search时,你会在递归函数结束时打印出正确的答案,当你回溯时,而不是在你第一次进入它时,就像你没有知道先验,哪个方向是正确的。同样适用于在图表中查找和打印欧拉循环(如果有)。
答案 2 :(得分:0)
除了“取消标记”路径之外,您可以尝试以下操作:不是仅返回True
或False
,而是返回您找到的路径,然后使用其他方法绘制标记。< / p>
当您找到"E"
时,只需返回[(x, y)]
即可。您的递归搜索可能如下所示:
for (dx,dy) in [(+1,0), (-1,0), (0,+1), (0,-1)]:
path = search(x+dx, y+dy, mazeList)
if path: # path is a (non-empty) list
return [(x, y)] + path
随着递归调用的返回,这将逐渐构建并返回目标的路径,从目标开始。
当然,由于您依赖于标记的路径以避免重新访问以前的位置,因此您需要一些其他方法,例如:以前访问过的地点的全球set
。
另请注意,您的算法是深度优先搜索,因此无法找到目标的最短,但任何路径。为此使用breadth-first-search可能更好,但这需要对代码进行一些重大重组,使用队列而不是递归来实现。