Advertisement
Falexom

Untitled

Jan 17th, 2023
1,354
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.82 KB | None | 0 0
  1. from copy import deepcopy
  2. from random import choice, randint
  3. from typing import List, Optional, Tuple, Union
  4.  
  5. import pandas as pd
  6.  
  7.  
  8. class Tools:
  9.     def swap(self, lst):
  10.         lst[0], lst[1] = lst[1], lst[0]
  11.         return lst
  12.  
  13.  
  14. tools = Tools()
  15.  
  16.  
  17. def create_grid(rows: int = 15, cols: int = 15) -> List[List[Union[str, int]]]:
  18.     return [["■"] * cols for _ in range(rows)]
  19.  
  20.  
  21. def remove_wall(
  22.     grid: List[List[Union[str, int]]], coord: Tuple[int, int]
  23. ) -> List[List[Union[str, int]]]:
  24.     """
  25.  
  26.    :param grid:
  27.    :param coord:
  28.    :return:
  29.    """
  30.  
  31.     if grid[coord[0]][coord[1]] != " ":
  32.         grid[coord[0]][coord[1]] = " "
  33.     elif coord[1] + 1 < len(grid[0]) - 1:
  34.         grid[coord[0]][coord[1] + 1] = " "
  35.     elif coord[0] - 1 > 1:
  36.         grid[coord[0] - 1][coord[1]] = " "
  37.     return grid
  38.  
  39.  
  40. def bin_tree_maze(
  41.     rows: int = 15, cols: int = 15, random_exit: bool = True
  42. ) -> List[List[Union[str, int]]]:
  43.     """
  44.  
  45.    :param rows:
  46.    :param cols:
  47.    :param random_exit:
  48.    :return:
  49.    """
  50.  
  51.     grid = create_grid(rows, cols)
  52.     empty_cells = []
  53.     for x, row in enumerate(grid):
  54.         for y, _ in enumerate(row):
  55.             if x % 2 == 1 and y % 2 == 1:
  56.                 grid[x][y] = " "
  57.                 empty_cells.append((x, y))
  58.  
  59.     # 1. выбрать любую клетку
  60.     # 2. выбрать направление: наверх или направо.
  61.     # Если в выбранном направлении следующая клетка лежит за границами поля,
  62.     # выбрать второе возможное направление
  63.     # 3. перейти в следующую клетку, сносим между клетками стену
  64.     # 4. повторять 2-3 до тех пор, пока не будут пройдены все клетки
  65.  
  66.     # генерация входа и выхода
  67.     random_action = [-1, 1]
  68.     for row_cor in range(1, rows - 1, 2):
  69.         for col_cor in range(1, cols - 1, 2):
  70.             action = choice(random_action)
  71.             if action == 1:
  72.                 if row_cor == 1:
  73.                     if col_cor + 1 == cols - 1:
  74.                         continue
  75.                     remove_wall(grid, (row_cor, col_cor + 1))
  76.                 elif col_cor + 1 < cols - 1:
  77.                     remove_wall(grid, (row_cor, col_cor + 1))
  78.                 elif col_cor - 1 <= cols - 1:
  79.                     remove_wall(grid, (row_cor - 1, col_cor))
  80.             else:
  81.                 if row_cor == 1:
  82.                     if col_cor + 1 == cols - 1:
  83.                         continue
  84.                     remove_wall(grid, (row_cor, col_cor + 1))
  85.                 elif row_cor + 1 <= rows - 1:
  86.                     remove_wall(grid, (row_cor - 1, col_cor))
  87.  
  88.     if random_exit:
  89.         x_in, x_out = randint(0, rows - 1), randint(0, rows - 1)
  90.         y_in = randint(0, cols - 1) if x_in in (0, rows - 1) else choice((0, cols - 1))
  91.         y_out = randint(0, cols - 1) if x_out in (0, rows - 1) else choice((0, cols - 1))
  92.     else:
  93.         x_in, y_in = 0, cols - 2
  94.         x_out, y_out = rows - 1, 1
  95.  
  96.     grid[x_in][y_in], grid[x_out][y_out] = "X", "X"
  97.  
  98.     return grid
  99.  
  100.  
  101. def get_exits(grid: List[List[Union[str, int]]]) -> List[Tuple[int, int]]:
  102.     """
  103.  
  104.    :param grid:
  105.    :return:
  106.    """
  107.     root = []
  108.     rows = len(grid) - 1
  109.     columns = len(grid[0]) - 1
  110.     column = 0
  111.     row = 0
  112.  
  113.     while column < columns:
  114.         if grid[0][column] == "X":
  115.             root.append((0, column))
  116.         column += 1
  117.         print("COLUMNS:", column)
  118.     while row < rows:
  119.         if grid[row][0] == "X":
  120.             root.append((row, 0))
  121.         row += 1
  122.  
  123.     if len(root) != 2:
  124.         column = 0
  125.         row = 0
  126.  
  127.         while column < columns:
  128.             if grid[rows][column] == "X":
  129.                 root.append((rows, column))
  130.             column += 1
  131.  
  132.         while row < rows:
  133.             if grid[row][columns] == "X":
  134.                 root.append((row, columns))
  135.             row += 1
  136.  
  137.     if len(root) > 1:
  138.         if root[0][1] > root[1][1]:
  139.             tools.swap(root)
  140.  
  141.         if root[0][0] > root[1][0]:
  142.             tools.swap(root)
  143.  
  144.     return root
  145.  
  146.  
  147. def make_step(grid: List[List[Union[str, int]]], k: int) -> List[List[Union[str, int]]]:
  148.     """
  149.  
  150.    :param grid:
  151.    :param k:
  152.    :return:
  153.    """
  154.  
  155.     moves = [[0, 1], [0, -1], [1, 0], [-1, 0]]
  156.     to_visit = []
  157.  
  158.     foo = 0
  159.     bar = 0
  160.  
  161.     while foo < len(grid):
  162.         while bar < len(grid[0]):
  163.             if grid[foo][bar] == k:
  164.                 to_visit.append((foo, bar, k + 1))
  165.  
  166.     for foo in range(len(to_visit)):
  167.         foo, bar = to_visit[0][0], to_visit[0][1]
  168.         for x, y in moves:
  169.             if 0 <= foo + x < len(grid):
  170.                 if 0 <= bar + y < len(grid[0]):
  171.                     if grid[foo + x][bar + y] == 0:
  172.                         grid[foo + x][bar + y] = to_visit[0][2]
  173.         to_visit.pop(0)
  174.     return grid
  175.  
  176.  
  177. def shortest_path(
  178.     grid: List[List[Union[str, int]]], exit_coord: Tuple[int, int]
  179. ) -> Optional[Union[Tuple[int, int], List[Tuple[int, int]]]]:
  180.     """
  181.  
  182.    :param grid:
  183.    :param exit_coord:
  184.    :return:
  185.    """
  186.     x = exit_coord[0]
  187.     y = exit_coord[1]
  188.     k = grid[x][y]
  189.     moves = [[0, 1], [0, -1], [1, 0], [-1, 0]]
  190.     way = []
  191.     way.append((x, y))
  192.     while k != 1:
  193.         for a, b in moves:
  194.             if 0 <= x + a < len(grid):
  195.                 if 0 <= y + b < len(grid[0]):
  196.                     buf = grid[x + a][y + b]
  197.                     if type(buf) == int:
  198.                         if buf < int(k):
  199.                             x, y = x + a, y + b
  200.                             way.append((x, y))
  201.                             k = grid[x][y]
  202.  
  203.     foo = 0
  204.     bar = 0
  205.  
  206.     while foo < (len(grid) - 1):
  207.         while bar < (len(grid[0])):
  208.             if grid[foo][bar] != "■":
  209.                 grid[foo][bar] = " "
  210.  
  211.     return way
  212.  
  213.  
  214. def encircled_exit(grid: List[List[Union[str, int]]], coord: Tuple[int, int]) -> bool:
  215.     """
  216.  
  217.    :param grid:
  218.    :param coord:
  219.    :return:
  220.    """
  221.  
  222.     flag = 0
  223.  
  224.     if coord == (0, 0) or coord == (len(grid) - 1, len(grid[0]) - 1) or coord == (len(grid) - 1, 0)  \
  225.             or coord == (0, len(grid[0]) - 1):
  226.         flag = 1
  227.     elif coord[0] == 0:
  228.         if grid[1][coord[1]] == " ":
  229.             flag = 0
  230.         else:
  231.             flag = 1
  232.  
  233.     elif coord[1] == 0:
  234.         if grid[coord[0]][1] == " ":
  235.             flag = 0
  236.         else:
  237.             flag = 1
  238.  
  239.     elif coord[0] == len(grid) - 1:
  240.         if grid[len(grid) - 2][coord[1]] == " ":
  241.             flag = 0
  242.         else:
  243.             flag = 1
  244.  
  245.     elif coord[1] == len(grid[0]) - 1:
  246.         if grid[coord[0]][len(grid[0]) - 2] == " ":
  247.             flag = 0
  248.         else:
  249.             flag = 1
  250.  
  251.     return flag
  252.  
  253.  
  254. def solve_maze(
  255.     grid: List[List[Union[str, int]]],
  256. ) -> Tuple[List[List[Union[str, int]]], Optional[Union[Tuple[int, int], List[Tuple[int, int]]]]]:
  257.     """
  258.  
  259.    :param grid:
  260.    :return:
  261.    """
  262.     exits = get_exits(grid)
  263.     if len(exits) < 2:
  264.         return grid, exits[0]
  265.     else:
  266.         for exit in exits:
  267.             if encircled_exit(grid, exit):
  268.                 return None, None
  269.     enter = exits[0]
  270.     exit = exits[1]
  271.     if exit[1] - enter[1] == 1:
  272.         if exit[0] - enter[0] == 0:
  273.             return grid, exits[::-1]
  274.  
  275.     elif exit[1] - enter[1] == 0:
  276.         if exit[0] - enter[0] == 1:
  277.             return grid, exits[::-1]
  278.  
  279.     elif exit[0] - enter[0] == 0:
  280.         if exit[1] - enter[1] == 1:
  281.             return grid, exits[::-1]
  282.  
  283.     elif exit[0] - enter[0] == 1:
  284.         if exit[1] - enter[1] == 0:
  285.             return grid, exits[::-1]
  286.  
  287.     foo = 0
  288.     bar = 0
  289.  
  290.     grid[exits[0][0]][exits[0][1]] = 1
  291.     while foo < len(grid):
  292.         while bar < len(grid[0]):
  293.             if grid[foo][bar] == " ":
  294.                 grid[foo][bar] = 0
  295.             elif grid[foo][bar] == "X":
  296.                 grid[foo][bar] = 0
  297.  
  298.     k = 1
  299.     while grid[exits[1][0]][exits[1][1]] == 0:
  300.         grid = make_step(grid, k)
  301.         k += 1
  302.  
  303.     path = shortest_path(grid, exits[1])
  304.  
  305.     return grid, path
  306.  
  307.  
  308. def add_path_to_grid(
  309.     grid: List[List[Union[str, int]]], path: Optional[Union[Tuple[int, int], List[Tuple[int, int]]]]
  310. ) -> List[List[Union[str, int]]]:
  311.     """
  312.  
  313.    :param grid:
  314.    :param path:
  315.    :return:
  316.    """
  317.  
  318.     if path:
  319.         for i, row in enumerate(grid):
  320.             for j, _ in enumerate(row):
  321.                 if (i, j) in path:
  322.                     grid[i][j] = "X"
  323.     return grid
  324.  
  325.  
  326. if __name__ == "__main__":
  327.     print(pd.DataFrame(bin_tree_maze(15, 15)))
  328.     GRID = bin_tree_maze(15, 15)
  329.     print(pd.DataFrame(GRID))
  330.     _, PATH = solve_maze(GRID)
  331.     MAZE = add_path_to_grid(GRID, PATH)
  332.     print(pd.DataFrame(MAZE))
  333.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement