如何构建此A *程序的邻接列表

时间:2013-01-18 00:12:09

标签: python path-finding a-star

我正在尝试理解A *路径查找算法,以及如何在python程序中实现它。我发现this website可以很好地解释算法本身的工作原理,并提供一些示例代码。

这是我陷入困境的地方:

def make_graph(mapinfo):

nodes = [[AStarGridNode(x, y) for y in range(mapinfo.height)] for x in range(mapinfo.width)]
graph = {}
for x, y in product(range(mapinfo.width), range(mapinfo.height)):
    node = nodes[x][y]
    graph[node] = []
    for i, j in product([-1, 0, 1], [-1, 0, 1]):
        if not (0 <= x + i < mapinfo.width): continue
        if not (0 <= y + j < mapinfo.height): continue
        graph[nodes[x][y]].append(nodes[x+i][y+j])
return graph, nodes

graph, nodes = make_graph({"width": 8, "height": 8})
paths = AStarGrid(graph)
start, end = nodes[1][1], nodes[5][7]
path = paths.search(start, end)
if path is None:
    print "No path found"
else:
    print "Path found:", path

我不明白“ mapinfo ”对象应该如何显示。我通过用一些数字替换mapinfo变量来管理程序,但是无法弄清楚整个列表是如何工作的,特别是如果我们想要包含墙。你能提供一些澄清/例子吗?

1 个答案:

答案 0 :(得分:2)

mapinfo对象(如给出的代码中所示)是传递给make_graph()函数的字典参数,用于存储要搜索的网格的尺寸(宽度和高度)

您可以在函数调用之前定义它,然后将其传递给函数,如:

mapinfo = {"width": 8, "height": 8}
graph, nodes = make_graph(mapinfo)

问题是make_graph()函数尝试直接访问width中的heightmapinfo值(例如mapinfo.height),结果例外AttributeError: 'dict' object has no attribute 'height'

我能想到的两个选择是:

  • 更改make_graph()中的语句,按键而非按属性访问字典元素,方法是将所有mapinfo.height更改为mapinfo['height'],同样更改宽度),或
  • 使用您需要的属性创建一个MapInfo类,并将其实例传递给make_graph()函数而不是字典。

    class MapInfo(object):
        def __init__(self, width, height):
            self.width = width
            self.height = height
    
    # ...
    
    mapinfo = MapInfo(width=8, height=8)
    graph, nodes = make_graph(mapinfo)
    

如果你想要包括无法通行的地形,你必须做更多的事情,例如墙壁。

也许通过给它另一个属性扩展MapInfo类:

def __init__(self, width, height, impassable=[]):
    """Create a MapInfo object representing the search area and obstacles.

        Args:
            width: Integer representing the width of the area
            height: Integer representing the height of the area
            impassable: List of (x, y) tuples representing impassable obstacles.
    """
    self.width = width
    self.height = height
    self.impassable = impassable

接下来,您需要修改make_graph()函数,以便只在目标区域无法通行的情况下在两个网格空间之间添加边。

for i, j in product([-1, 0, 1], [-1, 0, 1]):
    # Check that we are inside the grid area.
    if not (0 <= x + i < mapinfo.width): continue
    if not (0 <= y + j < mapinfo.height): continue
    # Check if the target area is impassable.
    if (x + i, y + j) in mapinfo.impassable: continue
    # All looks good. Add target space as reachable from current (x, y) space.
    graph[nodes[x][y]].append(nodes[x+i][y+j])

然后,您将根据需要修改您的mapinfo实例定义以及其他无法通过的区域:

impassable = [(3, 3), (3, 4), (3, 5)]  # modify to your needs
mapinfo = MapInfo(width=8, height=8, impassable=impassable)