当前位置:   article > 正文

python3.6实现的A星算法_a星算法python

a星算法python

A星算法原理:

    原理我就不再赘述,可以参考这篇博客https://blog.csdn.net/hitwhylz/article/details/23089415

    最近用js写了一遍,用的同样的算法,需要js代码的看这里:https://blog.csdn.net/qq_39687901/article/details/85697127

代码实现:

    首先添加两个通用类Array2D和Point:

  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]

 

  1. class Point:
  2. """
  3. 表示一个点
  4. """
  5. def __init__(self,x,y):
  6. self.x=x;self.y=y
  7. def __eq__(self, other):
  8. if self.x==other.x and self.y==other.y:
  9. return True
  10. return False
  11. def __str__(self):
  12. return "x:"+str(self.x)+",y:"+str(self.y)

 

    Array2D是为了简化二维数组的创建,Point是为了表示一个点,并且重载等号运算符,可以判断两个Point坐标是否相等.

 

    AStar类:

    

  1. class AStar:
  2. """
  3. AStar算法的Python3.x实现
  4. """
  5. class Node: # 描述AStar算法中的节点数据
  6. def __init__(self, point, endPoint, g=0):
  7. self.point = point # 自己的坐标
  8. self.father = None # 父节点
  9. self.g = g # g值,g值在用到的时候会重新算
  10. self.h = (abs(endPoint.x - point.x) + abs(endPoint.y - point.y)) * 10 # 计算h值
  11. def __init__(self, map2d, startPoint, endPoint, passTag=0):
  12. """
  13. 构造AStar算法的启动条件
  14. :param map2d: Array2D类型的寻路数组
  15. :param startPoint: Point或二元组类型的寻路起点
  16. :param endPoint: Point或二元组类型的寻路终点
  17. :param passTag: int类型的可行走标记(若地图数据!=passTag即为障碍)
  18. """
  19. # 开启表
  20. self.openList = []
  21. # 关闭表
  22. self.closeList = []
  23. # 寻路地图
  24. self.map2d = map2d
  25. # 起点终点
  26. if isinstance(startPoint, Point) and isinstance(endPoint, Point):
  27. self.startPoint = startPoint
  28. self.endPoint = endPoint
  29. else:
  30. self.startPoint = Point(*startPoint)
  31. self.endPoint = Point(*endPoint)
  32. # 可行走标记
  33. self.passTag = passTag
  34. def getMinNode(self):
  35. """
  36. 获得openlist中F值最小的节点
  37. :return: Node
  38. """
  39. currentNode = self.openList[0]
  40. for node in self.openList:
  41. if node.g + node.h < currentNode.g + currentNode.h:
  42. currentNode = node
  43. return currentNode
  44. def pointInCloseList(self, point):
  45. for node in self.closeList:
  46. if node.point == point:
  47. return True
  48. return False
  49. def pointInOpenList(self, point):
  50. for node in self.openList:
  51. if node.point == point:
  52. return node
  53. return None
  54. def endPointInCloseList(self):
  55. for node in self.openList:
  56. if node.point == self.endPoint:
  57. return node
  58. return None
  59. def searchNear(self, minF, offsetX, offsetY):
  60. """
  61. 搜索节点周围的点
  62. :param minF:F值最小的节点
  63. :param offsetX:坐标偏移量
  64. :param offsetY:
  65. :return:
  66. """
  67. # 越界检测
  68. if minF.point.x + offsetX < 0 or minF.point.x + offsetX > self.map2d.w - 1 or minF.point.y + offsetY < 0 or minF.point.y + offsetY > self.map2d.h - 1:
  69. return
  70. # 如果是障碍,就忽略
  71. if self.map2d[minF.point.x + offsetX][minF.point.y + offsetY] != self.passTag:
  72. return
  73. # 如果在关闭表中,就忽略
  74. currentPoint = Point(minF.point.x + offsetX, minF.point.y + offsetY)
  75. if self.pointInCloseList(currentPoint):
  76. return
  77. # 设置单位花费
  78. if offsetX == 0 or offsetY == 0:
  79. step = 10
  80. else:
  81. step = 14
  82. # 如果不再openList中,就把它加入openlist
  83. currentNode = self.pointInOpenList(currentPoint)
  84. if not currentNode:
  85. currentNode = AStar.Node(currentPoint, self.endPoint, g=minF.g + step)
  86. currentNode.father = minF
  87. self.openList.append(currentNode)
  88. return
  89. # 如果在openList中,判断minF到当前点的G是否更小
  90. if minF.g + step < currentNode.g: # 如果更小,就重新计算g值,并且改变father
  91. currentNode.g = minF.g + step
  92. currentNode.father = minF
  93. def start(self):
  94. """
  95. 开始寻路
  96. :return: None或Point列表(路径)
  97. """
  98. # 判断寻路终点是否是障碍
  99. if self.map2d[self.endPoint.x][self.endPoint.y] != self.passTag:
  100. return None
  101. # 1.将起点放入开启列表
  102. startNode = AStar.Node(self.startPoint, self.endPoint)
  103. self.openList.append(startNode)
  104. # 2.主循环逻辑
  105. while True:
  106. # 找到F值最小的点
  107. minF = self.getMinNode()
  108. # 把这个点加入closeList中,并且在openList中删除它
  109. self.closeList.append(minF)
  110. self.openList.remove(minF)
  111. # 判断这个节点的上下左右节点
  112. self.searchNear(minF, 0, -1)
  113. self.searchNear(minF, 0, 1)
  114. self.searchNear(minF, -1, 0)
  115. self.searchNear(minF, 1, 0)
  116. # 判断是否终止
  117. point = self.endPointInCloseList()
  118. if point: # 如果终点在关闭表中,就返回结果
  119. # print("关闭表中")
  120. cPoint = point
  121. pathList = []
  122. while True:
  123. if cPoint.father:
  124. pathList.append(cPoint.point)
  125. cPoint = cPoint.father
  126. else:
  127. # print(pathList)
  128. # print(list(reversed(pathList)))
  129. # print(pathList.reverse())
  130. return list(reversed(pathList))
  131. if len(self.openList) == 0:
  132. return None

 

    最后,进行代码测试:

    

 

  1. if __name__ == '__main__':
  2. #创建一个10*10的地图
  3. map2d=Array2D(10,10)
  4. #设置障碍
  5. map2d[4][0]= 1
  6. map2d[4][1] = 1
  7. map2d[4][2] = 1
  8. map2d[4][3] = 1
  9. map2d[4][4] = 1
  10. map2d[4][5] = 1
  11. map2d[4][6] = 1
  12. #显示地图当前样子
  13. map2d.showArray2D()
  14. #创建AStar对象,并设置起点为0,0终点为9,0
  15. aStar=AStar(map2d,Point(0,0),Point(9,0))
  16. #开始寻路
  17. pathList=aStar.start()
  18. #遍历路径点,在map2d上以'8'显示
  19. for point in pathList:
  20. map2d[point.x][point.y]=8
  21. # print(point)
  22. print("----------------------")
  23. #再次显示地图
  24. map2d.showArray2D()

 

运行效果:

最近用这个A星算法在游戏里实际应用上了:

https://blog.csdn.net/qq_39687901/article/details/88554716

 

 

    

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

闽ICP备14008679号