75 lines
2.7 KiB
Python
75 lines
2.7 KiB
Python
# maze_solver/builders.py
|
||
from abc import ABC, abstractmethod
|
||
from models import Cell, Maze
|
||
|
||
|
||
class MazeBuilder(ABC):
|
||
"""Интерфейс строителя лабиринта."""
|
||
@abstractmethod
|
||
def buildFromFile(self, filename: str) -> Maze:
|
||
"""Строит объект Maze из файла."""
|
||
pass
|
||
|
||
|
||
class TextFileMazeBuilder(MazeBuilder):
|
||
"""Строитель для текстового формата: ■ стена, ' ' проход, S старт, E выход."""
|
||
|
||
# Поддерживаемые символы стен
|
||
WALL_SYMBOLS = {'#', '■', '█', '▓', '▒', '░'}
|
||
|
||
def __init__(self, require_exit: bool = True):
|
||
"""
|
||
Args:
|
||
require_exit: Если False, позволяет создавать лабиринты без выхода
|
||
"""
|
||
self.require_exit = require_exit
|
||
|
||
def buildFromFile(self, filename: str) -> Maze:
|
||
with open(filename, 'r', encoding='utf-8') as f:
|
||
lines = f.readlines()
|
||
|
||
# Убираем символы новой строки и пустые строки в конце файла
|
||
cleaned_lines = [line.rstrip('\n') for line in lines if line.strip() != '']
|
||
|
||
if not cleaned_lines:
|
||
raise ValueError("Файл лабиринта пуст")
|
||
|
||
height = len(cleaned_lines)
|
||
width = len(cleaned_lines[0])
|
||
|
||
grid = []
|
||
start_cell = None
|
||
exit_cell = None
|
||
|
||
for y, line in enumerate(cleaned_lines):
|
||
row = []
|
||
if len(line) != width:
|
||
raise ValueError(
|
||
f"Строка {y} имеет длину {len(line)}, ожидалось {width}. "
|
||
f"Лабиринт должен быть прямоугольным."
|
||
)
|
||
|
||
for x, char in enumerate(line):
|
||
is_wall = char in self.WALL_SYMBOLS
|
||
cell = Cell(x, y, is_wall)
|
||
|
||
if char == 'S':
|
||
cell.isStart = True
|
||
start_cell = cell
|
||
elif char == 'E':
|
||
cell.isExit = True
|
||
exit_cell = cell
|
||
|
||
row.append(cell)
|
||
grid.append(row)
|
||
|
||
if not start_cell:
|
||
raise ValueError("В лабиринте не найдена стартовая позиция (S)")
|
||
|
||
if self.require_exit and not exit_cell:
|
||
raise ValueError("В лабиринте не найдена выходная позиция (E)")
|
||
|
||
maze = Maze(width, height, grid)
|
||
maze.start = start_cell
|
||
maze.exit = exit_cell
|
||
return maze |