2026-rff_mp/MininaVD/docs2/data2/solverMaze_solver.py

103 lines
3.5 KiB
Python
Raw Normal View History

#!/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