80 lines
2.7 KiB
Python
80 lines
2.7 KiB
Python
"""
|
||
Этап 5.1: Паттерн Observer — уведомления об изменении состояния.
|
||
|
||
Зачем Observer?
|
||
MazeSolver не знает, кто хочет получать уведомления о событиях.
|
||
Он просто оповещает всех подписчиков. ConsoleView можно заменить
|
||
на GUI-вью или логгер без изменения MazeSolver.
|
||
"""
|
||
|
||
from abc import ABC, abstractmethod
|
||
from maze_model import Maze, Cell
|
||
|
||
|
||
class Observer(ABC):
|
||
"""Интерфейс наблюдателя."""
|
||
|
||
@abstractmethod
|
||
def update(self, event: dict) -> None:
|
||
"""
|
||
event — словарь с ключом "type":
|
||
"maze_loaded" — лабиринт загружен
|
||
"path_found" — путь найден
|
||
"no_path" — путь не найден
|
||
"""
|
||
...
|
||
|
||
|
||
class ConsoleView(Observer):
|
||
"""
|
||
Наблюдатель: выводит лабиринт и путь в консоль.
|
||
|
||
Символы:
|
||
# — стена
|
||
. — проход
|
||
S — старт
|
||
E — выход
|
||
* — найденный путь
|
||
@ — текущее положение игрока
|
||
"""
|
||
|
||
def update(self, event: dict) -> None:
|
||
event_type = event.get("type")
|
||
|
||
if event_type == "maze_loaded":
|
||
print("\n[ConsoleView] Лабиринт загружен:")
|
||
self.render(event["maze"])
|
||
|
||
elif event_type == "path_found":
|
||
print("\n[ConsoleView] Путь найден!")
|
||
self.render(event["maze"], path=event.get("path"), player=event.get("player"))
|
||
|
||
elif event_type == "no_path":
|
||
print("\n[ConsoleView] Путь не найден.")
|
||
|
||
elif event_type == "move":
|
||
print(f"\n[ConsoleView] Игрок переместился в ({event['x']}, {event['y']})")
|
||
self.render(event["maze"], path=event.get("path"), player=event.get("player"))
|
||
|
||
def render(self, maze: Maze, path: list[Cell] | None = None,
|
||
player: Cell | None = None) -> None:
|
||
path_set = set(path) if path else set()
|
||
|
||
for y in range(maze.height):
|
||
row_str = ""
|
||
for x in range(maze.width):
|
||
cell = maze.get_cell(x, y)
|
||
if player and cell == player:
|
||
row_str += "@"
|
||
elif cell.is_start:
|
||
row_str += "S"
|
||
elif cell.is_exit:
|
||
row_str += "E"
|
||
elif cell in path_set:
|
||
row_str += "*"
|
||
elif cell.is_wall:
|
||
row_str += "#"
|
||
else:
|
||
row_str += "."
|
||
print(row_str)
|