Files
maze_solver/pathfinding_algorithms.py
klein panic aeaa436c25 first commit
2024-10-23 18:44:54 -04:00

123 lines
3.4 KiB
Python

# pathfinding_algorithms.py
from collections import deque
import heapq
def get_adjacent_cells(cell, maze):
row, col = cell
directions = [(-1,0), (1,0), (0,-1), (0,1)]
neighbors = []
for dr, dc in directions:
r, c = row + dr, col + dc
if 0 <= r < maze.shape[0] and 0 <= c < maze.shape[1] and maze[r][c] == 0:
neighbors.append((r, c))
return neighbors
def bfs_generator(maze, start, end):
queue = deque([start])
visited = set()
visited.add(start)
parent = {}
steps = 0
while queue:
current = queue.popleft()
steps += 1
yield ('visit', current, steps)
if current == end:
break
for neighbor in get_adjacent_cells(current, maze):
if neighbor not in visited:
queue.append(neighbor)
visited.add(neighbor)
parent[neighbor] = current
yield ('enqueue', neighbor, steps)
# Reconstruct path
path = []
if end in parent:
cell = end
while cell != start:
path.append(cell)
cell = parent[cell]
path.append(start)
path.reverse()
for cell in path:
yield ('path', cell, steps)
yield ('done', None, steps)
def dfs_generator(maze, start, end):
stack = [start]
visited = set()
visited.add(start)
parent = {}
steps = 0
while stack:
current = stack.pop()
steps += 1
yield ('visit', current, steps)
if current == end:
break
for neighbor in reversed(get_adjacent_cells(current, maze)):
if neighbor not in visited:
stack.append(neighbor)
visited.add(neighbor)
parent[neighbor] = current
yield ('enqueue', neighbor, steps)
# Reconstruct path
path = []
if end in parent:
cell = end
while cell != start:
path.append(cell)
cell = parent[cell]
path.append(start)
path.reverse()
for cell in path:
yield ('path', cell, steps)
yield ('done', None, steps)
def a_star_generator(maze, start, end):
heap = []
heapq.heappush(heap, (0, start))
came_from = {}
g_score = {start: 0}
f_score = {start: heuristic(start, end)}
steps = 0
while heap:
_, current = heapq.heappop(heap)
steps += 1
yield ('visit', current, steps)
if current == end:
break
for neighbor in get_adjacent_cells(current, maze):
tentative_g = g_score[current] + 1
if neighbor not in g_score or tentative_g < g_score[neighbor]:
came_from[neighbor] = current
g_score[neighbor] = tentative_g
f_score_neighbor = tentative_g + heuristic(neighbor, end)
f_score[neighbor] = f_score_neighbor
heapq.heappush(heap, (f_score_neighbor, neighbor))
yield ('enqueue', neighbor, steps)
# Reconstruct path
path = []
if end in came_from:
cell = end
while cell != start:
path.append(cell)
cell = came_from[cell]
path.append(start)
path.reverse()
for cell in path:
yield ('path', cell, steps)
yield ('done', None, steps)
def heuristic(a, b):
# Manhattan distance
return abs(a[0] - b[0]) + abs(a[1] - b[1])