2026-rff_mp/MashinDD/lab2/docs/data/maze_solver.py
2026-05-17 16:50:48 +03:00

122 lines
3.7 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 abc import ABC, abstractmethod
class SearchStats:
def __init__(self, time_ms, visited_cells, path_length, path):
self.time_ms = time_ms
self.visited_cells = visited_cells
self.path_length = path_length
self.path = path
def __repr__(self):
return (f"SearchStats(time={self.time_ms:.3f}ms, "
f"visited={self.visited_cells}, "
f"path_len={self.path_length})")
class Observer(ABC):
@abstractmethod
def update(self, event, data=None):
pass
class ConsoleView(Observer):
def update(self, event, data=None):
if event == 'maze_loaded':
print(f"\n[ConsoleView] Лабиринт загружен: "
f"{data['width']}×{data['height']}")
elif event == 'path_found':
stats = data['stats']
strategy_name = data['strategy']
if stats.path_length > 0:
print(f"\n[ConsoleView] [{strategy_name}] Путь найден! "
f"Длина: {stats.path_length}, "
f"Посещено клеток: {stats.visited_cells}, "
f"Время: {stats.time_ms:.3f} мс")
else:
print(f"\n[ConsoleView] [{strategy_name}] Путь не найден. "
f"Посещено клеток: {stats.visited_cells}")
elif event == 'move':
print(f"[ConsoleView] Игрок переместился в "
f"({data['x']}, {data['y']})")
class MazeSolver:
def __init__(self, maze, strategy=None):
self.maze = maze
self.strategy = strategy
self._observers = []
def set_strategy(self, strategy):
self.strategy = strategy
def add_observer(self, observer):
self._observers.append(observer)
def _notify(self, event, data=None):
for obs in self._observers:
obs.update(event, data)
def solve(self):
if self.strategy is None:
raise RuntimeError("Стратегия не задана. Используйте set_strategy().")
start = time.perf_counter()
path = self.strategy.find_path(self.maze, self.maze.start, self.maze.exit)
end = time.perf_counter()
stats = SearchStats(
time_ms=(end - start) * 1000,
visited_cells=getattr(self.strategy, 'visited_count', 0),
path_length=len(path),
path=path
)
self._notify('path_found', {
'stats': stats,
'strategy': type(self.strategy).__name__
})
return stats
class Command(ABC):
@abstractmethod
def execute(self):
pass
@abstractmethod
def undo(self):
pass
class Player:
def __init__(self, start_cell):
self.current_cell = start_cell
def move_to(self, cell):
self.current_cell = cell
class MoveCommand(Command):
def __init__(self, player, target_cell, observers=None):
self.player = player
self.target_cell = target_cell
self.previous_cell = None
self._observers = observers or []
def execute(self):
self.previous_cell = self.player.current_cell
self.player.move_to(self.target_cell)
for obs in self._observers:
obs.update('move', {'x': self.target_cell.x,
'y': self.target_cell.y})
def undo(self):
if self.previous_cell is not None:
self.player.move_to(self.previous_cell)
for obs in self._observers:
obs.update('move', {'x': self.previous_cell.x,
'y': self.previous_cell.y})