2026-rff_mp/pogodinda/lab2/src/maze_solver.py

86 lines
3.2 KiB
Python
Raw Normal View History

import time
from dataclasses import dataclass
from typing import List, Optional
from maze import Maze, Cell
from pathfinding import PathFindingStrategy
@dataclass
class SearchStats:
"""Статистика поиска пути."""
time_ms: float # время выполнения в миллисекундах
visited_cells: int # сколько клеток посетил алгоритм
path_length: int # длина найденного пути
algorithm_name: str # какой алгоритм использовался
maze_name: str # название лабиринта
class MazeSolver:
"""
Оркестратор поиска пути.
Использует паттерн Strategy для переключения алгоритмов.
"""
def __init__(self, maze: Maze, strategy: PathFindingStrategy = None):
self.maze = maze
self.strategy = strategy
self._observers = [] # для паттерна Observer (Этап 5)
def set_strategy(self, strategy: PathFindingStrategy):
"""
Динамическая смена алгоритма.
Без паттерна Strategy пришлось бы переписывать этот метод
под каждый новый алгоритм.
"""
self.strategy = strategy
def add_observer(self, observer):
"""Добавление наблюдателя (подготовка к Этапу 5)."""
self._observers.append(observer)
def _notify_observers(self, event: str):
"""Уведомляет всех наблюдателей о событии."""
for observer in self._observers:
observer.update(event)
def solve(self, maze_name: str = "unnamed") -> SearchStats:
"""
Выполняет поиск пути и возвращает статистику.
Args:
maze_name: название лабиринта для отчёта
Returns:
SearchStats с результатами поиска
"""
if not self.strategy:
raise ValueError("Стратегия не установлена! Вызовите set_strategy()")
# Уведомляем наблюдателей
self._notify_observers("search_started")
# Замер времени
start_time = time.perf_counter()
# Запускаем алгоритм (Strategy делает всю работу)
path, visited_count = self.strategy.find_path(
self.maze, self.maze.start, self.maze.exit
)
# Останавливаем замер
end_time = time.perf_counter()
time_ms = (end_time - start_time) * 1000
# Уведомляем о результате
event = "path_found" if path else "no_path"
self._notify_observers(event)
# Формируем статистику
return SearchStats(
time_ms=time_ms,
visited_cells=visited_count,
path_length=len(path),
algorithm_name=self.strategy.get_name(),
maze_name=maze_name
)