Добавил dfs
- чертовы координаты - изменил положение observer - изменил систему координат, привёл к единому стилю - столбец, строка
This commit is contained in:
parent
32ed692fd8
commit
5fce1bb8a6
|
|
@ -1,80 +0,0 @@
|
|||
from abc import ABC, abstractmethod
|
||||
import os
|
||||
|
||||
from source.classes.cell import Cell
|
||||
|
||||
|
||||
class Event:
|
||||
def __init__(self, event, maze, player_position, path):
|
||||
self.event = event
|
||||
self.maze = maze
|
||||
self.player_position = player_position
|
||||
self.path = path
|
||||
|
||||
|
||||
class Observer(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def update(self, event: Event):
|
||||
pass
|
||||
|
||||
|
||||
class ConsoleView(Observer):
|
||||
|
||||
def update(self, event: Event):
|
||||
if event.event == "path_found":
|
||||
print("Путь найден:")
|
||||
self.render(
|
||||
event.maze,
|
||||
event.player_position,
|
||||
event.path
|
||||
)
|
||||
elif event.event == "move":
|
||||
self.render(
|
||||
event.maze,
|
||||
event.player_position,
|
||||
event.path
|
||||
)
|
||||
elif event.event == "maze_loaded":
|
||||
print("Загружен лабиринт:")
|
||||
self.render(
|
||||
event.maze,
|
||||
event.player_position,
|
||||
event.path
|
||||
)
|
||||
else:
|
||||
pass
|
||||
|
||||
|
||||
def render(self, maze, player_position, path):
|
||||
if path and isinstance(path[0], tuple):
|
||||
self.render_xy(maze=maze, player_position=player_position, path=path)
|
||||
return
|
||||
os.system('cls' if os.name == 'nt' else 'clear')
|
||||
|
||||
path_xy = [cell.getXY() for cell in path]
|
||||
|
||||
for line in maze.cells:
|
||||
for c in line:
|
||||
if c.getXY() == player_position:
|
||||
print('P', end='')
|
||||
elif c.getXY() in path_xy:
|
||||
print('*', end='')
|
||||
else:
|
||||
print(c.toStr(), end='')
|
||||
|
||||
print()
|
||||
|
||||
def render_xy(self, maze, player_position, path: list[tuple[int, int]]):
|
||||
os.system('cls' if os.name == 'nt' else 'clear')
|
||||
# path_xy = [cell.getXY() for cell in path]
|
||||
|
||||
for line in maze.cells:
|
||||
for c in line:
|
||||
if c.getXY() == player_position:
|
||||
print('P', end='')
|
||||
elif c.getXY() in path:
|
||||
print('*', end='')
|
||||
else:
|
||||
print(c.toStr(), end='')
|
||||
print()
|
||||
|
|
@ -25,7 +25,6 @@ class TextFileMazeBuilder(MazeBuilder):
|
|||
|
||||
for line in data:
|
||||
x = 0
|
||||
|
||||
for c in line.strip():
|
||||
if c == 'S':
|
||||
cells[y][x] = Cell(x, y, isStart=True)
|
||||
|
|
@ -59,5 +58,5 @@ class TextFileMazeBuilder(MazeBuilder):
|
|||
width=width,
|
||||
height=height,
|
||||
start=start,
|
||||
exit=c_exit
|
||||
exit_cell=c_exit
|
||||
)
|
||||
|
|
@ -17,7 +17,8 @@ class Cell:
|
|||
"""
|
||||
Создание клетки лабиринта
|
||||
|
||||
`x, y` - координаты клетки в лабиринте
|
||||
`x` - столбец клетки в лабиринте
|
||||
`y` - строка клетки в лабиринте
|
||||
|
||||
`isWall` - Является ли клетка стеной
|
||||
|
||||
|
|
|
|||
|
|
@ -2,16 +2,16 @@ from source.classes.cell import Cell
|
|||
|
||||
class Maze:
|
||||
"""Лабиринт"""
|
||||
def __init__(self, cells, width: int, height: int, start: Cell, exit: Cell):
|
||||
def __init__(self, cells, width: int, height: int, start: Cell, exit_cell: Cell):
|
||||
self.cells = cells
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.start = start
|
||||
self.exit = exit
|
||||
self.exit = exit_cell
|
||||
pass
|
||||
|
||||
def getCell(self, x, y) -> Cell:
|
||||
return self.cells[x][y]
|
||||
def getCell(self, x: int, y: int) -> Cell:
|
||||
return self.cells[y][x] # строка стобец
|
||||
|
||||
def getNeighbors(self, cell) -> list[Cell]:
|
||||
"""Возвращает список соседних проходимых клеток (вверх, вниз, влево, вправо, если в пределах границ и не стена)."""
|
||||
|
|
@ -19,17 +19,17 @@ class Maze:
|
|||
|
||||
c_x, c_y = cell.getXY()
|
||||
|
||||
if c_x - 1 >= 0 and not self.cells[c_x - 1][c_y].isWall:
|
||||
neighbors.append(self.cells[c_x - 1][c_y])
|
||||
if c_y - 1 >= 0 and not self.cells[c_y - 1][c_x].isWall:
|
||||
neighbors.append(self.cells[c_y - 1][c_x])
|
||||
|
||||
if c_x + 1 < self.width and not self.cells[c_x + 1][c_y].isWall:
|
||||
neighbors.append(self.cells[c_x + 1][c_y])
|
||||
if c_y + 1 < self.height and not self.cells[c_y + 1][c_x].isWall:
|
||||
neighbors.append(self.cells[c_y + 1][c_x])
|
||||
|
||||
if c_y - 1 >= 0 and not self.cells[c_x][c_y - 1].isWall:
|
||||
neighbors.append(self.cells[c_x][c_y - 1])
|
||||
if c_x - 1 >= 0 and not self.cells[c_y][c_x - 1].isWall:
|
||||
neighbors.append(self.cells[c_y][c_x - 1])
|
||||
|
||||
if c_y + 1 < self.height and not self.cells[c_x][c_y + 1].isWall:
|
||||
neighbors.append(self.cells[c_x][c_y + 1])
|
||||
if c_x + 1 < self.width and not self.cells[c_y][c_x + 1].isWall:
|
||||
neighbors.append(self.cells[c_y][c_x + 1])
|
||||
|
||||
return neighbors
|
||||
|
||||
|
|
|
|||
80
stepushovgs/labyrinth/source/observer/console_view.py
Normal file
80
stepushovgs/labyrinth/source/observer/console_view.py
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
import os
|
||||
|
||||
|
||||
from source.observer.observer import Observer, Event
|
||||
from source.classes.cell import Cell
|
||||
from source.classes.maze import Maze
|
||||
|
||||
class ConsoleView(Observer):
|
||||
|
||||
def update(self, event: Event):
|
||||
"""Вывод состояния лабиринта на экран
|
||||
|
||||
`maze_loaded` - Лабиринт загружен
|
||||
|
||||
`path_found` - Отображает лабиринт и маршрут в нём (символом `*`)
|
||||
|
||||
`move` - Выводит лабиринт и позицию игрока в нём (символом `P`)
|
||||
|
||||
"""
|
||||
if event.event == "path_found":
|
||||
print("Путь найден:")
|
||||
self.render(
|
||||
event.maze,
|
||||
event.player_position,
|
||||
event.path
|
||||
)
|
||||
elif event.event == "move":
|
||||
self.render(
|
||||
event.maze,
|
||||
event.player_position,
|
||||
event.path
|
||||
)
|
||||
elif event.event == "maze_loaded":
|
||||
print("Загружен лабиринт:")
|
||||
self.render(
|
||||
event.maze,
|
||||
event.player_position,
|
||||
event.path
|
||||
)
|
||||
else:
|
||||
pass
|
||||
|
||||
|
||||
def render(self, maze:Maze, player_position: tuple[int, int], path: list):
|
||||
os.system('cls' if os.name == 'nt' else 'clear')
|
||||
|
||||
# Если path содержит объекты Cell, преобразуем в координаты
|
||||
if path and isinstance(path[0], Cell):
|
||||
path_xy = [cell.getXY() for cell in path]
|
||||
else:
|
||||
path_xy = path
|
||||
|
||||
# path_xy = [cell.getXY() for cell in path]
|
||||
|
||||
for line in maze.cells:
|
||||
for c in line:
|
||||
if c.getXY() == player_position:
|
||||
print('P', end='')
|
||||
elif c.toStr() in ["S", "E"]:
|
||||
print(c.toStr(), end='')
|
||||
elif c.getXY() in path_xy:
|
||||
print('*', end='')
|
||||
else:
|
||||
print(c.toStr(), end='')
|
||||
|
||||
print()
|
||||
|
||||
# def render_xy(self, maze: Maze, player_position: tuple[int, int], path: list[tuple[int, int]]):
|
||||
# os.system('cls' if os.name == 'nt' else 'clear')
|
||||
# # path_xy = [cell.getXY() for cell in path]
|
||||
|
||||
# for line in maze.cells:
|
||||
# for c in line:
|
||||
# if c.getXY() == player_position:
|
||||
# print('P', end='')
|
||||
# elif c.getXY() in path:
|
||||
# print('*', end='')
|
||||
# else:
|
||||
# print(c.toStr(), end='')
|
||||
# print()
|
||||
22
stepushovgs/labyrinth/source/observer/observer.py
Normal file
22
stepushovgs/labyrinth/source/observer/observer.py
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
from abc import ABC, abstractmethod
|
||||
# import os
|
||||
|
||||
# from source.classes.cell import Cell
|
||||
from source.classes.maze import Maze
|
||||
|
||||
|
||||
class Event:
|
||||
def __init__(self, event: str, maze: Maze, player_position: tuple[int, int], path):
|
||||
self.event = event
|
||||
self.maze = maze
|
||||
self.player_position = player_position
|
||||
self.path = path
|
||||
|
||||
|
||||
class Observer(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def update(self, event: Event):
|
||||
pass
|
||||
|
||||
|
||||
|
|
@ -2,7 +2,9 @@ import time
|
|||
|
||||
|
||||
from source.strategy.strategy import PathFindingStrategy
|
||||
from source.observer.observer import Observer, Event
|
||||
from source.classes.cell import Cell
|
||||
from source.classes.maze import Maze
|
||||
|
||||
class MazeSolver:
|
||||
def __init__(self, maze: Maze, strategy: PathFindingStrategy, observer: Observer):
|
||||
|
|
@ -23,6 +25,7 @@ class MazeSolver:
|
|||
|
||||
self.observer.update(Event(
|
||||
event="path_found",
|
||||
maze=self.maze,
|
||||
player_position=self.maze.exit,
|
||||
path=path
|
||||
))
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@
|
|||
}
|
||||
],
|
||||
"source": [
|
||||
"from source.classes.builder import TextFileMazeBuilder\n",
|
||||
"from source.builder.builder import TextFileMazeBuilder\n",
|
||||
"\n",
|
||||
"builder = TextFileMazeBuilder()\n",
|
||||
"maze = builder.buildFromFile(filename='test_lab.txt')\n",
|
||||
|
|
@ -65,7 +65,7 @@
|
|||
"output_type": "stream",
|
||||
"text": [
|
||||
"Загружен лабиринт:\n",
|
||||
"\u001b[H\u001b[2J**P# ###\n",
|
||||
"S*P# ###\n",
|
||||
"## # # E\n",
|
||||
"# # #\n",
|
||||
"### ## #\n",
|
||||
|
|
@ -75,7 +75,8 @@
|
|||
}
|
||||
],
|
||||
"source": [
|
||||
"from source.bububu.observer import ConsoleView, Event\n",
|
||||
"from source.observer.console_view import ConsoleView\n",
|
||||
"from source.observer.observer import Event\n",
|
||||
"\n",
|
||||
"view = ConsoleView()\n",
|
||||
"view.update(Event(\n",
|
||||
|
|
@ -88,21 +89,84 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 4,
|
||||
"id": "19840429",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Старт: (0, 0)\n",
|
||||
"Выход: (7, 1)\n",
|
||||
"Соседи старта: [(1, 0)]\n",
|
||||
"для клекти (0, 0) соседи: [(1, 0)]\n",
|
||||
"для клекти (1, 0) соседи: [(0, 0), (2, 0)]\n",
|
||||
"для клекти (2, 0) соседи: [(2, 1), (1, 0)]\n",
|
||||
"для клекти (2, 1) соседи: [(2, 0), (2, 2)]\n",
|
||||
"для клекти (2, 2) соседи: [(2, 1), (1, 2), (3, 2)]\n",
|
||||
"для клекти (3, 2) соседи: [(3, 3), (2, 2), (4, 2)]\n",
|
||||
"для клекти (4, 2) соседи: [(4, 1), (3, 2)]\n",
|
||||
"для клекти (4, 1) соседи: [(4, 0), (4, 2)]\n",
|
||||
"для клекти (4, 0) соседи: [(4, 1)]\n",
|
||||
"для клекти (3, 3) соседи: [(3, 2), (3, 4)]\n",
|
||||
"для клекти (3, 4) соседи: [(3, 3), (2, 4), (4, 4)]\n",
|
||||
"для клекти (4, 4) соседи: [(3, 4), (5, 4)]\n",
|
||||
"для клекти (5, 4) соседи: [(4, 4), (6, 4)]\n",
|
||||
"для клекти (6, 4) соседи: [(6, 3), (5, 4)]\n",
|
||||
"для клекти (6, 3) соседи: [(6, 2), (6, 4)]\n",
|
||||
"для клекти (6, 2) соседи: [(6, 1), (6, 3)]\n",
|
||||
"для клекти (6, 1) соседи: [(6, 2), (7, 1)]\n",
|
||||
"Путь найден:\n",
|
||||
"S**# ###\n",
|
||||
"##*# #*E\n",
|
||||
"# ** #*#\n",
|
||||
"###*##*#\n",
|
||||
"# ****#\n",
|
||||
"########\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"([(2, 1), (1, 0)],\n",
|
||||
" [(0, 0),\n",
|
||||
" (1, 0),\n",
|
||||
" (2, 0),\n",
|
||||
" (2, 1),\n",
|
||||
" (2, 2),\n",
|
||||
" (3, 2),\n",
|
||||
" (3, 3),\n",
|
||||
" (3, 4),\n",
|
||||
" (4, 4),\n",
|
||||
" (5, 4),\n",
|
||||
" (6, 4),\n",
|
||||
" (6, 3),\n",
|
||||
" (6, 2),\n",
|
||||
" (6, 1),\n",
|
||||
" (7, 1)])"
|
||||
]
|
||||
},
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from source.strategy.DFS import DFS\n",
|
||||
"from source.strategy.maze_solver import MazeSolver\n",
|
||||
"from source.classes.cell import Cell\n",
|
||||
"\n",
|
||||
"strat = MazeSolver(maze, DFS())\n",
|
||||
"\n"
|
||||
"\n",
|
||||
"solver = MazeSolver(maze, DFS(), ConsoleView())\n",
|
||||
"stats = solver.solve()\n",
|
||||
"\n",
|
||||
"[cord.getXY() for cord in maze.getNeighbors(cell=Cell(2, 0))], [cord.getXY() for cord in stats.path]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"execution_count": 5,
|
||||
"id": "857c5c04",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
|
|
@ -113,8 +177,9 @@
|
|||
"0\n",
|
||||
"2\n",
|
||||
"1\n",
|
||||
"4\n",
|
||||
"3\n",
|
||||
"4\n"
|
||||
"3\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -123,7 +188,7 @@
|
|||
"{'0', '1', '2', '3', '4'}"
|
||||
]
|
||||
},
|
||||
"execution_count": 4,
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
|
@ -149,6 +214,125 @@
|
|||
"\n",
|
||||
"dfs(graph, '0')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"id": "9a5ea5cb",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Размер: 8x6\n",
|
||||
"(0,0): wall=False, start=True, exit=False\n",
|
||||
"(1,0): wall=False, start=False, exit=False\n",
|
||||
"(2,0): wall=False, start=False, exit=False\n",
|
||||
"(3,0): wall=True, start=False, exit=False\n",
|
||||
"(4,0): wall=False, start=False, exit=False\n",
|
||||
"(5,0): wall=True, start=False, exit=False\n",
|
||||
"(6,0): wall=True, start=False, exit=False\n",
|
||||
"(7,0): wall=True, start=False, exit=False\n",
|
||||
"(0,1): wall=True, start=False, exit=False\n",
|
||||
"(1,1): wall=True, start=False, exit=False\n",
|
||||
"(2,1): wall=False, start=False, exit=False\n",
|
||||
"(3,1): wall=True, start=False, exit=False\n",
|
||||
"(4,1): wall=False, start=False, exit=False\n",
|
||||
"(5,1): wall=True, start=False, exit=False\n",
|
||||
"(6,1): wall=False, start=False, exit=False\n",
|
||||
"(7,1): wall=False, start=False, exit=True\n",
|
||||
"(0,2): wall=True, start=False, exit=False\n",
|
||||
"(1,2): wall=False, start=False, exit=False\n",
|
||||
"(2,2): wall=False, start=False, exit=False\n",
|
||||
"(3,2): wall=False, start=False, exit=False\n",
|
||||
"(4,2): wall=False, start=False, exit=False\n",
|
||||
"(5,2): wall=True, start=False, exit=False\n",
|
||||
"(6,2): wall=False, start=False, exit=False\n",
|
||||
"(7,2): wall=True, start=False, exit=False\n",
|
||||
"(0,3): wall=True, start=False, exit=False\n",
|
||||
"(1,3): wall=True, start=False, exit=False\n",
|
||||
"(2,3): wall=True, start=False, exit=False\n",
|
||||
"(3,3): wall=False, start=False, exit=False\n",
|
||||
"(4,3): wall=True, start=False, exit=False\n",
|
||||
"(5,3): wall=True, start=False, exit=False\n",
|
||||
"(6,3): wall=False, start=False, exit=False\n",
|
||||
"(7,3): wall=True, start=False, exit=False\n",
|
||||
"(0,4): wall=True, start=False, exit=False\n",
|
||||
"(1,4): wall=False, start=False, exit=False\n",
|
||||
"(2,4): wall=False, start=False, exit=False\n",
|
||||
"(3,4): wall=False, start=False, exit=False\n",
|
||||
"(4,4): wall=False, start=False, exit=False\n",
|
||||
"(5,4): wall=False, start=False, exit=False\n",
|
||||
"(6,4): wall=False, start=False, exit=False\n",
|
||||
"(7,4): wall=True, start=False, exit=False\n",
|
||||
"(0,5): wall=True, start=False, exit=False\n",
|
||||
"(1,5): wall=True, start=False, exit=False\n",
|
||||
"(2,5): wall=True, start=False, exit=False\n",
|
||||
"(3,5): wall=True, start=False, exit=False\n",
|
||||
"(4,5): wall=True, start=False, exit=False\n",
|
||||
"(5,5): wall=True, start=False, exit=False\n",
|
||||
"(6,5): wall=True, start=False, exit=False\n",
|
||||
"(7,5): wall=True, start=False, exit=False\n",
|
||||
"\n",
|
||||
"Клетка (2,0) из лабиринта: wall=True\n",
|
||||
"Соседи (2,0): [(1, 2)]\n",
|
||||
"Соседи (1,0): [(0, 0)]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# Проверьте структуру лабиринта\n",
|
||||
"print(f\"Размер: {maze.width}x{maze.height}\")\n",
|
||||
"\n",
|
||||
"# Проверьте конкретные клетки\n",
|
||||
"for y in range(maze.height):\n",
|
||||
" for x in range(maze.width):\n",
|
||||
" cell = maze.cells[y][x]\n",
|
||||
" print(f\"({x},{y}): wall={cell.isWall}, start={cell.isStart}, exit={cell.isExit}\")\n",
|
||||
"\n",
|
||||
"# Проверьте соседей конкретной клетки из лабиринта\n",
|
||||
"cell_from_maze = maze.cells[2][0] # Берём реальную клетку из лабиринта\n",
|
||||
"print(f\"\\nКлетка (2,0) из лабиринта: wall={cell_from_maze.isWall}\")\n",
|
||||
"print(f\"Соседи (2,0): {[n.getXY() for n in maze.getNeighbors(cell_from_maze)]}\")\n",
|
||||
"\n",
|
||||
"# Проверьте соседей (1,0)\n",
|
||||
"cell_1_0 = maze.cells[1][0]\n",
|
||||
"print(f\"Соседи (1,0): {[n.getXY() for n in maze.getNeighbors(cell_1_0)]}\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"id": "32edf4d1",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"['S # ###', '## # # E', '# # #', '### ## #', '# #', '########']\n",
|
||||
"8 6\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"with open('test_lab.txt') as f:\n",
|
||||
" data = f.read().splitlines()\n",
|
||||
" x, y = 0, 0\n",
|
||||
" width = len(data[0])\n",
|
||||
" height = len(data)\n",
|
||||
" print(data)\n",
|
||||
" print(width, height)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "48d20564",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
|
|
@ -167,7 +351,7 @@
|
|||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.14.4"
|
||||
"version": "3.10.6"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user