Skip to content

Instantly share code, notes, and snippets.

@xkyii
Forked from jdp/LICENSE
Created May 25, 2012 11:13
Show Gist options
  • Save xkyii/2787372 to your computer and use it in GitHub Desktop.
Save xkyii/2787372 to your computer and use it in GitHub Desktop.
A* pathfinding over any arbitrary graph structure, with example Cartesian grid implementation
class AStar(object):
def __init__(self, graph):
self.graph = graph
def heuristic(self, node, start, end):
raise NotImplementedError
def search(self, start, end):
openset = set()
closedset = set()
current = start
openset.add(current)
while openset:
current = min(openset, key=lambda o:o.g + o.h)
if current == end:
path = []
while current.parent:
path.append(current)
current = current.parent
path.append(current)
return path[::-1]
openset.remove(current)
closedset.add(current)
for node in self.graph[current]:
if node in closedset:
continue
if node in openset:
new_g = current.g + current.move_cost(node)
if node.g > new_g:
node.g = new_g
node.parent = current
else:
node.g = current.g + current.move_cost(node)
node.h = self.heuristic(node, start, end)
node.parent = current
openset.add(node)
return None
class AStarNode(object):
def __init__(self):
self.g = 0
self.h = 0
self.parent = None
def move_cost(self, other):
raise NotImplementedError
from astar import AStar, AStarNode
from math import sqrt
class AStarGrid(AStar):
def heuristic(self, node, start, end):
return sqrt((end.x - node.x)**2 + (end.y - node.y)**2)
class AStarGridNode(AStarNode):
def __init__(self, x, y):
self.x, self.y = x, y
super(AStarGridNode, self).__init__()
def move_cost(self, other):
diagonal = abs(self.x - other.x) == 1 and abs(self.y - other.y) == 1
return 14 if diagonal else 10
from astar_grid import AStarGrid, AStarGridNode
from itertools import product
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment