当前位置:   article > 正文

人工智能-A*算法-八数码问题_a*算法解决八数码问题

a*算法解决八数码问题

一,A*算法设计思想

A*算法(A-star)是一种寻路算法,主要用于游戏、机器人等领域。

它的设计思想是将最短路径搜索问题转化为一个优化问题,通过计算每个节点的评分(f(n) = g(n) + h(n))来寻找最优路径。

以下是 A*算法的设计思想:

1. 引入启发式函数(h(n)):

A*算法使用一个启发式函数来估计从当前节点到目标节点的距离。

启发式函数越好,搜索速度越快。

通常情况下,启发式函数为曼哈顿距离(曼哈顿距离是指两点在网格上沿着网格线走的距离之和)。

2. 优先级队列

A*算法使用一个优先级队列(开启列表)来存储待处理的节点。

队列中的节点按照评分(f(n))从高到低排列。

这样,每次迭代都可以优先处理评分最高的节点,从而保证搜索的速度和效率。

3. 扩展节点

A*算法从当前节点开始,遍历其所有相邻节点。

对于每个相邻节点,检查它是否在关闭列表中(表示已经访问过),如果不在关闭列表中,则将其加入开启列表,并更新其父节点和评分。

4. 关闭列表

A*算法使用一个关闭列表来记录已访问过的节点。

每次扩展节点时,都需要检查新节点是否在关闭列表中。

如果在,则忽略该节点,继续处理其他相邻节点。

5. 停止条件

A*算法在找到目标节点或开启列表为空时停止搜索。

找到目标节点时,意味着找到了一条从起始节点到目标节点的最短路径。

6. 回溯法

当开启列表为空时,搜索失败。

此时,可以使用回溯法(如 Dijkstra 算法)从起始节点开始,重新寻找一条路径。

这种情况下,A*算法退化为 Dijkstra 算法。

二,题目需求

应用启发式搜索算法A 解决以下八数码问题:

初始状态:

目标状态:

 

三,代码实现

完整代码,需要下载pygame库,直接使用,运行可以查看动画演示效果。

  1. import heapq
  2. from copy import deepcopy
  3. import time
  4. import pygame
  5. # 定义启发式函数,使用当前状态与目标状态,棋子的错位数作为估价值
  6. def heuristic(move_state, goal_state):
  7. err_num = 0
  8. for i in range(3):
  9. for j in range(3):
  10. if move_state[i][j] != goal_state[i][j]:
  11. err_num += 1
  12. return err_num
  13. # 根据当前状态,获取可移动方向
  14. def get_moves(state, g):
  15. # 获取空缺位(或0值)坐标
  16. x, y = None, None
  17. for i in range(3):
  18. for j in range(3):
  19. if state[i][j] == 0:
  20. x, y = i, j
  21. break
  22. moves = []
  23. if x > 0:
  24. new_state = deepcopy(state)
  25. # 空位与它左侧1位交换,左侧数字右移
  26. new_state[x][y], new_state[x - 1][y] = new_state[x - 1][y], new_state[x][y]
  27. moves.append((new_state, g + 1))
  28. if x < 2:
  29. new_state = deepcopy(state)
  30. # 空位与它右侧1位交换,右侧数字左移
  31. new_state[x][y], new_state[x + 1][y] = new_state[x + 1][y], new_state[x][y]
  32. moves.append((new_state, g + 1))
  33. if y > 0:
  34. new_state = deepcopy(state)
  35. # 空位与它下面1位交换,下面数字上移
  36. new_state[x][y], new_state[x][y - 1] = new_state[x][y - 1], new_state[x][y]
  37. moves.append((new_state, g + 1))
  38. if y < 2:
  39. new_state = deepcopy(state)
  40. # 空位与它上面1位交换,上面数字下移
  41. new_state[x][y], new_state[x][y + 1] = new_state[x][y + 1], new_state[x][y]
  42. moves.append((new_state, g + 1))
  43. return moves
  44. # A星算法搜索
  45. def a_star_search(initial_state, goal_state):
  46. f, g, h = 0, 0, 0
  47. open_set = [(f, initial_state)]
  48. close_set = set()
  49. # 从哪里来字典,记录节点来源,当成父节点
  50. come_from = {}
  51. while open_set:
  52. f, current_state = heapq.heappop(open_set)
  53. if current_state == goal_state:
  54. data = []
  55. current_state = tuple(map(tuple, current_state))
  56. # 从目标点向起点遍历路径
  57. while current_state in come_from:
  58. # 将当前点的位置加入路径
  59. data.append(current_state)
  60. # 将当前点设为从哪里来的节点,继续向上遍历
  61. current_state = come_from[current_state]
  62. # 将起始点的位置也加入路径
  63. data.append(tuple(map(tuple, initial_state)))
  64. # 将路径反转,因为我们是从目标向起点遍历的,所以需要反转得到真正的路径
  65. return data[::-1]
  66. close_set.add(tuple(map(tuple, current_state)))
  67. for move, g in get_moves(current_state, g):
  68. if tuple(map(tuple, move)) not in close_set:
  69. come_from[tuple(map(tuple, move))] = tuple(map(tuple, current_state))
  70. h = heuristic(move, goal_state)
  71. f = g + h
  72. heapq.heappush(open_set, (f, move))
  73. return None
  74. # 打印网格地图
  75. def grid_print(grid):
  76. for line in grid:
  77. print(line)
  78. # 定义网格矩阵长宽
  79. map_size = (3, 3)
  80. # 定义屏幕一个格子大小
  81. CELL_SIZE = 200
  82. # 定义屏幕宽高大小
  83. WIDTH, HEIGHT = map_size[0] * CELL_SIZE, map_size[1] * CELL_SIZE
  84. # 定义颜色
  85. WHITE = (255, 255, 255)
  86. RED = (255, 0, 0)
  87. BLUE = (0, 0, 255)
  88. BLACK = (0, 0, 0)
  89. # 绘制主地图,棋盘数字
  90. def draw_grid(pygame, screen, num_states):
  91. # 填充屏幕背景为白色
  92. screen.fill(WHITE)
  93. for i in range(0, WIDTH, CELL_SIZE):
  94. pygame.draw.line(screen, BLACK, (i, 0), (i, HEIGHT))
  95. for i in range(0, HEIGHT, CELL_SIZE):
  96. pygame.draw.line(screen, BLACK, (0, i), (WIDTH, i))
  97. # 字体
  98. font = pygame.font.Font(None, 48)
  99. for i in range(3):
  100. for j in range(3):
  101. # 数字值
  102. num_text = str(num_states[j][i])
  103. if num_text == '0':
  104. # 写数字
  105. text = font.render(num_text, True, RED)
  106. else:
  107. # 写数字
  108. text = font.render(num_text, True, BLUE)
  109. screen.blit(text, (i * CELL_SIZE + CELL_SIZE / 2, j * CELL_SIZE + CELL_SIZE / 2))
  110. # 绘制A*算法找到的路径,动画演示
  111. def draw_a_star_path(initial_state, goal_state):
  112. # 执行A*算法,寻找最优路径
  113. path_states = a_star_search(initial_state, goal_state)
  114. print("绘制网格地图和最优路径:")
  115. # 返回搜索路径和Open、Close表的内容
  116. i = 0
  117. for path in path_states:
  118. grid_print(path)
  119. print(f"======={i}=======")
  120. i += 1
  121. print("绘制A*算法找到的路径地图:")
  122. # 初始化 Pygame
  123. pygame.init()
  124. # 创建一个窗口(屏幕)对象
  125. screen = pygame.display.set_mode((WIDTH, HEIGHT))
  126. # 窗口描述
  127. pygame.display.set_caption("A星算法-8数码问题-动画演示")
  128. # 循环刷新地图,显示最优路径
  129. for num_states in path_states:
  130. # 绘制主地图,棋盘数字
  131. draw_grid(pygame, screen, num_states)
  132. # 更新显示屏幕
  133. pygame.display.flip()
  134. time.sleep(1)
  135. # 退出 Pygame
  136. pygame.quit()
  137. if __name__ == "__main__":
  138. # 八数码初始状态
  139. initial_state = [
  140. [2, 8, 3],
  141. [1, 6, 0],
  142. [7, 5, 4]
  143. ]
  144. # 八数码最终状态
  145. goal_state = [
  146. [1, 2, 3],
  147. [8, 0, 4],
  148. [7, 6, 5]
  149. ]
  150. # 绘制A*算法找到的路径,动画演示
  151. draw_a_star_path(initial_state, goal_state)

四,运行动画效果

 ==========结束==========

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/486314
推荐阅读
相关标签
  

闽ICP备14008679号