diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/Pacman.iml b/.idea/Pacman.iml
new file mode 100644
index 0000000..86d1115
--- /dev/null
+++ b/.idea/Pacman.iml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..7ba73c2
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..e4c734e
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/doc/202002422003-黄结伦-实验1.md b/doc/202002422003-黄结伦-实验1.md
new file mode 100644
index 0000000..a623fd3
--- /dev/null
+++ b/doc/202002422003-黄结伦-实验1.md
@@ -0,0 +1,541 @@
+# Pacman 实验1
+
+## 一.实验目的
+
+ 1.加深对经典的DFS,BFS,一致代价搜索,A*搜索的理解,并掌握其初步的使用方法
+
+## 二.实验原理
+
+### 1.宽度优先搜索
+
+ **宽度优先搜索**(bread-first search)是简单搜索策略,先扩展根节点,接着扩展根节点的所有后继,然后再扩展它们的后继,以此类推。其伪代码如下
+
+ 下图显示了一个简单二叉树的搜索过程
+
+
+
+### 2.深度优先搜索
+
+ **深度优先搜索**(depth-first search)总是扩展搜索树的当前边缘结点集中最深的节点。搜索很快推进到搜索树的最深层,那里的结点没有后继。当那些结点扩展完之后,就从边缘结点集中去掉,然后搜索算法回溯到下一个还有未扩展后继的深度稍浅的结点。其伪代码如下
+
+ 下图显示了一个简单的二叉树搜索过程
+
+
+
+### 3.一致代价搜索
+
+ **一致代价搜索**总是扩展路径消耗最小的节点N。N点的路径消耗等于前一节点N-1的路径消耗加上N-1到N节点的路径消耗。其伪代码如下
+
+
+
+ 下图举了一个简单的例子说明一致代价搜索
+
+
+
+### 4.A*搜索
+
+ **A*搜索**对结点的评估结合了g(n),即到达此结点已经花费的代价,和A(n),从该结点到目标结点所花代价:
+
+ `f(n)=g(n)+h(n)`
+
+ 由于g(n)是从开始结点到结点n的路径代价,而A(n)是从结点n到目标结点的最小代价路径的估计值,因此
+
+ ` f(n)= 经过结点n的最小代价解的估计代价`
+
+ 这样,如果我们想要找到最小代价的解,首先扩展g(n)+ A(n)值最小的结点是合理的.可以发现这个策略不仅仅合理:假设启发式函数H(n)满足特定的条件,A*搜索既是完备的也是最优的.算法与一致代价搜索类似,除了A*使用g+h而不是g.
+
+ 下图举了一个简单的例子说明A*搜索的过程
+
+
+
+
+
+## 三.实验内容
+
+ 1.完成search文件夹中search.py中的depthFirstSearch,breadFirstSearch,uniformCostSearch,aStarSearch四个函数。
+
+在编写完代码后,可在终端中的search目录下执行`python2 .\autograder.py` 命令,即可查看是否通过!
+
+## 四.实验结果
+
+ 搜索算法中四个函数的具体实现如下
+
+### 1.depthFirstSearch
+
+```python
+def depthFirstSearch(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 ***"
+ visited_node = []
+ myStack= util.Stack()
+ actions = []
+ s = problem.getStartState()
+ if problem.isGoalState(s):
+ return actions
+ myStack.push((s, actions))
+ while not myStack.isEmpty():
+ state = myStack.pop()
+ if state[0] in visited_node:
+ continue
+ visited_node.append(state[0])
+ actions = state[1]
+ if (problem.isGoalState(state[0])):
+ return actions
+ for successor in problem.getSuccessors(state[0]):
+ child_state = successor[0]
+ action = successor[1]
+ sub_action = list(actions)
+ if not child_state in visited_node:
+ sub_action.append(action)
+ myStack.push((child_state, sub_action))
+ return actions
+ util.raiseNotDefined()
+```
+
+### 2.breadFirstSearch
+
+```python
+def breadthFirstSearch(problem):
+ """Search the shallowest nodes in the search tree first."""
+ "*** YOUR CODE HERE ***"
+ visited_node = []
+ myQueue = util.Queue()
+ actions = []
+ s = problem.getStartState()
+ if problem.isGoalState(s):
+ return actions
+ myQueue.push((s, actions))
+ while not myQueue.isEmpty():
+ state = myQueue.pop()
+ if state[0] in visited_node:
+ continue
+ visited_node.append(state[0])
+ actions = state[1]
+ if (problem.isGoalState(state[0])):
+ return actions
+ for successor in problem.getSuccessors(state[0]):
+ child_state = successor[0]
+ action = successor[1]
+ sub_action = list(actions)
+ if not child_state in visited_node:
+ sub_action.append(action)
+ myQueue.push((child_state, sub_action))
+ return actions
+ util.raiseNotDefined()
+```
+
+### 3.uniformCostSearch
+
+```python
+def uniformCostSearch(problem):
+ """Search the node of least total cost first."""
+ "*** YOUR CODE HERE ***"
+ visited_node = []
+ mypriorityQueue = util.PriorityQueue()
+ actions = []
+ s = problem.getStartState()
+ if problem.isGoalState(s):
+ return actions
+ mypriorityQueue.push((s, actions), 0)
+ while not mypriorityQueue.isEmpty():
+ state = mypriorityQueue.pop()
+ if state[0] in visited_node:
+ continue
+ visited_node.append(state[0])
+ actions = state[1]
+ if (problem.isGoalState(state[0])):
+ return actions
+ for successor in problem.getSuccessors(state[0]):
+ child_state = successor[0]
+ action = successor[1]
+ sub_action = list(actions)
+ if not child_state in visited_node:
+ sub_action.append(action)
+ mypriorityQueue.push((child_state, sub_action), problem.getCostOfActions(sub_action))
+ return actions
+ util.raiseNotDefined()
+```
+
+### 4.aStarSearch
+
+```python
+def aStarSearch(problem, heuristic=nullHeuristic):
+ """Search the node that has the lowest combined cost and heuristic first."""
+ "*** YOUR CODE HERE ***"
+ visited_node = []
+ mypriorityQueue = util.PriorityQueue()
+ actions = []
+ s = problem.getStartState()
+ if problem.isGoalState(s):
+ return actions
+ mypriorityQueue.push((s, actions), 0)
+ while not mypriorityQueue.isEmpty():
+ state = mypriorityQueue.pop()
+ if state[0] in visited_node:
+ continue
+ visited_node.append(state[0])
+ actions = state[1]
+ if (problem.isGoalState(state[0])):
+ return actions
+ for successor in problem.getSuccessors(state[0]):
+ child_state = successor[0]
+ action = successor[1]
+ sub_action = list(actions)
+ if not child_state in visited_node:
+ sub_action.append(action)
+ mypriorityQueue.push((child_state, sub_action),heuristic(child_state, problem)
+ + problem.getCostOfActions(sub_action))
+ return actions
+ util.raiseNotDefined()
+```
+
+ 在写完这四个函数后,在终端中输入 `python2 .\autograder.py`
+
+
+
+ 等到一段时间后,可以得到测试结果
+
+
+
+ 测试通过!
+
+## 五.附加实验
+
+ 在完成了search实验的四个搜索算法的基础上,进一步完成附加实验,包括[Corners Problem: Representation](http://ai.berkeley.edu/search.html#Q5),[Corners Problem: Heuristic](http://ai.berkeley.edu/search.html#Q6),[Eating All The Dots: Heuristic](http://ai.berkeley.edu/search.html#Q7),[Suboptimal Search](http://ai.berkeley.edu/search.html#Q8).
+
+### 1.Corner Problem
+
+ 本关主要是实现一个找到所有角落的启发式函数,实现思路为先获取地图的大小,然后记录每个后继的坐标,然后通过比较判断是否为地图角落,实现代码如下
+
+```python
+ 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:
+ if not 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 ***"
+ self.top = top
+ self.right = right
+```
+
+```python
+ def getStartState(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()
+```
+
+```python
+ def isGoalState(self, state):
+ """
+ Returns whether this search state is a goal state of the problem.
+ """
+ "*** YOUR CODE HERE ***"
+ result = state[1]
+ if state[0] in self.corners:
+ if state[0] not in result:
+ result.append(state[0])
+ if (len(result) == 4):
+ return True
+ else:
+ return False
+ util.raiseNotDefined()
+```
+
+```python
+ def getSuccessors(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]
+ dx, dy = Actions.directionToVector(action)
+ nextx, nexty = int(x + dx), int(y + dy)
+ visited = list(state[1])
+ if not self.walls[nextx][nexty]:
+ nextState = (nextx, nexty)
+ cost = 1
+ if nextState in self.corners and nextState not in visited:
+ visited.append(nextState)
+ successors.append(((nextState, visited), action, cost))
+ self._expanded += 1 # DO NOT CHANGE
+ return successors
+```
+
+
+
+### 2.Corners Heuristic
+
+ 本关实现一个走到所有角落的最短路径的启发式函数,为之后的搜索作准备,实现思路为通过last记录四个角落,然后依次计算所有后继至四个角落的曼哈顿距离,求和之后取最小值,该后继作为下一步,实现代码如下
+
+```python
+def cornersHeuristic(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
+ walls = problem.walls # These are the walls of the maze, as a Grid (game.py)
+
+ "*** YOUR CODE HERE ***"
+ visited = state[1]
+ now_state = state[0]
+ Heuristic = 0
+ last = []
+ if (problem.isGoalState(state)):
+ return 0
+ for i in corners:
+ if i not in visited:
+ last.append(i)
+ pos = now_state
+ cost = 999999
+ while len(last) != 0:
+ for i in last:
+ if cost > (abs(pos[0] - i[0]) + abs(pos[1] - i[1])):
+ min_con = i
+ cost = (abs(pos[0] - i[0]) + abs(pos[1] - i[1]))
+ Heuristic += cost
+ pos = min_con
+ cost = 999999
+ last.remove(min_con)
+ return Heuristic
+```
+
+
+
+### 3.Food Heuristic
+
+ 本关实现一个新的搜索食物的启发式函数,使找到所有食物的路径最小。实现思路为先找到代价最大的食物,然后根据当前位置与最大代价的食物的相对位置,计算出已经吃掉的食物数量,先将代价小的食物都吃掉,最后再吃代价大的食物,即为最短路径。实现代码如下,
+
+```python
+def foodHeuristic(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 ***"
+ lsFoodGrid = foodGrid.asList()
+ last = list(lsFoodGrid)
+ Heuristic = 0
+ cost = 0
+ max_con = position
+ for i in last:
+ if cost < (abs(position[0] - i[0]) + abs(position[1] - i[1])):
+ max_con = i
+ cost = (abs(position[0] - i[0]) + abs(position[1] - i[1]))
+ Heuristic = cost
+ diff = position[0] - max_con[0]
+ count = 0
+ for i in last:
+ if diff > 0:
+ if position[0] < i[0]:
+ count += 1
+ if diff < 0:
+ if position[0] > i[0]:
+ count += 1
+ if diff == 0:
+ if position[0] != i[0]:
+ count += 1
+ return Heuristic + count
+```
+
+
+
+### 4.Suboptimal Search
+
+本关实现一个次优搜索,在保证吃掉所有食物的条件下,在较短的时间内找到一个比较好的路径。实现思路为使用优先队列和AnyFoodSearchProblem类中实现的函数完成本关,实现代码如下,
+
+```python
+class ClosestDotSearchAgent(SearchAgent):
+ "Search for all food using a sequence of searches"
+ def registerInitialState(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 not in legal:
+ t = (str(action), str(currentState))
+ raise Exception, 'findPathToClosestDot returned an illegal move: %s!\n%s' % t
+ currentState = currentState.generateSuccessor(0, action)
+ self.actionIndex = 0
+ print 'Path found with cost %d.' % len(self.actions)
+
+ def findPathToClosestDot(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 ***"
+ Result = []
+ Visited = []
+ Queue = util.PriorityQueue()
+ startState = (problem.getStartState(),[],0)
+ Queue.push(startState,startState[2])
+ while not Queue.isEmpty():
+ (state,path,cost) = Queue.pop()
+ if problem.isGoalState(state):
+ Result = path
+ break
+ if state not in Visited:
+ Visited.append(state)
+ for currentState,currentPath,currentCost in problem.getSuccessors(state):
+ newPath = path + [currentPath]
+ newCost = cost + currentCost
+ newState = (currentState,newPath,newCost)
+ Queue.push(newState,newCost)
+ return Result
+ util.raiseNotDefined()
+
+class AnyFoodSearchProblem(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 CHANGE
+
+ def isGoalState(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 ***"
+
+ foodGrid = self.food
+ if foodGrid[x][y] == True or foodGrid.count() == 0:
+ return True
+ else:
+ return False
+ util.raiseNotDefined()
+
+
+
+def mazeDistance(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()
+ assert not walls[x1][y1], 'point1 is a wall: ' + str(point1)
+ assert not walls[x2][y2], 'point2 is a wall: ' + str(point2)
+ prob = PositionSearchProblem(gameState, start=point1, goal=point2, warn=False, visualize=False)
+ return len(search.bfs(prob))
+```
+
+
+
+## 六.实验总结
+
+ 学会了四个经典的搜索算法的用法,在前期的算法课中虽然学习过DFS,BFS,aStar等搜索算法,但是之前的考试都考背诵代码,都没有真正的理解这些算法的过程。Pacman实验将算法的过程通过吃豆人的移动与路径的选择表现出来,让人眼前一亮,也让人更加深刻的理解这些算法。
+
+
\ No newline at end of file
diff --git a/doc/202002422003-黄结伦-实验2.md b/doc/202002422003-黄结伦-实验2.md
new file mode 100644
index 0000000..1c74a48
--- /dev/null
+++ b/doc/202002422003-黄结伦-实验2.md
@@ -0,0 +1,257 @@
+# Pacman 实验2
+
+## 一.实验目的
+
+ 1.通过实验理解零和游戏的博弈过程,学会简单的评估函数的设计
+
+ 2.掌握极小极大法和alpha-beta剪枝
+
+## 二.实验原理
+
+### 1.极小极大法
+
+ 在零和博弈中,玩家均会在可选的选项中选择将其N步后优势最大化或者令对手优势最小化的选择。将双方决策过程视作一颗决策树,若决策树某一层均为己方决策依据状态(即接下来是己方进行动作),则己方必定会选择使得己方收益最大化的路径,将该层称为MAX层。若决策树某一层均为对手决策依据状态(即接下来是对手进行动作),则对手必定会选择使得己方收益最小化的路径,将该层成为MIN层。由此,一个极小极大决策树将包含max节点(MAX层中的节点)、min节点(MIN层中的节点)和终止节点(博弈终止状态节点或N步时的状态节点)。每个节点对应的预期收益成为该节点的minimax值。
+ 对于终止结点, minimax值等于直接对局面的估值。对于max结点,由于max节点所选择的动作将会由己方给定,因此选择minimax值最大的子结点的值作为max结点的值。对于min结点,则选择minimax值最小的子结点的值作为min结点的值。
+极小极大算法过程可描述如下:
+
+构建决策树;
+ 1.将评估函数应用于叶子结点;
+ 2.自底向上计算每个结点的minimax值;
+ 3.从根结点选择minimax值最大的分支,作为行动策略。
+minimax计算流程如下:
+
+ 1.如果节点是终止节点:应用估值函数求值;
+ 2.如果节点是max节点:找到每个子节点的值,将其中最大的子节点值作为该节点的值;
+ 3.如果节点时min节点:找到每个子节点的值,将其中最小的子节点值作为该节点的值。
+
+其伪代码如下,
+
+
+
+### 2.alpah-beta剪枝
+
+ 举个简单的例子说明**alpha-beta剪枝**的过程
+
+
+
+ 其伪代码如下,
+
+
+
+## 三.实验内容
+
+ 1.完成multiagent文件夹中的evaluationFunction,MinimaxAgent,AlphaBetaAgent函数。
+
+ 在编写完代码后,可在终端中的multiagent目录下执行`python2 .\autograder.py` 命令,即可查看是否通过!
+
+## 四.实验结果
+
+ 博弈算法中的三个函数(类)的具体实现如下
+
+### 1.evaluationFunction
+
+```python
+ def evaluationFunction(self, currentGameState, action):
+ """
+ Design a better evaluation function here.
+
+ The evaluation function takes in the current and proposed successor
+ GameStates (pacman.py) and returns a number, where higher numbers are better.
+
+ The code below extracts some useful information from the state, like the
+ remaining food (newFood) and Pacman position after moving (newPos).
+ newScaredTimes holds the number of moves that each ghost will remain
+ scared because of Pacman having eaten a power pellet.
+
+ Print out these variables to see what you're getting, then combine them
+ to create a masterful evaluation function.
+ """
+ # Useful information you can extract from a GameState (pacman.py)
+ successorGameState = currentGameState.generatePacmanSuccessor(action)
+ newPos = successorGameState.getPacmanPosition()
+ newFood = successorGameState.getFood()
+ newGhostStates = successorGameState.getGhostStates()
+ newScaredTimes = [ghostState.scaredTimer for ghostState in newGhostStates]
+ #many ghosts
+ "*** YOUR CODE HERE ***"
+ GhostPos = successorGameState.getGhostPositions()
+ x_pacman,y_pacman = newPos
+ failedDist = min([(abs(each[0]- x_pacman) + abs(each[1]-y_pacman)) for each in GhostPos])
+ if failedDist != 0 and failedDist < 4:
+ ghostScore = -11 / failedDist
+ else :
+ ghostScore = 0
+ nearestFood = float('inf')
+ width = newFood.width
+ height = newFood.height
+ if failedDist >= 2:
+ dx = [1,0,-1,0]
+ dy = [0,1,0,-1]
+ List = []
+ d = {}
+ List.append(newPos)
+ d.update({(x_pacman,y_pacman) : 1})
+ while List:
+ tempPos = List[0]
+ List.pop(0)
+ temp_x,temp_y = tempPos
+ if newFood[temp_x][temp_y]:
+ nearestFood = min(nearestFood,(abs(temp_x - x_pacman) + abs(temp_y - y_pacman)))
+ break
+ for i in range(len(dx)):
+ x = temp_x + dx[i]
+ y = temp_y + dy[i]
+ if 0 <= x < width and 0 <= y < height:
+ tempPos =(x,y)
+ if tempPos not in d:
+ d[tempPos] = 1
+ List.append(tempPos)
+ if nearestFood != float('inf'):
+ foodScore = 10 / nearestFood
+ else :
+ foodScore = 0
+ return successorGameState.getScore() + foodScore + ghostScore
+```
+
+### 2.MinimaxAgent
+
+```python
+class MinimaxAgent(MultiAgentSearchAgent):
+ """
+ Your minimax agent (question 2)
+ """
+ def getAction(self, gameState):
+ """
+ Returns the minimax action from the current gameState using self.depth
+ and self.evaluationFunction.
+
+ Here are some method calls that might be useful when implementing minimax.
+
+ gameState.getLegalActions(agentIndex):
+ Returns a list of legal actions for an agent
+ agentIndex=0 means Pacman, ghosts are >= 1
+
+ gameState.generateSuccessor(agentIndex, action):
+ Returns the successor game state after an agent takes an action
+
+ gameState.getNumAgents():
+ Returns the total number of agents in the game
+
+ gameState.isWin():
+ Returns whether or not the game state is a winning state
+
+ gameState.isLose():
+ Returns whether or not the game state is a losing state
+ """
+ "*** YOUR CODE HERE ***"
+
+ def gameOver(gameState):
+ return gameState.isWin() or gameState.isLose()
+ #Be different with me
+ def min_value(gameState, depth, ghost):
+ value = float('inf')
+ if gameOver(gameState):
+ return self.evaluationFunction(gameState)
+ for action in gameState.getLegalActions(ghost):
+ if ghost == gameState.getNumAgents() - 1:
+ value = min(value, max_value(gameState.generateSuccessor(ghost, action), depth))
+ else:
+ value = min(value, min_value(gameState.generateSuccessor(ghost, action), depth,
+ ghost + 1))
+ return value
+
+
+ def max_value(gameState, depth):
+ value = float('-inf')
+ depth = depth + 1
+ #Be different with me
+ if depth == self.depth or gameOver(gameState):
+ return self.evaluationFunction(gameState)
+ for action in gameState.getLegalActions(0):
+ value = max(value, min_value(gameState.generateSuccessor(0, action), depth, 1))
+ return value
+ nextAction = gameState.getLegalActions(0)
+ Max = float('-inf')
+ Result = None
+
+ for action in nextAction:
+ if (action != "stop"):
+ depth = 0
+ value = min_value(gameState.generateSuccessor(0, action), depth, 1)
+ if (value > Max):
+ Max = value
+ Result = action
+ return Result
+ util.raiseNotDefined()
+```
+
+### 3.AlphaBetaAgent
+
+```python
+class AlphaBetaAgent(MultiAgentSearchAgent):
+ """
+ Your minimax agent with alpha-beta pruning (question 3)
+ """
+
+ def getAction(self, gameState):
+ """
+ Returns the minimax action using self.depth and self.evaluationFunction
+ """
+ "*** YOUR CODE HERE ***"
+ ghostIndex = [i for i in range(1,gameState.getNumAgents())]
+ def gameOver(state,depth):
+ return state.isWin() or state.isLose() or depth == self.depth
+ def min_value(state,depth,ghost,alpha,beta):
+ if gameOver(state,depth):
+ return self.evaluationFunction(state)
+ value = float('inf')
+ for action in state.getLegalActions(ghost):
+ if ghost == ghostIndex[-1]:
+ value = min(value,max_value(state.generateSuccessor(ghost,action),depth+1,alpha,beta))
+ else:
+ value = min(value,min_value(state.generateSuccessor(ghost,action),depth,ghost+1,alpha,beta))
+ if value < alpha:
+ return value
+ beta = min(beta,value)
+ return value
+ def max_value(state,depth,alpha,beta):
+ if gameOver(state,depth):
+ return self.evaluationFunction(state)
+ value = float('-inf')
+ for action in state.getLegalActions(0):
+ if action == 'stop':
+ continue
+ value = max(value,min_value(state.generateSuccessor(0,action),depth,1,alpha,beta))
+ if value > beta:
+ return value
+ alpha = max(value,alpha)
+ return value
+ def function(state):
+ value = float('-inf')
+ actions = None
+ alpha = float('-inf')
+ beta = float('inf')
+ for action in state.getLegalActions(0):
+ if action == 'stop':
+ continue
+ tmpValue = min_value(state.generateSuccessor(0,action),0,1,alpha,beta)
+ if value < tmpValue:
+ value = tmpValue
+ actions = action
+ alpha = max(value,alpha)
+ return actions
+ return function(gameState)
+ util.raiseNotDefined()
+```
+
+
+
+ 测试过程与结果如下
+
+
+
+
+
+## 五.实验总结
+
+ 博弈算法在AI课程中第一次接触,虽然博弈过程是一个十分玄妙的过程,但是计算机人用其大智慧,将这个过程转化为一个可以用数学公式描述的过程,而这种抽象化的思维能力是一个及其重要的能力。通过Pacman的实验,加深了我对alpha-beta剪枝的原理与过程。
\ No newline at end of file
diff --git a/doc/202002422003_黄结伦_实验1.pdf b/doc/202002422003_黄结伦_实验1.pdf
new file mode 100644
index 0000000..41974e1
Binary files /dev/null and b/doc/202002422003_黄结伦_实验1.pdf differ
diff --git a/doc/202002422003_黄结伦_实验2.pdf b/doc/202002422003_黄结伦_实验2.pdf
new file mode 100644
index 0000000..a213cae
Binary files /dev/null and b/doc/202002422003_黄结伦_实验2.pdf differ
diff --git a/doc/image-20221021212311445.png b/doc/image-20221021212311445.png
new file mode 100644
index 0000000..ecf52be
Binary files /dev/null and b/doc/image-20221021212311445.png differ
diff --git a/doc/image-20221021212559638.png b/doc/image-20221021212559638.png
new file mode 100644
index 0000000..6fc6f11
Binary files /dev/null and b/doc/image-20221021212559638.png differ
diff --git a/doc/image-20221021212636227.png b/doc/image-20221021212636227.png
new file mode 100644
index 0000000..d99274d
Binary files /dev/null and b/doc/image-20221021212636227.png differ
diff --git a/doc/image-20221021212936449.png b/doc/image-20221021212936449.png
new file mode 100644
index 0000000..bff341c
Binary files /dev/null and b/doc/image-20221021212936449.png differ
diff --git a/doc/image-20221021213229986.png b/doc/image-20221021213229986.png
new file mode 100644
index 0000000..b7f95a9
Binary files /dev/null and b/doc/image-20221021213229986.png differ
diff --git a/doc/image-20221021213316266.png b/doc/image-20221021213316266.png
new file mode 100644
index 0000000..039dc9f
Binary files /dev/null and b/doc/image-20221021213316266.png differ
diff --git a/doc/image-20221021213939136.png b/doc/image-20221021213939136.png
new file mode 100644
index 0000000..a5b4c09
Binary files /dev/null and b/doc/image-20221021213939136.png differ
diff --git a/doc/image-20221021214532214.png b/doc/image-20221021214532214.png
new file mode 100644
index 0000000..b4cfa0d
Binary files /dev/null and b/doc/image-20221021214532214.png differ
diff --git a/doc/image-20221021214643168.png b/doc/image-20221021214643168.png
new file mode 100644
index 0000000..8b5c894
Binary files /dev/null and b/doc/image-20221021214643168.png differ
diff --git a/doc/image-20221021214709128.png b/doc/image-20221021214709128.png
new file mode 100644
index 0000000..1a4f77a
Binary files /dev/null and b/doc/image-20221021214709128.png differ
diff --git a/doc/image-20221022153157435.png b/doc/image-20221022153157435.png
new file mode 100644
index 0000000..5139366
Binary files /dev/null and b/doc/image-20221022153157435.png differ
diff --git a/doc/image-20221022153238236.png b/doc/image-20221022153238236.png
new file mode 100644
index 0000000..7398ce0
Binary files /dev/null and b/doc/image-20221022153238236.png differ
diff --git a/doc/image-20221022153803006.png b/doc/image-20221022153803006.png
new file mode 100644
index 0000000..4f28e7e
Binary files /dev/null and b/doc/image-20221022153803006.png differ
diff --git a/doc/image-20221022153822732.png b/doc/image-20221022153822732.png
new file mode 100644
index 0000000..ef1fcc4
Binary files /dev/null and b/doc/image-20221022153822732.png differ
diff --git a/doc/实验报告模板.pdf b/doc/实验报告模板.pdf
new file mode 100644
index 0000000..8cdb2e1
Binary files /dev/null and b/doc/实验报告模板.pdf differ
diff --git a/multiagent/multiagent/autograder.pyc b/multiagent/multiagent/autograder.pyc
new file mode 100644
index 0000000..da84be1
Binary files /dev/null and b/multiagent/multiagent/autograder.pyc differ
diff --git a/multiagent/multiagent/game.pyc b/multiagent/multiagent/game.pyc
new file mode 100644
index 0000000..3699c34
Binary files /dev/null and b/multiagent/multiagent/game.pyc differ
diff --git a/multiagent/multiagent/ghostAgents.pyc b/multiagent/multiagent/ghostAgents.pyc
new file mode 100644
index 0000000..c0b3d99
Binary files /dev/null and b/multiagent/multiagent/ghostAgents.pyc differ
diff --git a/multiagent/multiagent/grading.pyc b/multiagent/multiagent/grading.pyc
new file mode 100644
index 0000000..8f231f8
Binary files /dev/null and b/multiagent/multiagent/grading.pyc differ
diff --git a/multiagent/multiagent/graphicsDisplay.pyc b/multiagent/multiagent/graphicsDisplay.pyc
new file mode 100644
index 0000000..a0f0b63
Binary files /dev/null and b/multiagent/multiagent/graphicsDisplay.pyc differ
diff --git a/multiagent/multiagent/graphicsUtils.pyc b/multiagent/multiagent/graphicsUtils.pyc
new file mode 100644
index 0000000..91bd2b2
Binary files /dev/null and b/multiagent/multiagent/graphicsUtils.pyc differ
diff --git a/multiagent/multiagent/keyboardAgents.pyc b/multiagent/multiagent/keyboardAgents.pyc
new file mode 100644
index 0000000..135f307
Binary files /dev/null and b/multiagent/multiagent/keyboardAgents.pyc differ
diff --git a/multiagent/multiagent/layout.pyc b/multiagent/multiagent/layout.pyc
new file mode 100644
index 0000000..8f45b28
Binary files /dev/null and b/multiagent/multiagent/layout.pyc differ
diff --git a/multiagent/multiagent/multiAgents.pyc b/multiagent/multiagent/multiAgents.pyc
new file mode 100644
index 0000000..e170839
Binary files /dev/null and b/multiagent/multiagent/multiAgents.pyc differ
diff --git a/multiagent/multiagent/multiagentTestClasses.pyc b/multiagent/multiagent/multiagentTestClasses.pyc
new file mode 100644
index 0000000..77b31bc
Binary files /dev/null and b/multiagent/multiagent/multiagentTestClasses.pyc differ
diff --git a/multiagent/multiagent/pacman.pyc b/multiagent/multiagent/pacman.pyc
new file mode 100644
index 0000000..c7bff85
Binary files /dev/null and b/multiagent/multiagent/pacman.pyc differ
diff --git a/multiagent/multiagent/pacmanAgents.pyc b/multiagent/multiagent/pacmanAgents.pyc
new file mode 100644
index 0000000..4b09f53
Binary files /dev/null and b/multiagent/multiagent/pacmanAgents.pyc differ
diff --git a/multiagent/multiagent/projectParams.pyc b/multiagent/multiagent/projectParams.pyc
new file mode 100644
index 0000000..2e4c8e8
Binary files /dev/null and b/multiagent/multiagent/projectParams.pyc differ
diff --git a/multiagent/multiagent/testClasses.pyc b/multiagent/multiagent/testClasses.pyc
new file mode 100644
index 0000000..5e0fd0a
Binary files /dev/null and b/multiagent/multiagent/testClasses.pyc differ
diff --git a/multiagent/multiagent/testParser.pyc b/multiagent/multiagent/testParser.pyc
new file mode 100644
index 0000000..6127ca6
Binary files /dev/null and b/multiagent/multiagent/testParser.pyc differ
diff --git a/multiagent/multiagent/textDisplay.pyc b/multiagent/multiagent/textDisplay.pyc
new file mode 100644
index 0000000..9f58a50
Binary files /dev/null and b/multiagent/multiagent/textDisplay.pyc differ
diff --git a/multiagent/multiagent/util.pyc b/multiagent/multiagent/util.pyc
new file mode 100644
index 0000000..762e132
Binary files /dev/null and b/multiagent/multiagent/util.pyc differ
diff --git a/project1.rar b/project1.rar
new file mode 100644
index 0000000..7b88c9f
Binary files /dev/null and b/project1.rar differ
diff --git a/project2.rar b/project2.rar
new file mode 100644
index 0000000..faf0a6c
Binary files /dev/null and b/project2.rar differ
diff --git a/search/grading.pyc b/search/grading.pyc
new file mode 100644
index 0000000..d147ad5
Binary files /dev/null and b/search/grading.pyc differ
diff --git a/search/projectParams.pyc b/search/projectParams.pyc
new file mode 100644
index 0000000..6255abc
Binary files /dev/null and b/search/projectParams.pyc differ
diff --git a/search/searchTestClasses.pyc b/search/searchTestClasses.pyc
new file mode 100644
index 0000000..3116b9e
Binary files /dev/null and b/search/searchTestClasses.pyc differ
diff --git a/search/testClasses.pyc b/search/testClasses.pyc
new file mode 100644
index 0000000..290a003
Binary files /dev/null and b/search/testClasses.pyc differ
diff --git a/search/testParser.pyc b/search/testParser.pyc
new file mode 100644
index 0000000..4608e42
Binary files /dev/null and b/search/testParser.pyc differ
diff --git a/search/textDisplay.pyc b/search/textDisplay.pyc
new file mode 100644
index 0000000..83c9ff7
Binary files /dev/null and b/search/textDisplay.pyc differ