2026-rff_mp/ivantsovma/maze/solver/maze_solver.py

127 lines
4.9 KiB
Python
Raw Normal View History

import time
from dataclasses import dataclass
from typing import List, Optional
@dataclass
#Статистика поиска пути
class SearchStats:
time_ms: float #Время выполнения в миллисекундах
visited_cells: int #Количество посещенных клеток
path_length: int #Длина найденного пути (0 если путь не найден)
path_found: bool #Найден ли путь
def __repr__(self):
status = "Найден" if self.path_found else "Не найден"
return f"Stats({status}, время={self.time_ms:.2f}мс, посещено={self.visited_cells}, длина={self.path_length})"
def to_dict(self):
"""Преобразует статистику в словарь для CSV"""
return {
'time_ms': f"{self.time_ms:.2f}",
'visited_cells': self.visited_cells,
'path_length': self.path_length,
'path_found': self.path_found
}
class MazeSolver:
"""Оркестратор для решения лабиринта"""
#Инициализация решателя лабиринта
def __init__(self, maze, strategy=None):
self.maze = maze
self._strategy = strategy
self._last_path = None
#Динамическая смена стратегии поиска
def set_strategy(self, strategy):
self._strategy = strategy
print(f"Стратегия изменена на: {strategy.name}")
def solve(self) -> SearchStats:
if self._strategy is None:
raise ValueError("Стратегия не установлена! Используйте set_strategy()")
if self.maze.start is None:
raise ValueError("В лабиринте нет стартовой клетки!")
if self.maze.exit is None:
raise ValueError("В лабиринте нет выходной клетки!")
# Замер времени
start_time = time.perf_counter()
# Поиск пути
path = self._strategy.find_path(self.maze, self.maze.start, self.maze.exit)
end_time = time.perf_counter()
time_ms = (end_time - start_time) * 1000
self._last_path = path
return SearchStats(
time_ms=time_ms,
visited_cells=self._strategy.visited_count,
path_length=len(path),
path_found=len(path) > 0
)
def get_path(self) -> Optional[List]:
"""Возвращает последний найденный путь"""
return self._last_path
#Выводит лабиринт с найденным путем
def print_maze_with_path(self):
if not self._last_path:
print("Путь еще не найден. Сначала вызовите solve()")
return
path_set = set(self._last_path)
print(f"\n {' ' * 4}", end="")
for x in range(self.maze.width):
print(f"{x} ", end="")
print()
for y in range(self.maze.height):
print(f" {y}", end="")
for x in range(self.maze.width):
cell = self.maze.get_cell(x, y)
if cell == self.maze.start:
print("S ", end="")
elif cell == self.maze.exit:
print("E ", end="")
elif cell in path_set:
print("", end="")
elif cell.is_wall:
print("# ", end="")
else:
print("· ", end="")
print()
print("\n Условные обозначения:")
print(" # - стена · - проход ● - путь")
print(" S - старт E - выход")
#Сравнивает несколько стратегий на одном лабиринте
def compare_strategies(self, strategies: List) -> dict:
results = {}
print(f"СРАВНЕНИЕ СТРАТЕГИЙ")
print(f"Лабиринт: {self.maze.width}x{self.maze.height}")
for strategy in strategies:
self.set_strategy(strategy)
stats = self.solve()
results[strategy.name] = {
'stats': stats,
'path': self.get_path()
}
# Вывод результатов
status = "OK" if stats.path_found else "BULLSHIT"
print(f"\n {status} {strategy.name}:")
print(f" Время: {stats.time_ms:.2f} мс")
print(f" Посещено клеток: {stats.visited_cells}")
print(f" Длина пути: {stats.path_length}")
return results