done: homework3

This commit is contained in:
2025-04-03 18:28:09 +08:00
parent 1ed9afee2c
commit c21dfa63ef
7 changed files with 220 additions and 1 deletions
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="com.codeverse.userSettings.MarscodeWorkspaceAppSettingsState">
<option name="ckgOperationStatus" value="SUCCESS" />
</component>
</project>
+8
View File
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="jdk" jdkName="ai-homework" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
@@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="ai-homework" />
</component>
</project>
+8
View File
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/homework3.iml" filepath="$PROJECT_DIR$/.idea/homework3.iml" />
</modules>
</component>
</project>
+3 -1
View File
@@ -1,4 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings" defaultProject="true" />
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>
+183
View File
@@ -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))