import sys from collections import deque import heapq import time import os class Cell: def __init__(self, x, y): self._x = x self._y = y self._is_wall = False self._is_start = False self._is_exit = False @property def x(self): return self._x @property def y(self): return self._y @property def is_wall(self): return self._is_wall @is_wall.setter def is_wall(self, value): self._is_wall = value @property def is_start(self): return self._is_start @is_start.setter def is_start(self, value): self._is_start = value @property def is_exit(self): return self._is_exit @is_exit.setter def is_exit(self, value): self._is_exit = value def is_passable(self): return not self._is_wall class Maze: def __init__(self, width, height): self._width = width self._height = height self._cells = [[Cell(x, y) for x in range(width)] for y in range(height)] self._start = None self._exit = None @property def width(self): return self._width @property def height(self): return self._height @property def start(self): return self._start @property def exit(self): return self._exit def get_cell(self, x, y): if 0 <= x < self._width and 0 <= y < self._height: return self._cells[y][x] return None def set_cell(self, x, y, cell_type): cell = self.get_cell(x, y) if cell is None: return if cell_type == 'wall': cell.is_wall = True elif cell_type == 'start': if self._start: self._start.is_start = False cell.is_start = True cell.is_wall = False self._start = cell elif cell_type == 'exit': if self._exit: self._exit.is_exit = False cell.is_exit = True cell.is_wall = False self._exit = cell elif cell_type == 'path': cell.is_wall = False def get_neighbors(self, cell): neighbors = [] directions = [(0, -1), (0, 1), (-1, 0), (1, 0)] for dx, dy in directions: nx, ny = cell.x + dx, cell.y + dy neighbor = self.get_cell(nx, ny) if neighbor and neighbor.is_passable(): neighbors.append(neighbor) return neighbors class MazeBuilder: def build_from_file(self, filename): raise NotImplementedError("Need to realise in calss") class TextFileMazeBuilder(MazeBuilder): def build_from_file(self, filename): with open(filename, 'r') as f: lines = [line.rstrip('\n') for line in f.readlines()] height = len(lines) width = max(len(line) for line in lines) if height > 0 else 0 start_en = 0 exit_en = 0 maze = Maze(width, height) for y, line in enumerate(lines): for x, ch in enumerate(line): if ch == "#": maze.set_cell(x, y, "wall") elif ch == "S": maze.set_cell(x, y, "start") start_en += 1 elif ch == "E": maze.set_cell(x, y, "exit") exit_en += 1 else: maze.set_cell(x, y, 'path') if start_en != 1 or exit_en != 1: raise ValueError(f"Labirint must have one S and one E. Found: S={start_en}, E={exit_en}") return maze