2026-rff_mp/lomakinae/docs/data/02/src/strategies.py

104 lines
3.4 KiB
Python
Raw Normal View History

import heapq
from abc import ABC, abstractmethod
from collections import deque
from typing import List
from .cell import Cell
from .maze import Maze
class PathFindingStrategy(ABC):
def __init__(self):
self.visited_count = 0
@abstractmethod
def find_path(self, maze: Maze, start: Cell, exit_cell: Cell) -> List[Cell]:
pass
def reconstruct_path(self, came_from: dict, exit_cell: Cell) -> List[Cell]:
path = []
current = exit_cell
while current is not None:
path.append(current)
current = came_from.get(current)
path.reverse()
return path
class BFSStrategy(PathFindingStrategy):
def find_path(self, maze: Maze, start: Cell, exit_cell: Cell) -> List[Cell]:
queue = deque([start])
came_from = {start: None}
visited = {start}
while queue:
current = queue.popleft()
if current == exit_cell:
self.visited_count = len(visited)
return self.reconstruct_path(came_from, exit_cell)
for neighbor in maze.get_neighbors(current):
if neighbor not in visited:
visited.add(neighbor)
came_from[neighbor] = current
queue.append(neighbor)
self.visited_count = len(visited)
return []
class DFSStrategy(PathFindingStrategy):
def find_path(self, maze: Maze, start: Cell, exit_cell: Cell) -> List[Cell]:
stack = [start]
came_from = {start: None}
visited = {start}
while stack:
current = stack.pop()
if current == exit_cell:
self.visited_count = len(visited)
return self.reconstruct_path(came_from, exit_cell)
for neighbor in maze.get_neighbors(current):
if neighbor not in visited:
visited.add(neighbor)
came_from[neighbor] = current
stack.append(neighbor)
self.visited_count = len(visited)
return []
class AStarStrategy(PathFindingStrategy):
def heuristic(self, cell: Cell, exit_cell: Cell) -> int:
return abs(cell.x - exit_cell.x) + abs(cell.y - exit_cell.y)
def find_path(self, maze: Maze, start: Cell, exit_cell: Cell) -> List[Cell]:
heap = []
counter = 0
start_f = self.heuristic(start, exit_cell)
heapq.heappush(heap, (start_f, counter, start))
counter += 1
came_from = {}
g_score = {start: 0}
f_score = {start: start_f}
visited = set()
while heap:
current_f, _, current = heapq.heappop(heap)
visited.add(current)
if current == exit_cell:
self.visited_count = len(visited)
return self.reconstruct_path(came_from, exit_cell)
if current_f > f_score.get(current, float("inf")):
continue
for neighbor in maze.get_neighbors(current):
tentative_g = g_score[current] + 1
if tentative_g < g_score.get(neighbor, float("inf")):
came_from[neighbor] = current
g_score[neighbor] = tentative_g
new_f = tentative_g + self.heuristic(neighbor, exit_cell)
f_score[neighbor] = new_f
heapq.heappush(heap, (new_f, counter, neighbor))
counter += 1
self.visited_count = len(visited)
return []