2026-rff_mp/groshevava/docs/data/strategies.py

104 lines
3.3 KiB
Python
Raw Normal View History

from abc import ABC, abstractmethod
from collections import deque
import heapq
from typing import List, Dict, Optional
from models import Cell, Maze
class PathFindingStrategy(ABC):
def __init__(self):
self.visited_count = 0
@abstractmethod
def findPath(self, maze: Maze, start: Cell, exit: Cell) -> List[Cell]:
pass
def _reconstruct_path(self, parent: Dict[Cell, Optional[Cell]], current: Cell) -> List[Cell]:
path = []
while current:
path.append(current)
current = parent.get(current)
return path[::-1]
class BFSStrategy(PathFindingStrategy):
def findPath(self, maze: Maze, start: Cell, exit: Cell) -> List[Cell]:
self.visited_count = 0
queue = deque([start])
visited = {start}
parent = {start: None}
while queue:
current = queue.popleft()
self.visited_count += 1
if current == exit:
return self._reconstruct_path(parent, current)
for neighbor in maze.getNeighbors(current):
if neighbor not in visited:
visited.add(neighbor)
parent[neighbor] = current
queue.append(neighbor)
return []
class DFSStrategy(PathFindingStrategy):
def findPath(self, maze: Maze, start: Cell, exit: Cell) -> List[Cell]:
self.visited_count = 0
stack = [start]
visited = {start}
parent = {start: None}
while stack:
current = stack.pop()
self.visited_count += 1
if current == exit:
return self._reconstruct_path(parent, current)
for neighbor in maze.getNeighbors(current):
if neighbor not in visited:
visited.add(neighbor)
parent[neighbor] = current
stack.append(neighbor)
return []
class AStarStrategy(PathFindingStrategy):
@staticmethod
def _heuristic(a: Cell, b: Cell) -> int:
return abs(a.x - b.x) + abs(a.y - b.y)
def findPath(self, maze: Maze, start: Cell, exit: Cell) -> List[Cell]:
self.visited_count = 0
counter = 0
open_set = []
heapq.heappush(open_set, (0, counter, start))
counter += 1
came_from = {start: None}
g_score = {start: 0}
visited = set()
while open_set:
_, _, current = heapq.heappop(open_set)
self.visited_count += 1
if current == exit:
return self._reconstruct_path(came_from, current)
if current in visited:
continue
visited.add(current)
for neighbor in maze.getNeighbors(current):
tentative_g_score = g_score[current] + 1
if neighbor not in g_score or tentative_g_score < g_score[neighbor]:
came_from[neighbor] = current
g_score[neighbor] = tentative_g_score
f_score = tentative_g_score + self._heuristic(neighbor, exit)
heapq.heappush(open_set, (f_score, counter, neighbor))
counter += 1
return []