# -- coding: utf-8 --# ---------# Licensing Information: You are free to use or extend these projects for# educational purposes provided that (1) you do not distribute or publish# solutions, (2) you retain this notice, and (3) you provide clear# attribution to UC Berkeley, including a link to http://ai.berkeley.edu.# # Attribution Information: The Pacman AI projects were developed at UC Berkeley.# The core projects and autograders were primarily created by John DeNero# (denero@cs.berkeley.edu) and Dan Klein (klein@cs.berkeley.edu).# Student side autograding was added by Brad Miller, Nick Hay, and# Pieter Abbeel (pabbeel@cs.berkeley.edu)."""
In search.py, you will implement generic search algorithms which are called by
Pacman agents (in searchAgents.py).
"""import util
classSearchProblem:"""
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.
"""defgetStartState(self):"""
Returns the start state for the search problem.
"""
util.raiseNotDefined()defisGoalState(self, state):"""
state: Search state
Returns True if and only if the state is a valid goal state.
"""
util.raiseNotDefined()defgetSuccessors(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()defgetCostOfActions(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()deftinyMazeSearch(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]defdepthFirstSearch(problem):"""
Search the deepest nodes in the search tree first.
Your search algorithm needs to return a list of actions that reaches the
goal. Make sure to implement a graph search algorithm.
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 ***"# result用于记录访问的路径与顺序 visited用于记录是否被访问过
result =[]
visited =[]# 使用栈来模拟深度最深的节点先拓展的逻辑
stack = util.Stack()
start =(problem.getStartState(),[])# 将初始状态入栈
stack.push(start)whilenot stack.isEmpty():# 出栈的是栈顶元素 就是最近入栈的元素 就是深度最深的节点(state, path)= stack.pop()if problem.isGoalState(state):
result = path
breakif state notin visited:# 将该元素打上访问过了的标记
visited.append(state)for currState, currPath, cost in problem.getSuccessors(state):
newPath = path +[currPath]
newState =(currState, newPath)# 拓展节点状态全部入栈
stack.push(newState)# 因为是深搜 所以一条路走到底 能较快的找到一条路径return result
util.raiseNotDefined()defbreadthFirstSearch(problem):"""Search the shallowest nodes in the search tree first.""""*** YOUR CODE HERE ***"# 宽搜和深搜的代码没有变化 只是换了数据结构 采用queue# 但是实现逻辑完全不一样 因为 出栈和出队的区别 出栈出来的是最深的节点 出队出的是最浅的节点# 则访问的顺序就不一样 是一层一层的往下搜索 在单位权值的情况下 能找到一条最短路
result =[]
visited =[]
q = util.Queue()
start =(problem.getStartState(),[])
q.push(start)whilenot q.isEmpty():(state, path)= q.pop()if problem.isGoalState(state):
result = path
breakif state notin visited:
visited.append(state)for currState, currPath, cost in problem.getSuccessors(state):
newPath = path +[currPath]
newState =(currState, newPath)
q.push(newState)return result
util.raiseNotDefined()defuniformCostSearch(problem):"""Search the node of least total cost first.""""*** YOUR CODE HERE ***"# ucs和宽搜的代码没有大的变化 只是换了数据结构 采用PriorityQueue# 但是实现逻辑完全不一样 因为 采用的是堆 这里提供的的是小根堆 # 所以我们每次除了状态 还要放入一个优先级 每次弹出的都是优先级的值最小的状态 # 每次节点拓展的时候 getSuccessors函数都有给我们返回代价的 将节点的累计代价作为优先级 累计代价越小 优先级的值越小 越早出堆# ucs找最短路的时候是bfs的广义化 ucs允许权值可变 借助堆的特性 找到一条累计代价最小的路线# 因为每次都是出堆的时候都是当前代价最小的状态 那么达到最终状态的时候肯定就是全局的最小代价的路径
result =[]
visited =[]
heap = util.PriorityQueue()
start =(problem.getStartState(),[],0)
heap.push(start, start[2])whilenot heap.isEmpty():(state, path, cost)= heap.pop()if problem.isGoalState(state):
result = path
breakif state notin visited:
visited.append(state)for currState, currPath, currCost in problem.getSuccessors(state):
newPath = path +[currPath]
newCost = cost + currCost
newState =(currState, newPath, newCost)
heap.push(newState, newCost)return result
util.raiseNotDefined()defnullHeuristic(state, problem=None):"""
A heuristic function estimates the cost from the current state to the nearest
goal in the provided SearchProblem. This heuristic is trivial.
"""return0defaStarSearch(problem, heuristic=nullHeuristic):"""Search the node that has the lowest combined cost and heuristic first.""""*** YOUR CODE HERE ***"# astar 在代码的实现上其实和上面的ucs一样 但是他的放入堆的 优先级的值 除了累计代价还有一个启发函数的值# 启发函数返回这个状态距离最终状态的估算距离 因为ucs很好 但是很慢 加上启发不影响ucs的最优性 还能加速找到最短路# 这题其实我们只是简单的用它上面定义好的启发函数就好了 没有必要自己写
result =[]
visited =[]
heap = util.PriorityQueue()
start =(problem.getStartState(),[],0)
heap.push(start,0)whilenot heap.isEmpty():
state, path, cost = heap.pop()if state notin visited:
visited.append(state)if problem.isGoalState(state):
result = path
breakfor currState, currPath, currCost in problem.getSuccessors(state):
newPath = path +[currPath]
newCost = cost + currCost
newState =(currState, newPath, newCost)
heap.push(newState, newCost + heuristic(currState, problem))return result
util.raiseNotDefined()# Abbreviations
bfs = breadthFirstSearch
dfs = depthFirstSearch
astar = aStarSearch
ucs = uniformCostSearch
searchAgents.py
# -- coding: utf-8 --# ---------------# Licensing Information: You are free to use or extend these projects for# educational purposes provided that (1) you do not distribute or publish# solutions, (2) you retain this notice, and (3) you provide clear# attribution to UC Berkeley, including a link to http://ai.berkeley.edu.# # Attribution Information: The Pacman AI projects were developed at UC Berkeley.# The core projects and autograders were primarily created by John DeNero# (denero@cs.berkeley.edu) and Dan Klein (klein@cs.berkeley.edu).# Student side autograding was added by Brad Miller, Nick Hay, and# Pieter Abbeel (pabbeel@cs.berkeley.edu)."""
This file contains all of the agents that can be selected to control Pacman. To
select an agent, use the '-p' option when running pacman.py. Arguments can be
passed to your agent using '-a'. For example, to load a SearchAgent that uses
depth first search (dfs), run the following command:
> python pacman.py -p SearchAgent -a fn=depthFirstSearch
Commands to invoke other search strategies can be found in the project
description.
Please only change the parts of the file you are asked to. Look for the lines
that say
"*** YOUR CODE HERE ***"
The parts you fill in start about 3/4 of the way down. Follow the project
description for details.
Good luck and happy searching!
"""from game import Directions
from game import Agent
from game import Actions
import util
import time
import search
from math import*classGoWestAgent(Agent):"An agent that goes West until it can't."defgetAction(self, state):"The agent receives a GameState (defined in pacman.py)."if Directions.WEST in state.getLegalPacmanActions():return Directions.WEST
else:return Directions.STOP
######################################################## This portion is written for you, but will only work ## after you fill in parts of search.py ########################################################classSearchAgent(Agent):"""
This very general search agent finds a path using a supplied search
algorithm for a supplied search problem, then returns actions to follow that
path.
As a default, this agent runs DFS on a PositionSearchProblem to find
location (1,1)
Options for fn include:
depthFirstSearch or dfs
breadthFirstSearch or bfs
Note: You should NOT change any code in SearchAgent
"""def__init__(self, fn='depthFirstSearch', prob='PositionSearchProblem', heuristic='nullHeuristic'):# Warning: some advanced Python magic is employed below to find the right functions and problems# Get the search function from the name and heuristicif fn notindir(search):raise AttributeError(fn +' is not a search function in search.py.')
func =getattr(search, fn)if'heuristic'notin func.__code__.co_varnames:print('[SearchAgent] using function '+ fn)
self.searchFunction = func
else:if heuristic inglobals().keys():
heur =globals()[heuristic]elif heuristic indir(search):
heur =getattr(search, heuristic)else:raise AttributeError(heuristic +' is not a function in searchAgents.py or search.py.')print('[SearchAgent] using function %s and heuristic %s'%(fn, heuristic))# Note: this bit of Python trickery combines the search algorithm and the heuristic
self.searchFunction =lambda x: func(x, heuristic=heur)# Get the search problem type from the nameif prob notinglobals().keys()ornot prob.endswith('Problem'):raise AttributeError(prob +' is not a search problem type in SearchAgents.py.')
self.searchType =globals()[prob]print('[SearchAgent] using problem type '+ prob)defregisterInitialState(self, state):"""
This is the first time that the agent sees the layout of the game
board. Here, we choose a path to the goal. In this phase, the agent
should compute the path to the goal and store it in a local variable.
All of the work is done in this method!
state: a GameState object (pacman.py)
"""if self.searchFunction ==None:raise Exception("No search function provided for SearchAgent")
starttime = time.time()
problem = self.searchType(state)# Makes a new search problem
self.actions = self.searchFunction(problem)# Find a path
totalCost = problem.getCostOfActions(self.actions)print('Path found with total cost of %d in %.1f seconds'%(totalCost, time.time()- starttime))if'_expanded'indir(problem):print('Search nodes expanded: %d'% problem._expanded)defgetAction(self, state):"""
Returns the next action in the path chosen earlier (in
registerInitialState). Return Directions.STOP if there is no further
action to take.
state: a GameState object (pacman.py)
"""if'actionIndex'notindir(self): self.actionIndex =0
i = self.actionIndex
self.actionIndex +=1if i <len(self.actions):return self.actions[i]else:return Directions.STOP
classPositionSearchProblem(search.SearchProblem):"""
A search problem defines the state space, start state, goal test, successor
function and cost function. This search problem can be used to find paths
to a particular point on the pacman board.
The state space consists of (x,y) positions in a pacman game.
Note: this search problem is fully specified; you should NOT change it.
"""def__init__(self, gameState, costFn =lambda x:1, goal=(1,1), start=None, warn=True, visualize=True):"""
Stores the start and goal.
gameState: A GameState object (pacman.py)
costFn: A function from a search state (tuple) to a non-negative number
goal: A position in the gameState
"""
self.walls = gameState.getWalls()
self.startState = gameState.getPacmanPosition()if start !=None: self.startState = start
self.goal = goal
self.costFn = costFn
self.visualize = visualize
if warn and(gameState.getNumFood()!=1ornot gameState.hasFood(*goal)):print('Warning: this does not look like a regular search maze')# For display purposes
self._visited, self._visitedlist, self._expanded ={},[],0# DO NOT CHANGEdefgetStartState(self):return self.startState
defisGoalState(self, state):
isGoal = state == self.goal
# For display purposes onlyif isGoal and self.visualize:
self._visitedlist.append(state)import __main__
if'_display'indir(__main__):if'drawExpandedCells'indir(__main__._display):#@UndefinedVariable
__main__._display.drawExpandedCells(self._visitedlist)#@UndefinedVariablereturn isGoal
defgetSuccessors(self, state):"""
Returns successor states, the actions they require, and a cost of 1.
As noted in search.py:
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
"""
successors =[]for action in[Directions.NORTH, Directions.SOUTH, Directions.EAST, Directions.WEST]:
x,y = state
dx, dy = Actions.directionToVector(action)
nextx, nexty =int(x + dx),int(y + dy)ifnot self.walls[nextx][nexty]:
nextState =(nextx, nexty)
cost = self.costFn(nextState)
successors.append(( nextState, action, cost))# Bookkeeping for display purposes
self._expanded +=1# DO NOT CHANGEif state notin self._visited:
self._visited[state]=True
self._visitedlist.append(state)return successors
defgetCostOfActions(self, actions):"""
Returns the cost of a particular sequence of actions. If those actions
include an illegal move, return 999999.
"""if actions ==None:return999999
x,y= self.getStartState()
cost =0for action in actions:# Check figure out the next state and see whether its' legal
dx, dy = Actions.directionToVector(action)
x, y =int(x + dx),int(y + dy)if self.walls[x][y]:return999999
cost += self.costFn((x,y))return cost
classStayEastSearchAgent(SearchAgent):"""
An agent for position search with a cost function that penalizes being in
positions on the West side of the board.
The cost function for stepping into a position (x,y) is 1/2^x.
"""def__init__(self):
self.searchFunction = search.uniformCostSearch
costFn =lambda pos:.5** pos[0]
self.searchType =lambda state: PositionSearchProblem(state, costFn,(1,1),None,False)classStayWestSearchAgent(SearchAgent):"""
An agent for position search with a cost function that penalizes being in
positions on the East side of the board.
The cost function for stepping into a position (x,y) is 2^x.
"""def__init__(self):
self.searchFunction = search.uniformCostSearch
costFn =lambda pos:2** pos[0]
self.searchType =lambda state: PositionSearchProblem(state, costFn)defmanhattanHeuristic(position, problem, info={}):"The Manhattan distance heuristic for a PositionSearchProblem"
xy1 = position
xy2 = problem.goal
returnabs(xy1[0]- xy2[0])+abs(xy1[1]- xy2[1])defeuclideanHeuristic(position, problem, info={}):"The Euclidean distance heuristic for a PositionSearchProblem"
xy1 = position
xy2 = problem.goal
return((xy1[0]- xy2[0])**2+(xy1[1]- xy2[1])**2)**0.5###################################################### This portion is incomplete. Time to write code! ######################################################classCornersProblem(search.SearchProblem):"""
This search problem finds paths through all four corners of a layout.
You must select a suitable state space and successor function
"""def__init__(self, startingGameState):"""
Stores the walls, pacman's starting position and corners.
"""
self.walls = startingGameState.getWalls()
self.startingPosition = startingGameState.getPacmanPosition()
top, right = self.walls.height-2, self.walls.width-2
self.corners =((1,1),(1,top),(right,1),(right, top))for corner in self.corners:ifnot startingGameState.hasFood(*corner):print('Warning: no food in corner '+str(corner))
self._expanded =0# DO NOT CHANGE; Number of search nodes expanded# Please add any code here which you would like to use# in initializing the problem"*** YOUR CODE HERE ***"# 可以记录一些信息 但是貌似我没用到defgetStartState(self):"""
Returns the start state (in your state space, not the full Pacman state
space)
""""*** YOUR CODE HERE ***"# 初始状态 是一个位置和一个已访问的角落的列表 方便做目标测试的
startState =(self.startingPosition,[])return startState
util.raiseNotDefined()defisGoalState(self, state):"""
Returns whether this search state is a goal state of the problem.
""""*** YOUR CODE HERE ***"# 只要每个角落都访问过了 就满足了题意 就是true
isGoal =(len(state[1])==4)return isGoal
util.raiseNotDefined()defgetSuccessors(self, state):"""
Returns successor states, the actions they require, and a cost of 1.
As noted in search.py:
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
"""
successors =[]for action in[Directions.NORTH, Directions.SOUTH, Directions.EAST, Directions.WEST]:# Add a successor state to the successor list if the action is legal# Here's a code snippet for figuring out whether a new position hits a wall:# x,y = currentPosition# dx, dy = Actions.directionToVector(action)# nextx, nexty = int(x + dx), int(y + dy)# hitsWall = self.walls[nextx][nexty]"*** YOUR CODE HERE ***"# 只要不是墙 这个状态就是满足的 放入结果列表# 这里的状态要与我们定义的状态一致 满足这个就好了的
x, y = state[0]
visitedCorners = state[1]
dx, dy = Actions.directionToVector(action)
nextx, nexty =int(x + dx),int(y + dy)
hitswall = self.walls[nextx][nexty]
node =(nextx, nexty)ifnot hitswall:
visitedCornersList =list(visitedCorners)if node in self.corners:if node notin visitedCornersList:
visitedCornersList.append(node)
newState =(node, visitedCornersList)
successor =(newState, action,1)
successors.append(successor)
self._expanded +=1# DO NOT CHANGEreturn successors
defgetCostOfActions(self, actions):"""
Returns the cost of a particular sequence of actions. If those actions
include an illegal move, return 999999. This is implemented for you.
"""if actions ==None:return999999
x, y= self.startingPosition
for action in actions:
dx, dy = Actions.directionToVector(action)
x, y =int(x + dx),int(y + dy)if self.walls[x][y]:return999999returnlen(actions)defcornersHeuristic(state, problem):"""
A heuristic for the CornersProblem that you defined.
state: The current search state
(a data structure you chose in your search problem)
problem: The CornersProblem instance for this layout.
This function should always return a number that is a lower bound on the
shortest path from the state to a goal of the problem; i.e. it should be
admissible (as well as consistent).
"""
corners = problem.corners # These are the corner coordinates ((1, 1), (1, 12), (28, 1), (28, 12))
walls = problem.walls # These are the walls of the maze, as a Grid (game.py)"*** YOUR CODE HERE ***"# 启发函数是当前状态距离最终状态的距离# 我们选择探索 探索 距离最远的两个未访问节点 的距离的最小值作为启发函数的函数值# 其实就是 距离最远的两个未访问角落+当前点到两个点中较近的一个点的距离# 如果是只剩一个角落了 那更简单 直接返回当前点到角落的距离就好了# 之前的一个想法是 剩余角落之间的距离是恒定的 那么我们可以采用当前节点 距离 剩余角落的点的距离的最小值作为启发函数的函数值# 但是很可惜 有一个测试点过不去
x, y = state[0]
visitedCorners = state[1]
nonVisitedCorners =list(set(corners).difference(set(visitedCorners)))
distance =0# while (len(nonVisitedCorners) != 0):# tmp = []# for corner in nonVisitedCorners:# manhattanDistance = abs(x - corner[0]) + abs(y - corner[1])# tmp.append((manhattanDistance, corner))# manhattanDistance, corner = min(tmp)# distance += manhattanDistance# x = corner[0]# y = corner[1]# nonVisitedCorners.remove(corner)
path=((0,0),(0,0),0)for currentCorner in nonVisitedCorners:for selectedCorner in nonVisitedCorners:if currentCorner!=selectedCorner:
distance =abs(currentCorner[0]- selectedCorner[0])+abs(currentCorner[1]- selectedCorner[1])if(path[2]< distance):
path =(currentCorner,selectedCorner,distance)if(path[0]!=path[1]):
d1 =abs(x - path[0][0])+abs(y - path[0][1])
d2 =abs(x - path[1][0])+abs(y - path[1][1])
distance = path[2]+min(d1,d2)eliflen(nonVisitedCorners)==1:
distance =abs(x - nonVisitedCorners[0][0])+abs(y - nonVisitedCorners[0][1])return distance
classAStarCornersAgent(SearchAgent):"A SearchAgent for FoodSearchProblem using A* and your foodHeuristic"def__init__(self):
self.searchFunction =lambda prob: search.aStarSearch(prob, cornersHeuristic)
self.searchType = CornersProblem
classFoodSearchProblem:"""
A search problem associated with finding the a path that collects all of the
food (dots) in a Pacman game.
A search state in this problem is a tuple ( pacmanPosition, foodGrid ) where
pacmanPosition: a tuple (x,y) of integers specifying Pacman's position
foodGrid: a Grid (see game.py) of either True or False, specifying remaining food
"""def__init__(self, startingGameState):
self.start =(startingGameState.getPacmanPosition(), startingGameState.getFood())
self.walls = startingGameState.getWalls()
self.startingGameState = startingGameState
self._expanded =0# DO NOT CHANGE
self.heuristicInfo ={}# A dictionary for the heuristic to store informationdefgetStartState(self):return self.start
defisGoalState(self, state):return state[1].count()==0defgetSuccessors(self, state):"Returns successor states, the actions they require, and a cost of 1."
successors =[]
self._expanded +=1# DO NOT CHANGEfor direction in[Directions.NORTH, Directions.SOUTH, Directions.EAST, Directions.WEST]:
x,y = state[0]
dx, dy = Actions.directionToVector(direction)
nextx, nexty =int(x + dx),int(y + dy)ifnot self.walls[nextx][nexty]:
nextFood = state[1].copy()
nextFood[nextx][nexty]=False
successors.append((((nextx, nexty), nextFood), direction,1))return successors
defgetCostOfActions(self, actions):"""Returns the cost of a particular sequence of actions. If those actions
include an illegal move, return 999999"""
x,y= self.getStartState()[0]
cost =0for action in actions:# figure out the next state and see whether it's legal
dx, dy = Actions.directionToVector(action)
x, y =int(x + dx),int(y + dy)if self.walls[x][y]:return999999
cost +=1return cost
classAStarFoodSearchAgent(SearchAgent):"A SearchAgent for FoodSearchProblem using A* and your foodHeuristic"def__init__(self):
self.searchFunction =lambda prob: search.aStarSearch(prob, foodHeuristic)
self.searchType = FoodSearchProblem
deffoodHeuristic(state, problem):"""
Your heuristic for the FoodSearchProblem goes here.
This heuristic must be consistent to ensure correctness. First, try to come
up with an admissible heuristic; almost all admissible heuristics will be
consistent as well.
If using A* ever finds a solution that is worse uniform cost search finds,
your heuristic is *not* consistent, and probably not admissible! On the
other hand, inadmissible or inconsistent heuristics may find optimal
solutions, so be careful.
The state is a tuple ( pacmanPosition, foodGrid ) where foodGrid is a Grid
(see game.py) of either True or False. You can call foodGrid.asList() to get
a list of food coordinates instead.
If you want access to info like walls, capsules, etc., you can query the
problem. For example, problem.walls gives you a Grid of where the walls
are.
If you want to *store* information to be reused in other calls to the
heuristic, there is a dictionary called problem.heuristicInfo that you can
use. For example, if you only want to count the walls once and store that
value, try: problem.heuristicInfo['wallCount'] = problem.walls.count()
Subsequent calls to this heuristic can access
problem.heuristicInfo['wallCount']
"""
position, foodGrid = state
"*** YOUR CODE HERE ***"# print('\n'.join(['%s:%s' % item for item in problem.__dict__.items()]))# position, foodGrid = state# walls# startingGameState# print(position)# print(foodGridList)# print(problem.walls)# 这一题写的和上一题的启发函数一样 因为其实这种思路是通用的欸
foodGridList = foodGrid.asList()
distance =0
path=((0,0),(0,0),0)for currentFood in foodGridList:for selectedFood in foodGridList:if currentFood!=selectedFood:
distance =abs(currentFood[0]- selectedFood[0])+abs(currentFood[1]- selectedFood[1])if(path[2]< distance):
path =(currentFood,selectedFood,distance)if(path[0]!=path[1]):
d1 =abs(position[0]- path[0][0])+abs(position[1]- path[0][1])
d2 =abs(position[0]- path[1][0])+abs(position[1]- path[1][1])
distance = path[2]+min(d1,d2)eliflen(foodGridList)==1:
distance =abs(position[0]- foodGridList[0][0])+abs(position[1]- foodGridList[0][1])return distance
classClosestDotSearchAgent(SearchAgent):"Search for all food using a sequence of searches"defregisterInitialState(self, state):
self.actions =[]
currentState = state
while(currentState.getFood().count()>0):
nextPathSegment = self.findPathToClosestDot(currentState)# The missing piece
self.actions += nextPathSegment
for action in nextPathSegment:
legal = currentState.getLegalActions()if action notin legal:
t =(str(action),str(currentState))raise Exception('findPathToClosestDot returned an illegal move: %s!\n%s'% t)
currentState = currentState.generateSuccessor(0, action)
self.actionIndex =0print('Path found with cost %d.'%len(self.actions))deffindPathToClosestDot(self, gameState):"""
Returns a path (a list of actions) to the closest dot, starting from
gameState.
"""# Here are some useful elements of the startState
startPosition = gameState.getPacmanPosition()
food = gameState.getFood()
walls = gameState.getWalls()
problem = AnyFoodSearchProblem(gameState)"*** YOUR CODE HERE ***"# 找最短路的话 抄了一下之前的ucs
result =[]
visited =[]
heap = util.PriorityQueue()
start =(problem.getStartState(),[],0)
heap.push(start, start[2])whilenot heap.isEmpty():(state, path, cost)= heap.pop()if problem.isGoalState(state):
result = path
breakif state notin visited:
visited.append(state)for currState, currPath, currCost in problem.getSuccessors(state):
newPath = path +[currPath]
newCost = cost + currCost
newState =(currState, newPath, newCost)
heap.push(newState, newCost)return result
util.raiseNotDefined()classAnyFoodSearchProblem(PositionSearchProblem):"""
A search problem for finding a path to any food.
This search problem is just like the PositionSearchProblem, but has a
different goal test, which you need to fill in below. The state space and
successor function do not need to be changed.
The class definition above, AnyFoodSearchProblem(PositionSearchProblem),
inherits the methods of the PositionSearchProblem.
You can use this search problem to help you fill in the findPathToClosestDot
method.
"""def__init__(self, gameState):"Stores information from the gameState. You don't need to change this."# Store the food for later reference
self.food = gameState.getFood()# Store info for the PositionSearchProblem (no need to change this)
self.walls = gameState.getWalls()
self.startState = gameState.getPacmanPosition()
self.costFn =lambda x:1
self._visited, self._visitedlist, self._expanded ={},[],0# DO NOT CHANGEdefisGoalState(self, state):"""
The state is Pacman's position. Fill this in with a goal test that will
complete the problem definition.
"""
x,y = state
"*** YOUR CODE HERE ***"
isGoal =self.food.asList().count((x,y))==1return isGoal
util.raiseNotDefined()defmazeDistance(point1, point2, gameState):"""
Returns the maze distance between any two points, using the search functions
you have already built. The gameState can be any game state -- Pacman's
position in that state is ignored.
Example usage: mazeDistance( (2,4), (5,6), gameState)
This might be a useful helper function for your ApproximateSearchAgent.
"""
x1, y1 = point1
x2, y2 = point2
walls = gameState.getWalls()assertnot walls[x1][y1],'point1 is a wall: '+str(point1)assertnot walls[x2][y2],'point2 is a wall: '+str(point2)
prob = PositionSearchProblem(gameState, start=point1, goal=point2, warn=False, visualize=False)returnlen(search.bfs(prob))