我正在尝试理解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变量来管理程序,但是无法弄清楚整个列表是如何工作的,特别是如果我们想要包含墙。你能提供一些澄清/例子吗?
答案 0 :(得分:2)
mapinfo
对象(如给出的代码中所示)是传递给make_graph()
函数的字典参数,用于存储要搜索的网格的尺寸(宽度和高度)
您可以在函数调用之前定义它,然后将其传递给函数,如:
mapinfo = {"width": 8, "height": 8}
graph, nodes = make_graph(mapinfo)
问题是make_graph()
函数尝试直接访问width
中的height
和mapinfo
值(例如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)