【问题标题】:Python Maze solving program: how to mark correct pathPython迷宫解决程序:如何标记正确的路径
【发布时间】:2014-09-15 23:52:47
【问题描述】:

我编写了一个递归解决迷宫的程序。它打开一个包含迷宫的文本文件,将其转换为列表列表,然后尝试递归解决它。 这是解决迷宫的部分:

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”是迷宫的尽头。它从迷宫的左下方开始,然后从那里开始。我希望用*标记正确的路径,但是它用*标记它所走的每条路径,即使它是它回溯的错误路径。

那么我该如何编辑我的代码,以便最后只有从开始到结束的正确路径用 * 标记

【问题讨论】:

  • 请先修正缩进!
  • @BasSwinckels 很抱歉,现在一切都解决了。

标签: python recursion maze


【解决方案1】:

您可以尝试在“回来的路上”重写路径,使用与用于创建访问路径的“*”不同的符号。

示例:替换

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's 编写。不过没测试过

【讨论】:

  • 这是正确的。它依赖于 Python 进行短路布尔求值这一事实,因此一旦其中一个搜索返回 True,其他搜索将不会被调用。 (否则你会标记多个正确的路径。)另外,没有必要在字母E上标记。
【解决方案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 时,你会在递归函数的末尾打印出正确的答案,当你回溯时,而不是当你第一次输入它时,因为你不知道先验,哪个方向是正确的。同样适用,例如找到并打印图中的欧拉环(如果有的话)。

【讨论】:

    【解决方案3】:

    作为“取消标记”路径的替代方法,您可以尝试以下操作:不要只返回 TrueFalse,而是返回您找到的路径,然后使用另一种方法绘制标记。

    当您找到"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 可能会更好,但这需要对代码进行一些重大重组,使用队列而不是递归来实现。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-09
      • 1970-01-01
      • 1970-01-01
      • 2014-05-07
      • 1970-01-01
      • 2019-02-01
      • 1970-01-01
      • 2011-03-07
      相关资源
      最近更新 更多