#!/usr/bin/env python # coding: utf-8 # In[ ]: import time from typing import List, Optional from dataclasses import dataclass, field from modelsMaze import Maze from modelsCell import Cell from strategiesPathfinding_strategy import PathFindingStrategy from visualizationObserver import Observer @dataclass class SearchStats: """Статистика поиска.""" algorithm_name: str time_ms: float visited_cells: int path_length: int path_found: bool = True class MazeSolver: """ Оркестратор для решения лабиринта. Использует паттерн Strategy для алгоритмов поиска. Поддерживает Observer для уведомлений. """ def __init__(self, maze: Maze, strategy: Optional[PathFindingStrategy] = None): self.maze = maze self._strategy = strategy self._observers: List[Observer] = [] self._last_path: List[Cell] = [] self._last_stats: Optional[SearchStats] = None def set_strategy(self, strategy: PathFindingStrategy) -> None: """Динамическая смена стратегии.""" self._strategy = strategy self._notify(f"Стратегия изменена на {strategy.name}") def attach(self, observer: Observer) -> None: """Подписать наблюдателя.""" self._observers.append(observer) def detach(self, observer: Observer) -> None: """Отписать наблюдателя.""" if observer in self._observers: self._observers.remove(observer) def _notify(self, event: str) -> None: """Уведомить всех наблюдателей.""" for observer in self._observers: observer.update(event) def solve(self) -> List[Cell]: """ Выполнить поиск пути с текущей стратегией. Возвращает путь (список клеток). """ if self._strategy is None: raise ValueError("Стратегия не установлена") if not self.maze.start_cell or not self.maze.exit_cell: raise ValueError("Лабиринт не имеет старта или выхода") self._notify(f"Начинаем поиск пути с использованием {self._strategy.name}...") start_time = time.perf_counter() path = self._strategy.find_path(self.maze, self.maze.start_cell, self.maze.exit_cell) end_time = time.perf_counter() time_ms = (end_time - start_time) * 1000 # Получаем количество посещённых клеток из стратегии visited_cells = getattr(self._strategy, 'last_visited_count', 0) self._last_path = path self._last_stats = SearchStats( algorithm_name=self._strategy.name, time_ms=time_ms, visited_cells=visited_cells, path_length=len(path), path_found=len(path) > 0 ) if path: self._notify(f"Путь найден! Длина: {len(path)}, время: {time_ms:.2f} мс, посещено: {visited_cells}") else: self._notify(f"Путь не найден! Время: {time_ms:.2f} мс, посещено: {visited_cells}") return path @property def last_path(self) -> List[Cell]: return self._last_path @property def last_stats(self) -> Optional[SearchStats]: return self._last_stats