from abc import ABC, abstractmethod from itertools import product import sys from task2.mazeObjects.maze import Maze from task2.mazeObjects.cell import Cell class MazeBuilder(ABC): """Интерфейс MazeBuilder с методом buildFromFile(filename)""" @abstractmethod def buildFromFile(self, filename: str): """Создание лабиринта из файла.""" class TextFileMazeBuilder(MazeBuilder): """Читает файл, парсит символы, создаёт объекты Cell, задаёт координаты и флаги, после чего возвращает готовый Maze.""" start = {'x': 0, 'y': 0} end = {'x': 0, 'y': 0} def cellStrategy(self, letter: str) -> Cell: if letter == '#': return Cell(isWall=True) elif letter == ' ': return Cell() elif letter == 'S': return Cell(isStart=True) elif letter == 'E': return Cell(isExit=True) else: sys.stderr.write(f"Неизвестный символ '{letter}' при загрузке из файла\n") return Cell() def updateStartEnd(self, letter: str, x:int, y:int) -> None: if letter == 'S': self.start = {'x': x, 'y': y} elif letter == 'E': self.end = {'x': x, 'y': y} def generate_row_from_txt(self, filename: str) -> list[str]: with open(filename) as file: text = file.read() text = text.strip() if not text: raise ValueError(f"Файл \"{filename}\" пуст") text = text.split('\n') return text def buildFromFile(self, filename: str): rows = self.generate_row_from_txt(filename) height = len(rows) width = len(rows[0]) array = [[Cell() for j in range(width)] for i in range(height)] # Здесь x и y где-то перепутаны, но мне лень это чинить try: for x, y in product(range(width), range(height)): cell = self.cellStrategy(rows[y][x]) self.updateStartEnd(rows[y][x], x, y) cell.x = x cell.y = y array[y][x] = cell except IndexError: raise ValueError(f"Строка {x+1} имеет длину {len(rows[x])}, ожидалось {width}") return Maze(array, self.start, self.end)