八数码问题(启发式)

from queue import PriorityQueue

start = [1, 5, 2,
         4, 8, 3,
         0, 7, 6]
goal = [1, 2, 3,
        4, 5, 6,
        7, 8, 0]
# 评估函数h(n)
# 计算结点的 h 值  f=g+h. 按照不在位的个数进行计算
def heuristic(state, goal):
    return sum(s != g for s, g in zip(state, goal))


# 扩展函数extends
def extends(state):
    # 找到空格所在的位置
    i = state.index(0)
    # 可能进行的移动
    extends = []
    if i % 3 > 0: extends.append(('left', i - 1))
    if i % 3 < 2: extends.append(('right', i + 1))
    if i // 3 > 0: extends.append(('up', i - 3))
    if i // 3 < 2: extends.append(('down', i + 3))
    return extends
# 根据当前状态,返回扩展后的新状态
def result(state, extends):
    # 复制当前状态
    new_state = state[:]

    # 找到空格的位置
    i = state.index(0)

    # 执行动作
    if extends[0] == 'up':
        new_state[i], new_state[i - 3] = new_state[i - 3], new_state[i] #交换索引
    elif extends[0] == 'down':
        new_state[i], new_state[i + 3] = new_state[i + 3], new_state[i]
    elif extends[0] == 'left':
        new_state[i], new_state[i - 1] = new_state[i - 1], new_state[i]
    elif extends[0] == 'right':
        new_state[i], new_state[i + 1] = new_state[i + 1], new_state[i]

    return new_state

# A*算法
def astar(start, goal):
    open = PriorityQueue()
    open.put((heuristic(start, goal), 0, start))
    visited = set()
    parents = {tuple(start): None}  # 记录父状态
    while not open.empty():
        print(list(open.queue))
        priority, cost, state = open.get()
        if state == goal:
            return cost, parents  # 返回最小步数和父状态
        if tuple(state) in visited:
            continue
        visited.add(tuple(state))
        for extend in extends(state):
            next_state = result(state, extend)
            if tuple(next_state) not in visited:
                priority = cost + 1 + heuristic(next_state, goal)
                open.put((priority, cost + 1, next_state))
                parents[tuple(next_state)] = state  # 记录父状态
    return None, None

if __name__ == '__main__':
    start = [1, 5, 2,
             4, 8, 3,
             0, 7, 6]
    goal = [1, 2, 3,
            4, 5, 6,
            7, 8, 0]
    steps, parents = astar(start, goal)
    print("最优的步数是:", steps)

    # 打印最优路径
    path = []
    state = goal
    while state is not None:
        path.append(state)
        state = parents[tuple(state)]
    path.reverse()
    print("最优的路径是:")
    for state in path:
        # 将状态转换为3x3的形式并打印
        for i in range(0, 9, 3):
            print(state[i:i + 3])
        print()
# 将起始点加入open表
#
#      当open表不为空时:
#
#        寻找open表中f值最小的点current
#
#        它是终止点,则找到结果,程序结束。
#
#        否则,Open表移出current,对current表中的每一个临近点
#
#            若它不可走或在close表中,略过
#
#            若它不在open表中,加入。
#
#            若它在open表中,计算g值,若g值更小,替换其父节点为current,更新它的g值。
#
# 若open表为空,则路径不存在。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值