能够使用 DFS 找到路径,但无法指定 Pacman _ Python 的正确方向

Posted

技术标签:

【中文标题】能够使用 DFS 找到路径,但无法指定 Pacman _ Python 的正确方向【英文标题】:Able to find path using DFS but not able specify the right directions to Pacman _ Python 【发布时间】:2011-11-18 05:53:22 【问题描述】:

我正在完成一项在伯克利网站的 AI 课程页面上找到的作业,以获取乐趣。我需要为 pacman 游戏编写深度优先搜索,以便它可以找到它的路径。问题是 pacman 卡住了。我将首先粘贴代码以使我的意思更清楚:

import util

class SearchProblem:
  """
  This class outlines the structure of a search problem, but doesn't implement
  any of the methods (in object-oriented terminology: an abstract class).

  You do not need to change anything in this class, ever.
  """

  def getStartState(self):
     """
     Returns the start state for the search problem 
     """
     util.raiseNotDefined()

  def isGoalState(self, state):
     """
       state: Search state

     Returns True if and only if the state is a valid goal state
     """
     util.raiseNotDefined()

  def getSuccessors(self, state):
     """
       state: Search state

     For a given state, this should return a list of triples, 
     (successor, action, stepCost), where 'successor' is a 
     successor to the current state, 'action' is the action
     required to get there, and 'stepCost' is the incremental 
     cost of expanding to that successor
     """
     util.raiseNotDefined()

  def getCostOfActions(self, actions):
     """
          actions: A list of actions to take

     This method returns the total cost of a particular sequence of actions.  The sequence must
     be composed of legal moves
     """
     util.raiseNotDefined()


def tinyMazeSearch(problem):
  """
      Returns a sequence of moves that solves tinyMaze.  For any other
  maze, the sequence of moves will be incorrect, so only use this for tinyMaze
  """
  from game import Directions
  s = Directions.SOUTH
  w = Directions.WEST
  return  [s,s,w,s,w,w,s,w]

def depthFirstSearch(problem):

  """
  Search the deepest nodes in the search tree first [p 74].

  Your search algorithm needs to return a list of actions that reaches
  the goal.  Make sure to implement a graph search algorithm [Fig. 3.18].

  To get started, you might want to try some of these simple commands to
  understand the search problem that is being passed in:

  print 'Start:', problem.getStartState()
  print 'Is the start a goal?', problem.isGoalState(problem.getStartState())
  print 'Start's successors:', problem.getSuccessors(problem.getStartState())

  """

  # *** YOUR CODE HERE ***


  start = [problem.getStartState()]
  for item in start:
      Open=[item]
  State=[]
  Closed=[]
  Path=[]

  if problem.isGoalState(Open[0]) is True:
      return State
  else:
       while Open:
                visit= Open.pop()
                Closed.append(visit)
                if State: 
                  Path.append(State.pop())

                if problem.isGoalState(visit) is True:
                    print Closed
                    return Path
                else:
                    Successors= problem.getSuccessors(visit)
                    for index in Successors:
                            it=iter(index)
                            data=it.next()

                            if data not in Closed :
                              Open.append(data)
                              State.append(it.next())
                            else:
                              print Path

现在,如果您阅读我在 dfs 下的代码,您会看到打开列表包含我访问和扩展的所有点。

Path 文件包含为 pacman 设置的方向。当我面临我得到的两个继任者都未被访问的情况时,问题就出现了,我的 pacman 选择了一条通往死胡同的路径,因此它需要回溯。我的 Open 做到了并找到了解决方案,但我无法找到如何在我的路径列表中提供回溯方向的方法。如果你去http://inst.eecs.berkeley.edu/~cs188/sp09/projects/search/search.html并下载zip并将我的代码粘贴到dfs搜索下的search.py你就会明白我的问题。

【问题讨论】:

由于某种原因,我在 dfs 下的代码显示为红色,如果有人知道如何编辑它,请做! :) 【参考方案1】:

一些提示:

您检查的每个节点都应该封装您如何到达那里的数据。 DFS 就像一个堆栈;你从推动开始状态开始。您弹出堆栈,然后从您弹出的节点推回可以跟随的节点。 由于您最终要寻找路径,因此节点数据必须包含您的位置和到达那里的路径。

【讨论】:

是的,我有打开的路径。如果它到达死胡同,它会从堆栈中弹出一个元素,直到它获得一个未探索的节点。但是包含方向的路径列表表示南、北等。我无法在其中提供正确的路径,因为将意味着再次遍历访问的节点。如果您运行我的代码并打印路径,您将知道我在说什么! 你有太多的数据结构,这使得整个设置过于复杂。如果您只是要将数据从 State 移动到 Path,为什么还要有 State 和 Path 数组?我还建议只使用索引访问后继数据,而不是创建迭代器(即对于 issue.getSuccessors(visit) 中的后继数据:position = successor[0]、action = successor[1] 等)【参考方案2】:
 start = [problem.getStartState()]
  for item in start:
      Open=[item]
  Closed=[]
  Path=[]

  if problem.isGoalState(Open[0]) is True:
      return 
  else:
       count=0
       while Open:
                if count==0:
                  visit=Open.pop()
                else:
                  temp=Open.pop()
                  visit=temp[0]

                Closed.append(visit)                            
                if problem.isGoalState(visit) is True:
                    return Path
                else:
                    Successors= problem.getSuccessors(visit)
                    for index in Successors:
                            if index[0] not in Closed :
                              Open.append((index[0],index[1]))
                print Open
                count=count+1

我按照你说的修改了代码。现在我没有任何东西在路上。

找到解后打开这个-(1,1是解)

[((5, 4), 'South'), ((4, 5), 'West')]
[((5, 4), 'South'), ((3, 5), 'West')]
[((5, 4), 'South'), ((2, 5), 'West')]
[((5, 4), 'South'), ((1, 5), 'West')]
[((5, 4), 'South'), ((1, 4), 'South')]
[((5, 4), 'South'), ((1, 3), 'South')]
[((5, 4), 'South'), ((2, 3), 'East')]
[((5, 4), 'South'), ((2, 2), 'South')]
[((5, 4), 'South'), ((2, 1), 'South'), ((3, 2), 'East')]
[((5, 4), 'South'), ((2, 1), 'South'), ((4, 2), 'East')]
[((5, 4), 'South'), ((2, 1), 'South'), ((4, 3), 'North')]
[((5, 4), 'South'), ((2, 1), 'South'), ((5, 3), 'East')]
[((5, 4), 'South'), ((2, 1), 'South'), ((5, 4), 'North')]
[((5, 4), 'South'), ((2, 1), 'South')]
[((5, 4), 'South'), ((1, 1), 'West')]

现在,如果您会注意到当它获得三个列表成员时,它会采用一条死路,现在 Open 能够回溯并找到正确的路径,但我需要一种方法来以某种方式在 Path 变量中指定返回方向喜欢

例如 Path = ['south',west'west'........] 等

【讨论】:

【参考方案3】:

我确实做到了,确保每次移动只有 1 个距离。您的代码的问题之一是它最后尝试跳转 5 或 6 个位置。确保它所做的每一步都是一个并反向直到移动距离变为 1 到您的下一个目的地。提示 manhattanDistance()。

【讨论】:

我也有类似的问题。曼哈顿距离对我的事业有什么帮助?【参考方案4】:

当您考虑到某些搜索可能会导致路径超过 200 步时,如何存储路径是一个非常重要的主题。多次迭代列表.... O(2^N) 还是 O(3^N)?任何类型的搜索列表作为路径存储机制都是错误的答案,尤其是当您进入 BFS 并且任何时候您有多个目标时(意味着可以存在通过同一节点的多条路径)。列表的复杂性和数据存储是荒谬的。

我建议将链接列表作为一种路径存储机制。当您将节点推入边缘时,只需将它们键入具有唯一键的字典并按下键。然后,当您从边缘拉出一个节点时,您可以从字典中按原样获取整个状态。

如果您的状态的一部分是该状态在前一步中的节点,那么您有一条通往开始的路径;终端节点链接到它后面的那个,它链接到它后面的那个,等等。使用这样的唯一密钥系统允许多条路径通过同一点,数据成本极低;你仍然必须对你从边缘拉出的路径保持理性。然而,任何时候你从边缘拉出任何东西,你拉它的整个路径,只有 1 个数字。

【讨论】:

以上是关于能够使用 DFS 找到路径,但无法指定 Pacman _ Python 的正确方向的主要内容,如果未能解决你的问题,请参考以下文章

使用 BFS/DFS 寻找有向无环图中权重最大的路径

使用 DFS 查找两个节点之间的所有路径

迷宫救人——DFS小题

使用 DFS 检查二叉树中是不是存在路径不起作用

Unity - 使用正常分辨率混合参数覆盖

在矩阵中找到最长的递增路径