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

127 lines
4.9 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
@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