-
Notifications
You must be signed in to change notification settings - Fork 8
/
a_star.py
75 lines (63 loc) · 2.25 KB
/
a_star.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
from queues import PriorityQueue
def heuristic(tile1, tile2):
"""
Manhattan distance between two tiles.
:param tile1: Tile
:param tile2: Tile
:return: int distance
"""
(x1, y1) = (tile1.r, tile1.c)
(x2, y2) = (tile2.r, tile2.c)
return abs(x1 - x2) + abs(y1 - y2)
def reconstruct_path(came_from, start, end):
"""
Reconstructs the came_from dictionary to be a list of tiles
we can traverse and draw later.
:param came_from: dictionary
:param start: Tile
:param end: Tile
:return: List path
"""
current = end
path = [current]
while current != start:
current = came_from[current]
path.append(current)
path.append(start) # optional
path.reverse() # optional
return path
def a_star(start, end):
"""
A* Pathfinding algorithm. Takes a start tile and end tile, and uses
their neighbour list to traverse.
Uses the heapq queue in queues.py.
:param start: Tile
:param end: Tile
:return: came_from, dictionary with all tiles as key, and where we came from (parent tile) as value.
cost_so_far, dictionary with tiles as key, and their cost so far as value.
success, True or False. If the algorithm found the end tile or not.
has_been_next, list over tiles that has been considered as the next tile.
"""
frontier = PriorityQueue()
frontier.put(start, 0)
came_from = {start: None}
cost_so_far = {start: 0}
has_been_next = []
success = False
while not frontier.empty():
current = frontier.pop()
current.visit()
if current == end:
print("A* Pathfinder, successful.")
success = True
break
for next_tile in current.neighbours:
if next_tile not in has_been_next:
has_been_next.append(next_tile)
new_cost = cost_so_far[current] + next_tile.weight
if next_tile not in cost_so_far or new_cost < cost_so_far[next_tile]:
cost_so_far[next_tile] = new_cost
priority = new_cost + heuristic(end, next_tile)
frontier.put(next_tile, priority)
came_from[next_tile] = current
return came_from, cost_so_far, success, has_been_next