from abc import ABC, abstractmethod from typing import List, Optional from models import Cell, Maze class Observer(ABC): @abstractmethod def update(self, event: str, data: dict) -> None: pass class ConsoleView(Observer): def render(self, maze: Maze, player_position: Optional[Cell] = None, path: Optional[List[Cell]] = None) -> None: path_set = set(path) if path else set() print("\n+" + "-" * maze.width + "+") for y in range(maze.height): row = [] for x in range(maze.width): cell = maze.get_cell(x, y) if cell is None: row.append('?') elif player_position and cell == player_position: row.append('@') elif cell.is_start: row.append('S') elif cell.is_exit: row.append('E') elif cell in path_set: row.append('*') elif cell.is_wall: row.append('#') else: row.append(' ') print("|" + ''.join(row) + "|") print("+" + "-" * maze.width + "+") def update(self, event: str, data: dict) -> None: if event == "maze_loaded": maze = data.get('maze') print("\n Лабиринт загружен:") self.render(maze) elif event == "search_start": algorithm = data.get('algorithm', 'Unknown') print(f"\n Начинаем поиск алгоритмом: {algorithm}") elif event == "path_found": maze = data.get('maze') path = data.get('path') stats = data.get('stats') self.render(maze, path=path) elif event == "no_path": stats = data.get('stats') print(f"\n {stats}") elif event == "player_moved": maze = data.get('maze') player = data.get('player') if player: self.render(maze, player_position=player.current_cell)