from abc import ABC, abstractmethod from maze_model import Cell, Maze class MazeBuilder(ABC): @abstractmethod def build_from_file(self, filename: str) -> Maze: ... class TextFileMazeBuilder(MazeBuilder): def build_from_file(self, filename: str) -> Maze: with open(filename, "r", encoding="utf-8") as f: lines = f.read().splitlines() if not lines: raise ValueError("Файл лабиринта пуст.") height = len(lines) width = max(len(line) for line in lines) lines = [line.ljust(width, "#") for line in lines] cells: list[list[Cell]] = [] start: Cell | None = None exit_cell: Cell | None = None for y, line in enumerate(lines): row = [] for x, ch in enumerate(line): is_wall = ch == "#" is_start = ch == "S" is_exit = ch == "E" cell = Cell(x, y, is_wall=is_wall, is_start=is_start, is_exit=is_exit) if is_start: start = cell if is_exit: exit_cell = cell row.append(cell) cells.append(row) if start is None: raise ValueError("Лабиринт не содержит стартовой клетки (S).") if exit_cell is None: raise ValueError("Лабиринт не содержит выхода (E).") return Maze(width, height, cells, start, exit_cell)