-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathastar_pathfinding.py
84 lines (63 loc) · 2.52 KB
/
astar_pathfinding.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
76
77
78
79
80
81
82
83
84
import pygame
import math
from node import Node
from node_state_enum import NodeState
from queue import PriorityQueue
def h(node1: tuple, node2: tuple) -> float:
x1, y1 = node1
x2, y2 = node2
return abs(x2 - x1) + abs(y2 - y1)
def d(node1: tuple, node2: tuple) -> float:
x1, y1 = node1
x2, y2 = node2
return math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)
def reconstruct_path(came_from: dict, current: Node, draw) -> tuple[int, int]:
i = 0
l = 0
last: Node = current
while current in came_from:
current = came_from[current]
l += d(last.get_pos(), current.get_pos())
current.set_state(NodeState.PATH)
last = current
draw()
i += 1
return i, l
def astar_algorithm(draw, grid: list[list[Node]], start: Node, end: Node) -> tuple[int, int]:
count: int = 0
length: int = 0
open_set = PriorityQueue()
open_set.put((0, count, start))
came_from: dict = {}
g_score: dict = {node: float("inf") for row in grid for node in row}
g_score[start] = 0
f_score: dict = {node: float("inf") for row in grid for node in row}
f_score[start] = h(start.get_pos(), end.get_pos())
open_set_hash: set = {start}
while not open_set.empty():
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
current: Node = open_set.get()[2]
open_set_hash.remove(current)
if current == end:
count, length = reconstruct_path(came_from, end, draw)
start.set_state(NodeState.START)
end.set_state(NodeState.END)
return count, length
for neighbor in current.neighbors:
tentative_g_score = g_score[current] + d(current.get_pos(), neighbor.get_pos())
if tentative_g_score < g_score[neighbor]:
came_from[neighbor] = current
g_score[neighbor] = tentative_g_score
f_score[neighbor] = tentative_g_score + h(neighbor.get_pos(), end.get_pos())
if neighbor not in open_set_hash:
count += 1
open_set.put((f_score[neighbor], count, neighbor))
open_set_hash.add(neighbor)
neighbor.set_state(NodeState.OPEN)
draw()
if current != start:
current.set_state(NodeState.CLOSED)
return count, length