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

86 lines
3.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
)