能够使用DFS找到路径,但无法为吃豆人指定正确方向 _ Python

1 投票
4 回答
15093 浏览
提问于 2025-04-17 02:24

我在伯克利网站的一个人工智能课程页面上找到一个作业,出于好玩我决定做一下。我需要为吃豆人游戏写一个深度优先搜索的代码,这样它就能找到自己的路径。问题是,吃豆人有时候会卡住。我先把代码贴出来,这样你们就能更清楚我在说什么了:

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)部分的代码,你会发现开放列表里包含了我访问过和扩展过的所有点。

路径文件里包含了吃豆人的移动方向。问题出现在我遇到的情况是,当我得到的两个后继点都是未访问过的时,吃豆人会选择一条通往死胡同的路,这样就需要回溯。我的开放列表可以做到这一点并找到解决方案,但我不知道怎么把回溯的方向添加到我的路径列表里。如果你去http://inst.eecs.berkeley.edu/~cs188/sp09/projects/search/search.html下载压缩包,然后把我的代码粘贴到search.py的深度优先搜索部分,你就能理解我的问题了。

4 个回答

1

我让它正常工作了,方法是确保每次移动的距离都是1。你代码中的一个问题是,最后它试图跳跃5或6个位置。确保每次移动的距离都是1,并且要反向移动,直到距离下一个目标的移动距离变成1。可以参考一下manhattanDistance()这个函数。

2

存储路径的方式是一个非常重要的话题,尤其是当你考虑到有些搜索可能会产生超过200步的路径时。想象一下,要遍历这么多次一个列表……这就像是 O(2^N)O(3^N) 的复杂度?用列表来存储路径作为搜索的工具并不是个好主意,特别是在使用广度优先搜索(BFS)时,或者当你有多个目标时(也就是说,可能会有多条路径经过同一个节点)。列表的复杂性和数据存储的效率都很低。

我建议使用链表作为路径存储的方式。当你把节点放入边缘时,可以把它们用一个唯一的键存入字典,然后只需要存储这个键。当你从边缘取出一个节点时,可以直接从字典中获取到这个节点的完整状态。

如果你的状态的一部分是这个节点在前一步的位置,那么你就能追溯到起点;结束节点链接到它后面的节点,后面的节点又链接到更前面的节点,依此类推。使用这种唯一键的系统可以让你在同一个点上有多条路径,而且数据开销非常低;不过,你还是需要理智地选择从边缘取出哪些路径。不过,每次你从边缘取出任何东西时,你都能用一个数字获取到它的完整路径。

3

一些提示:

  • 你检查的每个节点都应该包含你到达那里的数据。
  • 深度优先搜索(DFS)就像一个栈;你先把起始状态放进去。然后你把栈顶的元素拿出来,再把从这个元素可以继续走的节点放回栈里。
  • 因为你最终是想找到一条路径,所以每个节点的数据必须记录你的位置和到达那里的路径。

撰写回答