第一关:评估函数和启发信息

  1. A
  2. A


    第2关:A*搜索算法

  1. class Array2D:
  2. """
  3. 说明:
  4. 1.构造方法需要两个参数,即二维数组的宽和高
  5. 2.成员变量w和h是二维数组的宽和高
  6. 3.使用:‘对象[x][y]’可以直接取到相应的值
  7. 4.数组的默认值都是0
  8. """
  9. def __init__(self, w, h):
  10. self.w = w
  11. self.h = h
  12. self.data = []
  13. self.data = [[0 for y in range(h)] for x in range(w)]
  14. def showArray2D(self):
  15. for y in range(self.h):
  16. for x in range(self.w):
  17. print(self.data[x][y], end=' ')
  18. print("")
  19. def __getitem__(self, item):
  20. return self.data[item]
  21. class Point:
  22. """
  23. 表示一个点
  24. """
  25. def __init__(self, x, y):
  26. self.x = x
  27. self.y = y
  28. def __eq__(self, other):
  29. if self.x == other.x and self.y == other.y:
  30. return True
  31. return False
  32. def __str__(self):
  33. return "x:" + str(self.x) + ",y:" + str(self.y)
  34. class AStar:
  35. """
  36. AStar算法的Python3.x实现
  37. """
  38. class Node: # 描述AStar算法中的节点数据
  39. def __init__(self, point, endPoint, g=0):
  40. self.point = point # 自己的坐标
  41. self.father = None # 父节点
  42. self.g = g # g值,g值在用到的时候会重新算
  43. self.h = (abs(endPoint.x - point.x) +
  44. abs(endPoint.y - point.y)) * 10 # 计算h值
  45. def __init__(self, map2d, startPoint, endPoint, passTag=0):
  46. """
  47. 构造AStar算法的启动条件
  48. :param map2d: Array2D类型的寻路数组
  49. :param startPoint: Point或二元组类型的寻路起点
  50. :param endPoint: Point或二元组类型的寻路终点
  51. :param passTag: int类型的可行走标记(若地图数据!=passTag即为障碍)
  52. """
  53. # 开启表
  54. self.openList = []
  55. # 关闭表
  56. self.closeList = []
  57. # 寻路地图
  58. self.map2d = map2d
  59. # 起点终点
  60. #********** Begin **********#
  61. self.startPoint = startPoint
  62. self.endPoint = endPoint
  63. #********** End **********#
  64. # 可行走标记
  65. self.passTag = passTag
  66. def getMinNode(self):
  67. """
  68. 获得openlist中F值最小的节点
  69. :return: Node
  70. """
  71. #********** Begin **********#
  72. if len(self.openList) == 0:
  73. return None
  74. min_f = self.openList[0]
  75. for node in self.openList[1:]:
  76. if (node.g + node.h) < (min_f.g + min_f.h):
  77. min_f = node
  78. return min_f
  79. #********** End **********#
  80. def pointInCloseList(self, point):
  81. for node in self.closeList:
  82. if node.point == point:
  83. return True
  84. return False
  85. def pointInOpenList(self, point):
  86. for node in self.openList:
  87. if node.point == point:
  88. return node
  89. return None
  90. def endPointInCloseList(self):
  91. for node in self.openList:
  92. if node.point == self.endPoint:
  93. return node
  94. return None
  95. def searchNear(self, minF, offsetX, offsetY):
  96. """
  97. 搜索节点周围的点
  98. :param minF:F值最小的节点
  99. :param offsetX:坐标偏移量
  100. :param offsetY:
  101. :return:
  102. """
  103. # 越界检测
  104. #********** Begin **********#
  105. if (minF.point.x+offsetX) < 0 or (minF.point.x+offsetX) >= self.map2d.w or \
  106. (minF.point.y+offsetY) < 0 or (minF.point.y+offsetY) >= self.map2d.h:
  107. return
  108. #********** End **********#
  109. # 如果是障碍,就忽略
  110. if self.map2d[minF.point.x + offsetX][minF.point.y + offsetY] != self.passTag:
  111. return
  112. # 如果在关闭表中,就忽略
  113. currentPoint = Point(minF.point.x + offsetX, minF.point.y + offsetY)
  114. if self.pointInCloseList(currentPoint):
  115. return
  116. # 设置单位花费
  117. if offsetX == 0 or offsetY == 0:
  118. step = 10
  119. else:
  120. step = 14
  121. # 如果不再openList中,就把它加入openlist
  122. #********** Begin **********#
  123. currentNode = self.pointInOpenList(currentPoint)
  124. if not currentNode:
  125. new_node = AStar.Node(currentPoint, self.endPoint)
  126. new_node.father = minF
  127. self.openList.append(new_node)
  128. return
  129. #********** End **********#
  130. # 如果在openList中,判断minF到当前点的G是否更小
  131. if minF.g + step < currentNode.g: # 如果更小,就重新计算g值,并且改变father
  132. currentNode.g = minF.g + step
  133. currentNode.father = minF
  134. def start(self):
  135. """
  136. 开始寻路
  137. :return: None或Point列表(路径)
  138. """
  139. # 判断寻路终点是否是障碍
  140. if self.map2d[self.endPoint.x][self.endPoint.y] != self.passTag:
  141. return None
  142. # 定义算子
  143. directions = ((0, 1), (0, -1), (1, 0), (-1, 0))
  144. # 1.将起点放入开启列表
  145. startNode = AStar.Node(self.startPoint, self.endPoint)
  146. self.openList.append(startNode)
  147. # 2.主循环逻辑
  148. while True:
  149. # 找到F值最小的点
  150. minF = self.getMinNode()
  151. # 把这个点加入closeList中,并且在openList中删除它
  152. self.closeList.append(minF)
  153. self.openList.remove(minF)
  154. # 判断这个节点的上下左右节点
  155. #********** Begin **********#
  156. for i, j in directions:
  157. self.searchNear(minF, i, j)
  158. #********** End **********#
  159. # 判断是否终止
  160. point = self.endPointInCloseList()
  161. if point: # 如果终点在关闭表中,就返回结果
  162. # print("关闭表中")
  163. cPoint = point
  164. pathList = []
  165. while True:
  166. if cPoint.father:
  167. pathList.append(cPoint.point)
  168. cPoint = cPoint.father
  169. else:
  170. return list(reversed(pathList))
  171. if len(self.openList) == 0:
  172. return None