2026-rff_mp/GutovVM/docs/data/lab_2_data/main.py
2026-05-24 22:12:39 +03:00

229 lines
6.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import numpy as np
import abc
from collections import deque
#Классы клетки и лабиринта
class Cell:
def __init__(self, coords, isWall = False, isStart = False,
isExit = False):
self.coords = coords
self.isWall = isWall
self.isStart = isStart
self.isExit = isExit
def isPassable(self):
if self.isWall:
return False
return True
class Maze:
def __init__(self, cells, width, height, st, ex):
self.cells = cells
self.width = width
self.height = height
self.st = st
self.ex = ex
def getCell(self,x,y):
try:
return self.cells[x][y]
except:
return None
def getNeighbors(self,cell):
x,y = cell.coords
res = []
for i,j in (x,y+1),(x,y-1),(x-1,y),(x+1,y):
cellij = self.getCell(i,j)
if i <= self.width-1 and j <= self.height-1 and 0 <= i and 0 <= j and cellij is not None:
if cellij.isPassable():
res.append(cellij)
else:
res.append(None)
else:
res.append(None)
return res
#Тестирование классов клетки и лабиринта
cell1 = Cell((1,2), isExit = True, isWall = True, isStart = False)
print(cell1.isPassable())
print(cell1.isStart)
print(cell1.coords)
width, height = 3,3
cells = np.full((width,height), None, dtype=object)
for x in range(width):
for y in range(height):
if x != 0 and x != width-1 and y != 0 and y != height-1:
cells[x][y] = Cell((x,y), isWall = False)
else:
cells[x][y] = Cell((x,y), isWall = True)
print(cells)
maze1 = Maze(cells, width, height, cells[0], cells[-1])
for column in cells:
for cell in column:
print(cell.coords)
print(maze1.getNeighbors(cell))
print('\n')
#Интерфейс постройки лабиринта
class MazeBuilder(abc.ABC):
@abc.abstractmethod
def buildFromFile(filename): pass
#Наследуем от него класс постройки из текстового файла
class TextFileMazeBuilder(MazeBuilder):
def buildFromFile(filename):
with open(filename, "r") as file:
rows = file.read().splitlines()
print(rows)
width = 0
height = 0
for row in rows:
height += 1
if len(row) > width:
width = len(row)
print(width, height)
st = (0,0)
ex = (width,height)
cells = np.full((width,height), None, dtype=object)
for y in range(height):
for x in range(width):
isWall = False
isStart = False
isExit = False
if rows[-(y+1)][x] == '#':
isWall = True
elif rows[-(y+1)][x] == 'S':
isStart = True
st = (x,y)
print('Старт в',x,y)
elif rows[-(y+1)][x] == 'E':
isExit = True
ex = (x,y)
print('Выход в',x,y)
elif rows[-(y+1)][x] != ' ':
raise ValueError("Неверный формат лабиринта! Пожалуйста, используйте только символы #,S,E и пробелы")
cells[x][y] = Cell((x,y), isWall, isStart, isExit)
return Maze(cells, width, height, cells[st[0]][st[1]], cells[ex[0]][ex[1]])
builder = TextFileMazeBuilder
maze = builder.buildFromFile('maze1.txt')
print(maze)
#Интерфейс поиска пути
class PathFindingStrategy(abc.ABC):
@abc.abstractmethod
def findPath(maze, st, ex): pass
#Поиск в глубину
class DFS(PathFindingStrategy):
def findPath(maze,st,ex):
stack = [st]
visited = {st.coords} #по координатам надёжнее, а то вдруг адрес изменится
pathmap = {}
while stack:
cell = stack.pop()
if cell == ex:
#маршрут выстраивается в обратном порядке и разворачивается
path = []
while cell.coords != st.coords:
path.append(cell)
cell = pathmap[cell.coords]
path.append(st)
path = path[::-1]
return path
for n in maze.getNeighbors(cell):
if n != None and n.coords not in visited:
visited.add(n.coords)
pathmap[n.coords] = cell
stack.append(n)
return None
path = DFS.findPath(maze,maze.st,maze.ex)
print('путь поиском в глубину:')
for cell in path:
print(cell.coords)
class BFS(PathFindingStrategy):
def findPath(maze,st,ex):
queue = deque([st])
visited = {st.coords} #по координатам надёжнее, а то вдруг адрес изменится
pathmap = {}
while queue:
cell = queue.popleft()
if cell == ex:
#маршрут выстраивается в обратном порядке и разворачивается
path = []
while cell.coords != st.coords:
path.append(cell)
cell = pathmap[cell.coords]
path.append(st)
path = path[::-1]
return path
for n in maze.getNeighbors(cell):
if n != None and n.coords not in visited:
visited.add(n.coords)
pathmap[n.coords] = cell
queue.append(n)
return None
path = BFS.findPath(maze,maze.st,maze.ex)
print('путь поиском в ширину:')
for cell in path:
print(cell.coords)