2026-05-24 15:00:14 +00:00
|
|
|
|
from abc import ABC, abstractmethod
|
|
|
|
|
|
from dataclasses import dataclass
|
|
|
|
|
|
from typing import Optional
|
|
|
|
|
|
|
|
|
|
|
|
from source.models.base import Maze, Cell
|
|
|
|
|
|
from source.settings import cell_mapping
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ---------------------------------------------------------------------------- #
|
|
|
|
|
|
# События #
|
|
|
|
|
|
# ---------------------------------------------------------------------------- #
|
|
|
|
|
|
|
2026-05-25 07:23:00 +00:00
|
|
|
|
|
2026-05-24 15:00:14 +00:00
|
|
|
|
@dataclass
|
|
|
|
|
|
class Event:
|
|
|
|
|
|
"""Событие, передаваемое наблюдателям.
|
|
|
|
|
|
|
|
|
|
|
|
Attributes:
|
|
|
|
|
|
type: Тип события ('maze_loaded', 'path_found', 'move', 'no_path').
|
|
|
|
|
|
payload: Дополнительные данные события.
|
|
|
|
|
|
"""
|
2026-05-25 07:23:00 +00:00
|
|
|
|
|
2026-05-24 15:00:14 +00:00
|
|
|
|
type: str
|
|
|
|
|
|
payload: dict = None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ---------------------------------------------------------------------------- #
|
|
|
|
|
|
# Интерфейс наблюдателя #
|
|
|
|
|
|
# ---------------------------------------------------------------------------- #
|
|
|
|
|
|
|
2026-05-25 07:23:00 +00:00
|
|
|
|
|
2026-05-24 15:00:14 +00:00
|
|
|
|
class Observer(ABC):
|
|
|
|
|
|
"""Интерфейс наблюдателя за событиями лабиринта."""
|
|
|
|
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
|
|
def update(self, event: Event) -> None:
|
|
|
|
|
|
"""Обрабатывает входящее событие.
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
event: Объект события с типом и данными.
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
# Консольный наблюдатель
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
|
2026-05-25 07:23:00 +00:00
|
|
|
|
|
2026-05-24 15:00:14 +00:00
|
|
|
|
class ConsoleView(Observer):
|
|
|
|
|
|
"""Отображает состояние лабиринта и события в консоли."""
|
|
|
|
|
|
|
|
|
|
|
|
# Символ игрока на карте
|
|
|
|
|
|
PLAYER_SYMBOL = "P"
|
2026-05-25 07:23:00 +00:00
|
|
|
|
PATH_SYMBOL = "·"
|
2026-05-24 15:00:14 +00:00
|
|
|
|
|
|
|
|
|
|
def update(self, event: Event) -> None:
|
|
|
|
|
|
"""Реагирует на события и выводит информацию в консоль.
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
event: Объект события.
|
|
|
|
|
|
"""
|
|
|
|
|
|
match event.type:
|
|
|
|
|
|
case "maze_loaded":
|
|
|
|
|
|
print("Лабиринт загружен.")
|
|
|
|
|
|
self.render(event.payload["maze"])
|
|
|
|
|
|
case "path_found":
|
|
|
|
|
|
print(f"Путь найден! Длина: {event.payload['length']} шагов.")
|
|
|
|
|
|
self.render(
|
|
|
|
|
|
event.payload["maze"],
|
|
|
|
|
|
path=event.payload["path"],
|
|
|
|
|
|
)
|
|
|
|
|
|
case "no_path":
|
|
|
|
|
|
print("Путь не найден.")
|
|
|
|
|
|
case "move":
|
|
|
|
|
|
print(f"Ход: {event.payload['direction']}")
|
|
|
|
|
|
self.render(
|
|
|
|
|
|
event.payload["maze"],
|
|
|
|
|
|
player=event.payload["player_cell"],
|
|
|
|
|
|
path=event.payload.get("path"),
|
|
|
|
|
|
)
|
|
|
|
|
|
case _:
|
|
|
|
|
|
print(f"[событие] {event.type}")
|
|
|
|
|
|
|
|
|
|
|
|
def render(
|
|
|
|
|
|
self,
|
|
|
|
|
|
maze: Maze,
|
|
|
|
|
|
player: Optional[Cell] = None,
|
|
|
|
|
|
path: Optional[list[Cell]] = None,
|
|
|
|
|
|
) -> None:
|
|
|
|
|
|
"""Рисует лабиринт в консоли.
|
|
|
|
|
|
|
|
|
|
|
|
Путь отмечается символом '·', позиция игрока — 'P'.
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
maze: Объект лабиринта.
|
|
|
|
|
|
player: Текущая клетка игрока (опционально).
|
|
|
|
|
|
path: Список клеток найденного пути (опционально).
|
|
|
|
|
|
"""
|
|
|
|
|
|
path_set = set(path) if path else set()
|
|
|
|
|
|
rows, cols = maze.shape
|
|
|
|
|
|
|
|
|
|
|
|
print("+" + "─" * cols + "+")
|
|
|
|
|
|
for y in range(rows):
|
|
|
|
|
|
row_str = "|"
|
|
|
|
|
|
for x in range(cols):
|
|
|
|
|
|
cell = maze[y, x]
|
|
|
|
|
|
if player and cell is player:
|
|
|
|
|
|
row_str += self.PLAYER_SYMBOL
|
|
|
|
|
|
elif cell in path_set:
|
|
|
|
|
|
row_str += self.PATH_SYMBOL
|
|
|
|
|
|
else:
|
|
|
|
|
|
row_str += str(cell)
|
|
|
|
|
|
row_str += "|"
|
|
|
|
|
|
print(row_str)
|
2026-05-25 07:23:00 +00:00
|
|
|
|
print("+" + "─" * cols + "+")
|