Python实现A*算法,地图是二维数组形式

def A_star(pos_start, pos_end, map):
    """

    :param pos_start:   起点位置, 例如(3,3)
    :param pos_end:     终点位置, 例如(9,9)
    :param map:     用于记录地图信息的二维矩阵,0表示空白,1表示墙体等障碍物,9表示食物(终点)
    :return:
    """
    map_width = len(map[0])         #地图的宽
    map_height = len(map)           #地图的高
    open_list = order_seq()         #order_seq是我自己写的一个类,它会自动维护一个升序队列
    close_list = []                 #close_list
    open_list.append((0, 0, pos_start))         #首先将起点加入openlist中
    count = 0                       #记录遍历次数
    while True:
        count += 1                  #遍历次数+1
        if open_list.is_empty():    #如果open表为空,则说明没有路径可达终点,算法结束
            return False, {}, 0
        else:                       #如果open表不为空,则取出队列头,注意这里的pop是被我在order_seq类重写过的,它在这里取的是队列头
            temp_tuple = open_list.pop()  # temp_tuple like (1,2,(1,2)) referring to (F,G,(this_position)
        pos = temp_tuple[2]         #pos为从open表中取出的坐标,例如(1,1)
        if pos == pos_end:          #如果取出来的这个点就是终点,则算法结束,返回
            return True, open_list.last_dict,count

       #得到取出点的F值、G值以及坐标
        F = temp_tuple[0]
        G = temp_tuple[1]
        x = temp_tuple[2][0]
        y = temp_tuple[2][1]

        #接下来按照左、上、右、下的顺序将可走的点并且未在close表中的点加入到open表中,并计算它们的F值和G值
        #以左边的点为例
        if y - 1 >= 0 and map[x][y - 1] in [0, 9] and (x, y - 1) not in close_list:  # left
            New_G = G + 1       #新的G值等于当前点的G值加1,即经过的步数
            New_H = abs(pos_end[0] - x) + abs(pos_end[1] - (y - 1))             #这个点到终点的曼哈顿距离 H=|x1-x2|+|y1-y2|
            New_F = New_G + New_H           #F=G+H
            New_tuple = (New_F, New_G, (x, y - 1))
            open_list.append(New_tuple, pos)        #将新的点加入openlist中

        if x - 1 >= 0 and map[x - 1][y] in [0, 9] and (x - 1, y) not in close_list:  # up
            New_G = G + 1
            New_H = abs(pos_end[0] - (x - 1)) + abs(pos_end[1] - y)
            New_F = New_G + New_H
            New_tuple = (New_F, New_G, (x - 1, y))
            open_list.append(New_tuple, pos)

        if y + 1 < map_width and map[x][y + 1] in [0, 9] and (x, y + 1) not in close_list:  # right
            New_G = G + 1
            New_H = abs(pos_end[0] - x) + abs(pos_end[1] - (y + 1))
            New_F = New_G + New_H
            New_tuple = (New_F, New_G, (x, y + 1))
            open_list.append(New_tuple, pos)

        if x + 1 < map_height and map[x + 1][y] in [0, 9] and (x + 1, y) not in close_list:  # down
            New_G = G + 1
            New_H = abs(pos_end[0] - (x + 1)) + abs(pos_end[1] - y)
            New_F = New_G + New_H
            New_tuple = (New_F, New_G, (x + 1, y))
            open_list.append(New_tuple, pos)
        close_list.append(pos)

在A*算法中,需要维护一个open表,每次取出open表中F值最小的点,为了简化操作,我自己写了一个类order_seq


class order_seq():  # ascending
    def __init__(self):
        self.data = []
        self.last_dict = {}  # create mapping from this pos to last pos  eg:  (1,2) -> (3,4) means the last position of (1,2) is (3,4)

    def append(self, tuple, last_pos=(-1, -1)):  # tuple like ( 1,1,(1,2)) refering to (F,G,(this_position))
        insert_tag = True
        if self.data == []:
            self.data.append(tuple)
            self.last_dict[tuple[2]] = last_pos
        else:
            for item in self.data:
                if tuple[2] == item[2]:
                    if tuple[1] < item[1]:
                        self.data.remove(item)
                    else:
                        insert_tag = False
                    break
            if insert_tag:
                is_insert = False
                for id, item in enumerate(self.data):
                    if tuple[0] <= item[0]:
                        self.data.insert(id, tuple)
                        self.last_dict[tuple[2]] = last_pos
                        is_insert = True
                        break
                if not is_insert:
                    self.data.append(tuple)
                    self.last_dict[tuple[2]] = last_pos

    def pop(self):
        return self.data.pop(0)

    def is_empty(self):
        if self.data == []:
            return True
        else:
            return False

最后,这里的A*算法返回的是什么东西呢?我让其返回了三样东西:①是否找到路径?(True or False)②一个用于记录某位置的上一个位置的字典(映射)last_dict ③while循环遍历的次数(这个可以根据需要自行删除)

这里详细介绍一下last_dict是干嘛用的:
它里面存放的形式如下:

该位置上一个位置
(1,2)(1,1)
(1,1)(1,0)
(1,0)(0,0)
(0,0)(-1,-1)

last_dict建立的就是该位置到上一个位置的映射

如上表的含义为(1,2)的上一步是(1,1), (1,1)的上一步是(1,0),(1,0)的上一步是(0,0),由于(0,0)的上一步是(-1,-1)说明(0,0)是起点(在代码中首先将起点加入open表中时,会首先建立一个(起点)->(-1,-1)的映射)。通过这样的方法可以还原出找到的路径。例如,假设上表中终点是(1,2),就可以逆向形成一个搜索链(1,2)->(1,1)->(1,0)->(0,0),这就是倒过来的路径。

这里提供还原逆向路径的函数:path_parser

def path_parser(food_pos,last_dict):
"""
food_pos:终点坐标,例如(9,9)
last_dict: 就是A*算法返回的last_dict
"""
	path_list=[]
    path_list.append(food_pos)
    temp=path_dict[food_pos]
    while temp != (-1,-1):
         path_list.append(temp)
         temp=path_dict[temp]
    return path_list

最后就是一个简单的应用示例:

map = [[0, 0, 0, 1, 0],
       [0, 0, 0, 1, 0],
       [0, 0, 9, 1, 0],
       [1, 1, 1, 1, 0],
       [1, 0, 0, 0, 0]]
flag, dict,count = A_star((0, 0), (2, 2), map)
#解析路径
path_list=path_parser((2,2),dict))
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是Python实现A*算法的示例代码: ```python import heapq def heuristic(a, b): # 计算两点之间的曼哈顿距离 return abs(a[0] - b[0]) + abs(a[1] - b[1]) def astar(array, start, goal): neighbors = [(0,1),(0,-1),(1,0),(-1,0),(1,1),(1,-1),(-1,1),(-1,-1)] close_set = set() came_from = {} gscore = {start:0} fscore = {start:heuristic(start, goal)} oheap = [] heapq.heappush(oheap, (fscore[start], start)) while oheap: current = heapq.heappop(oheap)[1] if current == goal: data = [] while current in came_from: data.append(current) current = came_from[current] return data[::-1] close_set.add(current) for i, j in neighbors: neighbor = current[0] + i, current[1] + j tentative_g_score = gscore[current] + heuristic(current, neighbor) if 0 <= neighbor[0] < array.shape[0]: if 0 <= neighbor[1] < array.shape[1]: if array[neighbor[0]][neighbor[1]] == 1: continue else: # 超出边界 continue else: # 超出边界 continue if neighbor in close_set and tentative_g_score >= gscore.get(neighbor, 0): continue if tentative_g_score < gscore.get(neighbor, 0) or neighbor not in [i[1] for i in oheap]: came_from[neighbor] = current gscore[neighbor] = tentative_g_score fscore[neighbor] = tentative_g_score + heuristic(neighbor, goal) heapq.heappush(oheap, (fscore[neighbor], neighbor)) return False ``` 在这个示例中,我们使用了一个二维数组表示地图,1表示障碍物,0表示可以通过。起始点和目标点分别用元组表示。`heuristic`函数计算两点之间的曼哈顿距离,`astar`函数实现了A*算法的核心部分。它使用堆来搜寻下一个搜索的节点,并计算每个节点到终点的距离,然后选择最短的路径。如果找到了路径,则返回路径,否则返回False。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值