diff --git a/homework3/.idea/MarsCodeWorkspaceAppSettings.xml b/homework3/.idea/MarsCodeWorkspaceAppSettings.xml
new file mode 100644
index 0000000..05ed8ba
--- /dev/null
+++ b/homework3/.idea/MarsCodeWorkspaceAppSettings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/homework3/.idea/homework3.iml b/homework3/.idea/homework3.iml
new file mode 100644
index 0000000..2051088
--- /dev/null
+++ b/homework3/.idea/homework3.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/homework3/.idea/inspectionProfiles/profiles_settings.xml b/homework3/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/homework3/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/homework3/.idea/misc.xml b/homework3/.idea/misc.xml
new file mode 100644
index 0000000..6de7068
--- /dev/null
+++ b/homework3/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/homework3/.idea/modules.xml b/homework3/.idea/modules.xml
new file mode 100644
index 0000000..886212e
--- /dev/null
+++ b/homework3/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/homework3/.idea/vcs.xml b/homework3/.idea/vcs.xml
index d843f34..6c0b863 100644
--- a/homework3/.idea/vcs.xml
+++ b/homework3/.idea/vcs.xml
@@ -1,4 +1,6 @@
-
+
+
+
\ No newline at end of file
diff --git a/homework3/main.py b/homework3/main.py
index e69de29..e22c21c 100644
--- a/homework3/main.py
+++ b/homework3/main.py
@@ -0,0 +1,183 @@
+import numpy as np
+
+class State:
+ def __init__(self, state, directionFlag=None, parent=None, f=0):
+ """八数码问题状态类
+ Args:
+ state: 3x3 numpy数组,表示当前状态
+ directionFlag: 禁止的移动方向(用于防止走回头路)
+ parent: 父状态节点
+ f: 评估函数值(f = g + h)
+ """
+ self.state = state # 当前状态矩阵
+ self.direction = ['up', 'down', 'right', 'left'] # 可移动方向
+ if directionFlag: # 移除来源方向防止回退
+ self.direction.remove(directionFlag)
+ self.parent = parent # 父节点指针
+ self.f = f # 评估函数值
+
+ def getDirection(self):
+ """获取当前允许的移动方向列表"""
+ return self.direction
+
+ def setF(self, f):
+ """设置评估函数值"""
+ self.f = f
+ return
+
+ # 打印结果
+ def showInfo(self):
+ """打印当前状态矩阵"""
+ for i in range(len(self.state)):
+ for j in range(len(self.state)):
+ print(self.state[i, j], end=' ')
+ print("\n")
+ print('->')
+ return
+
+ # 获取0点
+ def getZeroPos(self):
+ """获取空白格(0)的位置坐标
+ Returns:
+ tuple: 包含空白格的行列坐标(x, y)
+ """
+ postion = np.where(self.state == 0)
+ return postion
+
+ # 曼哈顿距离 f = g + h,g=1,如果用宽度优先的评估函数可以不调用该函数
+ def getFunctionValue(self):
+ """计算曼哈顿距离评估值
+ Returns:
+ int: 当前状态到目标状态的评估值(f = 移动步数 + 启发函数值)
+ """
+ cur_node = self.state.copy()
+ fin_node = self.answer.copy()
+ dist = 0 # 曼哈顿距离总和
+ N = len(cur_node) # 矩阵维度(3)
+
+ # 遍历每个格子计算距离
+ for i in range(N):
+ for j in range(N):
+ if cur_node[i][j] != fin_node[i][j]:
+ index = np.argwhere(fin_node == cur_node[i][j]) # 找到对应数字在目标状态的位置
+ x = index[0][0] # 目标x坐标
+ y = index[0][1] # 目标y坐标
+ dist += (abs(x - i) + abs(y - j)) # 累加曼哈顿距离
+ return dist + 1 # 总距离+当前步数(g值固定为1)
+
+ def nextStep(self):
+ """生成所有可能的下一个合法状态
+ Returns:
+ State: 评估函数值最小的下一个状态
+ """
+ if not self.direction: # 无可用移动方向
+ return []
+ subStates = [] # 子状态列表
+ boarder = len(self.state) - 1 # 矩阵边界索引
+
+ # 获取0点位置
+ x, y = self.getZeroPos()
+ x, y = x[0], y[0] # 转换为标量值
+
+ # 向左移动
+ if 'left' in self.direction and y > 0:
+ s = self.state.copy()
+ tmp = s[x, y - 1]
+ s[x, y - 1] = s[x, y]
+ s[x, y] = tmp
+ news = State(s, directionFlag='right', parent=self)
+ news.setF(news.getFunctionValue())
+ subStates.append(news)
+
+ # 向上移动
+ if 'up' in self.direction and x > 0:
+ s = self.state.copy()
+ tmp = s[x - 1, y]
+ s[x - 1, y] = s[x, y]
+ s[x, y] = tmp
+ news = State(s, directionFlag='down', parent=self)
+ news.setF(news.getFunctionValue())
+ subStates.append(news)
+
+ # 向下移动
+ if 'down' in self.direction and x < boarder:
+ s = self.state.copy()
+ tmp = s[x + 1, y]
+ s[x + 1, y] = s[x, y]
+ s[x, y] = tmp
+ news = State(s, directionFlag='up', parent=self)
+ news.setF(news.getFunctionValue())
+ subStates.append(news)
+
+ # 向右移动
+ if 'right' in self.direction and y < boarder:
+ s = self.state.copy()
+ tmp = s[x, y + 1]
+ s[x, y + 1] = s[x, y]
+ s[x, y] = tmp
+ news = State(s, directionFlag='left', parent=self)
+ news.setF(news.getFunctionValue())
+ subStates.append(news)
+
+ # 返回F值最小的下一个点
+ subStates.sort(key=compareNum)
+ return subStates[0]
+
+ # A* 迭代
+ def solve(self):
+ """执行A*算法求解路径
+ Returns:
+ list: 从初始状态到目标状态的路径节点列表
+ """
+ # openList(待访问节点列表)
+ openTable = []
+ # closeList(已访问节点列表)
+ closeTable = []
+ openTable.append(self) # 初始节点加入open表
+
+ while len(openTable) > 0: # 当存在待访问节点时
+ # 取出评估值最小的节点
+ n = openTable.pop(0)
+ # 加入已访问列表
+ closeTable.append(n)
+ # 生成子节点
+ subStates = n.nextStep()
+ path = []
+
+ # 判断是否到达目标状态
+ if (subStates.state == subStates.answer).all():
+ # 回溯路径
+ while subStates.parent and subStates.parent != originState:
+ path.append(subStates.parent)
+ subStates = subStates.parent
+ path.reverse() # 反转得到正序路径
+ return path
+
+ # 将子节点加入open表
+ openTable.append(subStates)
+ else:
+ return None, None
+
+def compareNum(state):
+ """状态比较函数(用于排序)"""
+ return state.f
+
+if __name__ == '__main__':
+ # 初始化起始状态(0代表空格)
+ originState = State(np.array([[1, 5, 3], [2, 4, 6], [7, 0, 8]]))
+ # 设置类属性:目标状态
+ State.answer = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 0]])
+
+ # 创建初始状态对象
+ s1 = State(state=originState.state)
+ # 求解路径
+ path = s1.solve()
+
+ # 输出结果
+ if path:
+ print("解决方案路径:")
+ for node in path:
+ node.showInfo()
+ print("目标状态:")
+ print(State.answer)
+ print("总步数:%d" % len(path))