环境:win10 语言: Python3.6 编译器:pycharm
先看效果图(红色:终点 黄色:起点 黑色:障碍 绿色路径)
一、A*算法:
A*算法是一种启发式搜索算法,它不需遍历所有节点,只是利用包含问题启发式信息的评价函数对节点进行排序,使搜索方向朝着最有可能找到目标并产生最优解的方向。它的独特之处是检查最短路径中每个可能的节点时引入了全局信息,对当前节点距终点的距离做出估计,并作为评价节点处于最短路径上的可能性度量。
A*算法中引入了评估函数,评估函数为:f(n)=g(n)+h(n) 其中:n是搜索中遇到的任意状态。g(n)是沿路径从起点到n点的移动耗费。h(n)是对n到目标状态代价的启发式估计。即评估函数f ( n) 是从初始节点到达节点n 处已经付出的代价与节点n 到达目标节点的接近程度估价值的总和。
这里我们定义n点到目标点的最小实际距离为h(n)*,A*算法要满足的条件为:h(n)<=h(n)* 。迷宫走的时候只能往上下左右走,每走一步,代价为1,H值可以用不同的方法估算。我们这里使用的方法被称为曼哈顿方法,它计算从当前格到目的格之间水平和垂直的方格的数量总和,即: h(n)=|endPoint.x – n.x|+ |endpoint.y – n.y|这里endPoint表示迷宫的目标点,n表示当前点,很明显这里h(n)<=h(n)*。
二、类的定义
1、mapPoint :代表图中的每一个格子,搜索路径的每一个格子,记录的信息有:
self.x = x self.y = y 当前节点的坐标位置
self.distanceStart = distanceStart 记录下由起点走到该节点的耗散值(由起点走到该节点的路径的距离,该节点的下一个节点会加1)
self.endX = endX self.endY = endY 目标节点
self.parentPoint = parentPoint # 前一个节点
方法:
评价函数:由于该评价函数比较容易计算,我直接放到该类中
def evaluate(self): return self.distanceStart + abs(self.x - self.endX) + abs(self.y - self.endY)
判断两个节点是否是同一个位置的
def isEq(self, point): if point.x == self.x and point.y == self.y: return True else: return False
以下是A*算法
def Astart(self):
# 将起点放到open表中
self.openList.append(self.startPoint)
while (not self.isOK):
# 先检查终点是否在open表中 ,没有继续,有则结束
if self.inOpenList(self.endPoint) != -1: # 在open表中
self.isOK = True #
self.end = self.openList[self.inOpenList(self.endPoint)]
self.route.append(self.end)
self.te = self.end
while (self.te.parentPoint != 0):
self.te = self.te.parentPoint
self.route.append(self.te)
else:
self.sortOpenList() # 将估值最小的节点放在index = 0
current_min = self.openList[0] # 估值最小节点
self.openList.pop(0)
self.closeList.append(current_min)
# 开拓current_min节点,并放到open 表
if current_min.x - 1 >= 0: # 没有越界
if (self.mapStatus[current_min.y][current_min.x - 1]) != 0: # 非障碍,可开拓
self.temp1 = mapPoint(current_min.x - 1, current_min.y, current_min.distanceStart + 1,
self.endPoint.x, self.endPoint.y, current_min)
if self.inOpenList(self.temp1) != -1: # open表存在相同的节点
if self.temp1.evaluate() < self.openList[self.inOpenList(self.temp1)].evaluate():
self.openList[self.inOpenList(self.temp1)] = self.temp1
elif self.inCloseList(self.temp1) != -1: # 否则查看close表是否存在相同的节点(存在)
if self.temp1.evaluate() < self.closeList[self.inCloseList(self.temp1)].evaluate():
self.closeList[self.inCloseList(self.temp1)] = self.temp1
else: # open 、 close表都不存在 temp1
self.openList.append(self.temp1)
if current_min.x + 1 < 15:
if (self.mapStatus[current_min.y][current_min.x + 1]) != 0: # 非障碍,可开拓
self.temp2 = mapPoint(current_min.x + 1, current_min.y, current_min.distanceStart + 1,
self.endPoint.x, self.endPoint.y, current_min)
if self.inOpenList(self.temp2) != -1: # open表存在相同的节点
if self.temp2.evaluate() < self.openList[self.inOpenList(self.temp2)].evaluate():
self.openList