from typing import Optional class Cell: """Класс отвечает за хранение характеристик поля лабиринта""" def __init__( self, x: int, y: int, is_wall: bool = False, is_start: bool = False, is_exit: bool = False, ): """ :param x: Координата поля по оси X :type x: int :param y: Координата поля по оси Y :type y: int :param is_wall: Является ли поле **стеной**, defaults to False :type is_wall: bool, optional :param is_start: Является ли поле **началом**, defaults to False :type is_start: bool, optional :param is_exit: Является ли поле **концом**, defaults to False :type is_exit: bool, optional """ self.x = x self.y = y self._is_wall = is_wall self._is_start = is_start self._is_exit = is_exit def isPossible(self) -> bool: """Проверка возможности перемещения в это поле :return: Если перемещение возможно, то `True`, иначе `False` :rtype: bool """ return not self.is_wall @property def is_wall(self): return self._is_wall @property def is_start(self): return self._is_start @property def is_exit(self): return self._is_exit def _clear_flags(self) -> None: """Обнуляет все флаги поля""" self._is_start = False self._is_exit = False self._is_wall = False @is_wall.setter def is_wall(self, value: bool) -> None: self._clear_flags() self._is_wall = True @is_start.setter def is_start(self, value: bool) -> None: self._clear_flags() self._is_start = True @is_exit.setter def is_exit(self, value: bool) -> None: self._clear_flags() self._is_exit = True def __str__(self) -> str: if self._is_wall: type_cell = "Стена" elif self._is_start: type_cell = "Начало" elif self._is_exit: type_cell = "Выход" else: type_cell = "Пусто" return f"Cell: (x={self.x}, y={self.y}), '{type_cell}'" class Maze: def __init__( self, size: tuple[int, int] = (10, 10) ): # Установка размеров лабиринта self._width = size[0] self._height = size[1] # Создание двумерного списка лабиринта self._map = [ [Cell(x, y) for x in range(self._width)] for y in range(self._height) ] def _check_point_in_map(self, x: int, y: int) -> bool: """Проверка нахождения точки в границах поля Args: x (int): Координата точки в оси X y (int): Координата точки в оси Y Returns: bool: True если поля в поле, иначе False """ return (0 <= x < self._width) and (0 <= y < self._height) def get_cell(self, x: int, y: int) -> Optional[Cell]: """Получение значения поля по координате в лабиринте Args: x (int): Координата точки в оси X y (int): Координата точки в оси Y Returns: Optional[Cell]: Объект поля, при его наличии """ if not self._check_point_in_map(x, y): return None return self._map[y][x] def get_neighbors(self, x: int, y: int) -> Optional[list[Cell]]: """Получение соседних полей относительно заданного поля Под соседями поля в лабиринте имеется виду клетки сверху, справа, снизу и слева относительно её. Если точка находится за границами, то будет возвращено `None` Args: x (int): Координата точки в оси X y (int): Координата точки в оси Y Returns: Optional[list[Cell]]: Список соседних полей """ if not self._check_point_in_map(x, y): return None list() vector_x = [0, 1, 0, -1] vector_y = [1, 0, -1, 0] neighbors = [] for vec_x, vec_y in zip(vector_x, vector_y): temp_x, temp_y = x + vec_x, y + vec_y value = self.get_cell(temp_x, temp_y) if value is not None: neighbors.append(value) return neighbors