# builder.py from abc import ABC, abstractmethod from maze import Maze, Cell class MazeBuilder(ABC): @abstractmethod def build_from_file(self, filename: str, require_exit: bool = True) -> Maze: pass class TextFileMazeBuilder(MazeBuilder): def build_from_file(self, filename: str, require_exit: bool = True) -> Maze: with open(filename, 'r', encoding='utf-8') as f: lines = [line.rstrip('\n') for line in f] if not lines: raise ValueError("Файл пуст") height = len(lines) width = max(len(line) for line in lines) maze = Maze(width, height) for y, line in enumerate(lines): for x, ch in enumerate(line): if x >= width: continue cell = maze.get_cell(x, y) if ch == '#': cell.is_wall = True elif ch == 'S': cell.is_start = True maze.start = cell elif ch == 'E': cell.is_exit = True maze.exit = cell if maze.start is None: raise ValueError("Лабиринт должен содержать S (старт)") if require_exit and maze.exit is None: raise ValueError("Лабиринт должен содержать E (выход)") return maze