import heapq from itertools import count from strategies.strategy import PathFindingStrategy class AStarStrategy(PathFindingStrategy): def _estimate(self, current, target): return ( abs(current.x - target.x) + abs(current.y - target.y) ) def findPath(self, maze, start, exit): frontier = [] sequence = count() heapq.heappush( frontier, ( self._estimate(start, exit), next(sequence), 0, start ) ) ancestry = {} travel_cost = { start.getPosition(): 0 } explored = set() explored_count = 0 while frontier: _, _, spent, current = heapq.heappop( frontier ) current_mark = current.getPosition() if current_mark in explored: continue explored.add(current_mark) explored_count += 1 if current == exit: break for neighbor in maze.getNeighbors(current): mark = neighbor.getPosition() new_cost = spent + 1 if ( mark not in travel_cost or new_cost < travel_cost[mark] ): travel_cost[mark] = new_cost ancestry[mark] = current priority = ( new_cost + self._estimate( neighbor, exit ) ) heapq.heappush( frontier, ( priority, next(sequence), new_cost, neighbor ) ) if ( exit.getPosition() not in ancestry and exit != start ): return [], explored_count route = [] cursor = exit while cursor != start: route.append(cursor) cursor = ancestry[ cursor.getPosition() ] route.append(start) route.reverse() return route, explored_count