You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python实现A*算法无法返回存在路径的问题求助

A*算法返回None的问题修复

以下是代码中导致问题的关键错误及修复方案:

1. NODE类排序方法拼写错误

__lt__方法中调用了不存在的other.fcost()(小写c),但类中定义的方法是fCost()(大写C),这会导致堆排序时抛出AttributeError,中断搜索流程,最终返回None。

修正后的__lt__方法:

def __lt__(self, other):
    return self.fCost() < other.fCost()

2. 路径回溯使用错误节点

搜索到目标位置时,当前的current_node才是带有完整父节点链的路径节点,而初始创建的goal_node没有父节点信息,直接传入会导致回溯失败。

修改search方法中的目标判断逻辑:

if current_node.position == goal_node.position:
    return self.retracePath(start_node, current_node)  # 用current_node代替goal_node

3. OPEN堆节点判断逻辑错误

OPEN堆存储的是(fCost, node)元组,直接用neighbour in OPEN判断永远为False(元组和节点对象无法匹配)。需要新增集合跟踪OPEN中的节点,避免重复入堆。

优化后的search方法:

def search(self, start_node, goal_node):
    OPEN = []
    OPEN_SET = set()  # 记录OPEN中的节点
    CLOSED = set()
    start_node.h_cost = self.findManhattanDistance(start_node, goal_node)
    heapq.heappush(OPEN, (start_node.fCost(), start_node))
    OPEN_SET.add(start_node)
    
    while OPEN:
        current_cost, current_node = heapq.heappop(OPEN)
        OPEN_SET.remove(current_node)
        CLOSED.add(current_node)

        if current_node.position == goal_node.position:
            return self.retracePath(start_node, current_node)

        for neighbour in self.getNeighbours(current_node):
            if neighbour.isObstacle or neighbour in CLOSED:
                continue
            new_g_cost = current_node.g_cost + 1
            if new_g_cost < neighbour.g_cost or neighbour not in OPEN_SET:
                neighbour.g_cost = new_g_cost
                neighbour.h_cost = self.findManhattanDistance(neighbour, goal_node)
                neighbour.parent = current_node

                if neighbour not in OPEN_SET:
                    heapq.heappush(OPEN, (neighbour.fCost(), neighbour))
                    OPEN_SET.add(neighbour)

    return None

4. 可选优化:邻居节点生成逻辑

合并方向循环,简化代码(符合贪吃蛇只能上下左右移动的逻辑):

def getNeighbours(self, node):
    neighbours = []
    directions = [(-1,0), (1,0), (0,-1), (0,1)]  # 上下左右四个方向
    for dx, dy in directions:
        new_x = node.position[0] + dx
        new_y = node.position[1] + dy
        if 0 <= new_x < 16 and 0 <= new_y < 16:
            neighbours.append(NODE((new_x, new_y), node.g_cost + 1, float('inf'), node, False))
    return neighbours

完整修复代码

import heapq
from pygame import Vector2

class NODE:
    def __init__(self, position, g_cost, h_cost, parent, isObstacle):
        self.position = position
        self.g_cost = g_cost
        self.h_cost = h_cost
        self.parent = parent
        self.isObstacle = isObstacle

    def __eq__(self, other):
        return self.position == other.position

    def __lt__(self, other):
        return self.fCost() < other.fCost()

    def __hash__(self):
        return hash(self.position)

    def fCost(self):
        return self.g_cost + self.h_cost

class ASTAR:
    def __init__(self):
        pass

    def getNeighbours(self, node):
        neighbours = []
        directions = [(-1,0), (1,0), (0,-1), (0,1)]
        for dx, dy in directions:
            new_x = node.position[0] + dx
            new_y = node.position[1] + dy
            if 0 <= new_x < 16 and 0 <= new_y < 16:
                neighbours.append(NODE((new_x, new_y), node.g_cost + 1, float('inf'), node, False))
        return neighbours

    def findManhattanDistance(self, node1, node2):
        x1, y1 = node1.position
        x2, y2 = node2.position
        return abs(x1 - x2) + abs(y1 - y2)

    def search(self, start_node, goal_node):
        OPEN = []
        OPEN_SET = set()
        CLOSED = set()
        start_node.h_cost = self.findManhattanDistance(start_node, goal_node)
        heapq.heappush(OPEN, (start_node.fCost(), start_node))
        OPEN_SET.add(start_node)
        
        while OPEN:
            current_cost, current_node = heapq.heappop(OPEN)
            OPEN_SET.remove(current_node)
            CLOSED.add(current_node)

            if current_node.position == goal_node.position:
                return self.retracePath(start_node, current_node)

            for neighbour in self.getNeighbours(current_node):
                if neighbour.isObstacle or neighbour in CLOSED:
                    continue
                new_g_cost = current_node.g_cost + 1
                if new_g_cost < neighbour.g_cost or neighbour not in OPEN_SET:
                    neighbour.g_cost = new_g_cost
                    neighbour.h_cost = self.findManhattanDistance(neighbour, goal_node)
                    neighbour.parent = current_node

                    if neighbour not in OPEN_SET:
                        heapq.heappush(OPEN, (neighbour.fCost(), neighbour))
                        OPEN_SET.add(neighbour)

        return None

    def retracePath(self, start_node, goal_node):
        path = []
        current_node = goal_node

        while current_node != start_node:
            path.append(current_node.position)  # 可选:只存储坐标,方便贪吃蛇使用
            current_node = current_node.parent

        path.append(start_node.position)
        path.reverse()

        return path

astar = ASTAR()
start_node = NODE((0, 0), 0, 0, None, False)
goal_node = NODE((8, 8), 0, 0, None, False)
print(astar.search(start_node, goal_node))

内容的提问来源于stack exchange,提问作者pmoh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 05:53:22