Compare commits

..

6 Commits

Author SHA1 Message Date
49fa517565 [2] lab_2 finished and merged 2026-05-28 18:03:51 +03:00
19f9b5403c lab_2 graphics, doc finished 2026-05-28 17:54:18 +03:00
bbd059e8b2 main full ver, graphics unfinished 2026-05-27 01:45:20 +03:00
2360b42a88 solver, observer and movement 2026-05-26 22:18:10 +03:00
7e723606cb lab_2 Astar 2026-05-25 01:11:16 +03:00
3d7c072106 lab_2 builder, BFS, DFS 2026-05-24 22:12:39 +03:00
18 changed files with 1052 additions and 0 deletions

View File

@ -0,0 +1,10 @@
##########
#S# #
# # #### #
# # # #
### # ## #
# # #
# ##### ##
# # #
##### ##E#
##########

View File

@ -0,0 +1,51 @@
###################################################
#S# # # # #
# # ##### # ######### # ##### # ################# #
# # # # # # # # # #
##### # ########### # ### # ############# ####### #
# # # # # # # # #
# ##### # ############# # # # ############# ##### #
# # # # # # # # # # #
# # ##### # ############# # # # ######### ##### # #
# # # # # # # # # # # # #
# # # ##### # ######### # # ##### ##### ##### # # #
# # # # # # # # # # # # #
# # ######### # ##### ########### # # # # ##### # #
# # # # # # # # # # #
# ############# ### # # ########### ##### # ##### #
# # # # # # #
############### # ### ########### ############### #
# # # # # # #
# ############# ### # # ##### # ######### # ##### #
# # # # # # # # # # # # # #
# # ############# ### # # # # # ####### # # # # # #
# # # # # # # # # # # #
# # ############### # ####### ####### # # ####### #
# # # # # # # # # #
# # # ############# ####### ####### # # ####### # #
# # # # # # # # # # # #
# # # # ######### ####### # # ##### # ####### # # #
# # # # # # # # # # # # # #
##### # # ##### ####### # ##### # # # # ### # #####
# # # # # # # # # # # # #
# ##### ##### # # ############# # # # ### # ##### #
# # # # # # # # # # # # #
##### ##### # # # # ############# # ### # ##### # #
# # # # # # # # # # # # #
# # ##### # # # # ################### # ### # ### #
# # # # # # # # # # # # # #
# ##### # # # # # # ############### # ### # ### # #
# # # # # # # # # # # # #
##### # ######### ############### # ### # # ### # #
# # # # # # # # #
# ############# ##################### ####### # # #
# # # # #
############# ######################### ###########
# # # #
# ########### # ####################### # ####### #
# # # # # # #
########### # # # ####################### ####### #
# # # # #
# ########### ################################### #
# E#
###################################################

View File

@ -0,0 +1,97 @@
#####################################################################################################
#S# # # # # #
# # ##### # ################# # ######### # ################# # ################################### #
# # # # # # # # # # # # # #
##### # ############# ####### # # ##### # # # ############# # # # ################################# #
# # # # # # # # # # # # # # # # #
# ##### # ############# ####### # # # # # # # # ############# # # # ############################### #
# # # # # # # # # # # # # # # # # #
# # ##### # ######### ########### # # # # # # ############### # # # # ############################# #
# # # # # # # # # # # # # # # #
# # # ##### # ##### ############### ##### ################# # # # # # ############################# #
# # # # # # # # # # #
# # ############# ######################### ############### # ##### # ############################# #
# # # # # # # # #
# ############### # ####################### # ############# # # ##### # ########################### #
# # # # # # # # # # # #
############### # # # ##################### # # ############# # # ##### # ######################### #
# # # # # # # # # # # # # #
# ############# # # # # ################### # # # ############# # # ##### # ####################### #
# # # # # # # # # # # # # # # # #
# # ############# # # # # ################# # # # # ############# # ##### # # ##################### #
# # # # # # # # # # # # # # # # # #
# # # ############# # # # # ############### # # # ############### # ##### # # # ################### #
# # # # # # # # # # # # # # # #
# # # # ############# ##################### # # ######################### # # # # ################# #
# # # # # # # # # # # # #
# # # # # ################################# # ########################### # # # # # ############### #
# # # # # # # # # # #
# # # ####### ############################### ############################# ####### ############### #
# # # # # # # #
# # ######### # ############################# # ########################### ####### # ############# #
# # # # # # # # # #
# ########### # # ########################### # # ######################### ####### # ############# #
# # # # # # # # # #
############# # # # ######################### # ########################### # ##### # ############# #
# # # # # # # # # # #
# ########### # # # # ####################### ############################# # # ##### # #############
# # # # # # # # # # # # #
# # ######### # # # # # ##################### # ########################### # # # ##### ########### #
# # # # # # # # # # # # # # # # #
# # # ####### # # # # # # ################### # # ######################### # # # # ##### ######### #
# # # # # # # # # # # # # # # # # # #
# # # # ##### # ##### # # # ################# # ########################### # # # # # ##### ####### #
# # # # # # # # # # # # # # # # # # #
# ##### # # # # # ##### # # # ############### ############################# ####### # # ##### ##### #
# # # # # # # # # # # # # # # # # # #
# # ##### # # # # # ##### # # # ############################################# ####### # # # # # ### #
# # # # # # # # # # # # # # # #
# ######### ####### ########### # ############################################# ####### ### # ### # #
# # # # # # # # # # #
########### # ####### ########### # ########################################### ######### # ### # # #
# # # # # # # # # # # #
# ########### # ##### # ########### # ######################################### # ######### ### # # #
# # # # # # # # # # # # # # # #
# # ######### # # # # # # ######### # ######################################### # # ##### ### # # # #
# # # # # # # # # # # # # # # # # # # # #
# # # ####### # # # # # # # ####### # ######################################### # # # # ### # # # # #
# # # # # # # # # # # # # # # # # # #
# ##### ####### ######### # # ##### ########################################### # # # ### # ### # # #
# # # # # # # # # # # # # # #
####### # ############### # # ##### # ######################################### # # ### # ### # # # #
# # # # # # # # # # # # # # # #
# ####### # ############# # ### # ### # ######################################### ### # ### # ### # #
# # # # # # # # # # # # # # # # #
# # ##### # ############### ### # # ### # ######################################### # # ### # ### # #
# # # # # # # # # # # # # # # # #
# # # # ##### ############### # # ##### # # ####################################### # # ### # ### # #
# # # # # # # # # # # # # # # # #
# # # ######### ############# # # # ##### # # ##################################### ##### # ### # # #
# # # # # # # # # # # # # # #
# # ############# ############### # # ##### # # ################################### # ##### ### # # #
# # # # # # # # # # # # # #
# ############### # ############# # # # ##### # # ################################# # # ##### ##### #
# # # # # # # # # # # # # # #
# ################# # ########### # # # # ##### # # ############################### # # # ##### ### #
# # # # # # # # # # # # # # # # #
# # ############### # # ######### # ##### # ##### # # ############################# # # # # ##### # #
# # # # # # # # # # # # # # # # # #
# # # ############# # # # ####### ######### # ##### # # ########################### ####### # ##### #
# # # # # # # # # # # # # # # # # #
# # # # ############# # # # ##### # ####### # # ##### # # ######################### # ####### # #####
# # # # # # # # # # # # # # # # # # # # # # #
# # # # # ########### # # # # # # # # ##### # # # ##### # # ####################### # # ##### # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # ##### # ######### # ##### # # # # # # # # # # # ##### # # ##################### # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # #
# ######### # ######### ############### ######### # ##### # # ##################### ##### # ##### # #
# # # # # # # # # # # # # # # #
########### # ######### # ##################### # # # ##### # # ################### # ##### # # # # #
# # # # # # # # # # # # # # # # # #
# ####################### # ################### # # # # ##### # # ################# # # ##### # # # #
# # # # # # # # # # # # # # # # #
# # ##################### # # ################# ##### # # ##### # # ############### # # # ##### ### #
# # # # # # # # # # # # # # # # # # #
# # # ################### # # # ############### # ##### # # ##### # # ############# # # # # ##### # #
# # # # # # # # # # # # # # # # E
#####################################################################################################

View File

@ -0,0 +1,50 @@
S
E

View File

@ -0,0 +1,51 @@
###################################################
#S# # # # #
# # ##### # ######### # ##### # ################# #
# # # # # # # # # #
##### # ########### # ### # ############# ####### #
# # # # # # # # #
# ##### # ############# # # # ############# ##### #
# # # # # # # # # # #
# # ##### # ############# # # # ######### ##### # #
# # # # # # # # # # # # #
# # # ##### # ######### # # ##### ##### ##### # # #
# # # # # # # # # # # # #
# # ######### # ##### ########### # # # # ##### # #
# # # # # # # # # # #
# ############# ### # # ########### ##### # ##### #
# # # # # # #
############### # ### ########### ############### #
# # # # # # #
# ############# ### # # ##### # ######### # ##### #
# # # # # # # # # # # # # #
# # ############# ### # # # # # ####### # # # # # #
# # # # # # # # # # # #
# # ############### # ####### ####### # # ####### #
# # # # # # # # # #
# # # ############# ####### ####### # # ####### # #
# # # # # # # # # # # #
# # # # ######### ####### # # ##### # ####### # # #
# # # # # # # # # # # # # #
##### # # ##### ####### # ##### # # # # ### # #####
# # # # # # # # # # # # #
# ##### ##### # # ############# # # # ### # ##### #
# # # # # # # # # # # # #
##### ##### # # # # ############# # ### # ##### # #
# # # # # # # # # # # # #
# # ##### # # # # ################### # ### # ### #
# # # # # # # # # # # # # #
# ##### # # # # # # ############### # ### # ### # #
# # # # # # # # # # # # #
##### # ######### ############### # ### # # ### # #
# # # # # # # # #
# ############# ##################### ####### # # #
# # # # #
############# ######################### ###########
# # # #
# ########### # ####################### # ####### #
# # # # # # #
########### # # # ####################### ####### #
# # # # ### #
# ########### ########################### #E# #
# ### #
###################################################

View File

@ -0,0 +1,29 @@
#Графики
import matplotlib.pyplot as plt
import pandas as pd
df = pd.read_csv('results.csv', header=None, names=['lab','strategy','timeMs','cellsVisited','pathLength'])
print(df)
df_time = df.pivot(index='lab', columns='strategy', values=['timeMs','cellsVisited','pathLength'])
print(df_time)
# 1. График только для Времени
df_time["timeMs"].plot(kind="bar", figsize=(10, 5), rot=0)
plt.title("Время работы стратегий (мс)")
plt.ylabel("timeMs")
plt.show()
# 2. График для Посещенных клеток
df_time["cellsVisited"].plot(kind="bar", figsize=(10, 5), rot=0)
plt.title("Количество посещенных клеток")
plt.ylabel("cellsVisited")
plt.show()
# 3. График для Длины пути
df_time["pathLength"].plot(kind="bar", figsize=(10, 5), rot=0)
plt.title("Длина найденного пути")
plt.ylabel("pathLength")
plt.show()

View File

@ -0,0 +1,596 @@
import numpy as np
import abc
from collections import deque
import heapq
import time
import os
import keyboard
import csv
#Классы клетки и лабиринта
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)
flagst = False
flagex = False
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)
flagst = True
#print('Старт в',x,y)
elif rows[-(y+1)][x] == 'E':
isExit = True
ex = (x,y)
flagex = True
#print('Выход в',x,y)
elif rows[-(y+1)][x] != ' ':
raise ValueError("Неверный формат лабиринта! Пожалуйста, используйте только символы #,S,E и пробелы")
cells[x][y] = Cell((x,y), isWall, isStart, isExit)
if flagst and flagex:
return Maze(cells, width, height, cells[st[0]][st[1]], cells[ex[0]][ex[1]])
raise ValueError('В лабаиринте должны быть вход и выход (S и E)')
# builder = TextFileMazeBuilder
# maze = builder.buildFromFile('maze1.txt')
# print(maze)
#Интерфейс поиска пути
class PathFindingStrategy(abc.ABC):
@abc.abstractmethod
def findPath(self, maze, st, ex): pass
#Поиск в глубину
class DFS(PathFindingStrategy):
def findPath(self,maze,st,ex):
stack = [st]
self.visited = {st.coords} #по координатам надёжнее, а то вдруг адрес изменится
pathmap = {}
while stack:
cell = stack.pop()
if cell.coords == ex.coords:
#маршрут выстраивается в обратном порядке и разворачивается
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 self.visited:
self.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(self,maze,st,ex):
queue = deque([st])
self.visited = {st.coords} #по координатам надёжнее, а то вдруг адрес изменится
pathmap = {}
while queue:
cell = queue.popleft()
if cell.coords == ex.coords:
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 self.visited:
self.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)
class Astar(PathFindingStrategy):
def findPath(self,maze,st,ex):
c = 0
hp_queue = [(0,c,st)]
self.g_score = {st.coords: 0}
pathmap = {}
hp_queue_coords = {st.coords} #нам важна скорость
while hp_queue:
cell = heapq.heappop(hp_queue)[2]
hp_queue_coords.remove(cell.coords)
if cell.coords == ex.coords:
path = []
while cell.coords != st.coords:
path.append(cell)
cell = pathmap[cell.coords]
path.append(st)
path = path[::-1]
self.visited = set(self.g_score.keys()) #экий костыль
return path
for n in maze.getNeighbors(cell):
new_g_score = self.g_score[cell.coords] + 1
if n is not None and new_g_score < self.g_score.get(n.coords, float('inf')):
pathmap[n.coords] = cell
self.g_score[n.coords] = new_g_score
h_score = abs(n.coords[0]-ex.coords[0]) + abs(n.coords[1]-ex.coords[1])
#f = g + h
#h - манхэттенское расстояние
full_score = new_g_score + h_score
if n.coords not in hp_queue_coords:
c += 1
heapq.heappush(hp_queue, (full_score, c, n))
hp_queue_coords.add(n.coords)
self.visited = set(self.g_score.keys()) #экий костыль 2: возвращение ситхов
return None
# path = Astar().findPath(maze,maze.st,maze.ex)
# print('путь с A*:')
# for cell in path:
# print(cell.coords)
#Класс статистики поиска пути и класс оркестратор
class SearchStats():
def __init__(self, timeMs, visitedCells, pathLength):
self.timeMs = timeMs
self.visitedCells = visitedCells
self.pathLength = pathLength
class MazeSolver():
def __init__(self, maze, strategy):
self.maze = maze
self.strategy = strategy
self.observers = [ConsoleView(maze)]
for observer in self.observers:
observer.update(MazeEvent('maze_loaded',maze,maze.st.coords))
def setStrategy(self,strategy):
self.strategy = strategy
def solve(self):
start = time.perf_counter()
path = self.strategy.findPath(self.maze,self.maze.st,self.maze.ex)
end = time.perf_counter()
elapsed = end - start
visitedCells = len(self.strategy.visited)
if path is not None:
pathLength = len(path)
for observer in self.observers:
observer.update(MazeEvent('path_found',self.maze,path[-1].coords,path))
else:
pathLength = 0
for observer in self.observers:
observer.update(MazeEvent('path_found',self.maze,None,path))
return SearchStats(elapsed*1000, visitedCells, pathLength)
# MS = MazeSolver(maze, DFS())
# Stats = MS.solve()
# print(Stats.timeMs)
# print(Stats.visitedCells)
# print(Stats.pathLength)
# MS = MazeSolver(maze, BFS())
# Stats = MS.solve()
# print(Stats.timeMs)
# print(Stats.visitedCells)
# print(Stats.pathLength)
# MS = MazeSolver(maze, Astar())
# Stats = MS.solve()
# print(Stats.timeMs)
# print(Stats.visitedCells)
# print(Stats.pathLength)
#Класс для событий
class MazeEvent():
def __init__(self,event_type, maze, player_position = None, path = []):
if player_position is None:
player_position = maze.st.coords
self.event_type = event_type
self.maze = maze
self.player_position = player_position
self.path = path
#Интерфейс наблюдатель
class Observer(abc.ABC):
@abc.abstractmethod
def update(self, event):
if not isinstance(event, (str, MazeEvent)):
raise TypeError('Только строки и объекты события')
elif isinstance(event, MazeEvent) and event.event_type not in ('path_found','move','maze_loaded'):
raise TypeError('Только события "path_found","move","maze_loaded"')
#Класс консольного просмотра
class ConsoleView(Observer):
def __init__(self, maze, player_position = (0,0), path = []):
self.maze = maze
self.player_position = player_position
self.path = path
def update(self, event):
super().update(event) #проверка через сам интерфейс
if isinstance(event, str):
print('')
print(event+'\n')
self.render(self.maze, self.player_position, self.path)
else:
print('')
print(event.event_type+'\n')
if event.player_position is not None:
self.player_position = event.player_position
if event.path is not None and event.path:
self.path = event.path
self.render(event.maze, self.player_position, self.path)
def render(self, maze, player_position, path):
os.system('cls' if os.name == 'nt' else 'clear')
#из-за системы координат надо всё опять транспонировать
res = []
for row in maze.cells.T[::-1]:
subres = []
for cell in row:
if cell.isWall:
subres += '#'
elif cell.isStart:
subres += 'S'
elif cell.isExit:
subres += 'E'
else:
subres += ' '
res.append(subres)
for cell in path:
x,y = cell.coords
if res[-(y+1)][x] != 'S':
res[-(y+1)][x] = '*'
res[-(player_position[1]+1)][player_position[0]] = 'X'
for row in res:
print(''.join(row))
# builder = TextFileMazeBuilder
# maze = builder.buildFromFile('maze1.txt')
# print(maze)
# CV = ConsoleView(maze, (0,0))
# CV.update('Что-то случилось')
# ME = MazeEvent('maze_loaded', maze, (0,0))
# CV.update(ME)
# CV.update('Что-то случилось')
#Интерфейс для команд
class Command(abc.ABC):
@abc.abstractmethod
def execute(self): pass
@abc.abstractmethod
def undo(self): pass
#Класс команды движения
class MoveCommand(Command):
def __init__(self):
self.previousCell = (0,0)
def execute(self,player,direction):
self.previousCell = player.currentCell
resCell = (self.previousCell[0]+direction.dir[0],self.previousCell[1]+direction.dir[1])
player.moveTo(resCell)
def undo(self,player):
player.moveTo(self.previousCell)
#Класс игрока
class Player():
#Он хранит не текущую клетку, а только её координаты. Поскольку
#нам надо перемещать игрока динамически, а команда для перемещения
#не принимает лабиринт в качестве аргумента, следующую клетку мы
#как объект получить не можем, а можем получить только её координаты.
def __init__(self, currentCell):
self.currentCell = currentCell
def moveTo(self, cell):
self.currentCell = cell
#Класс направление
class Direction():
def __init__(self, x,y):
self.dir = (x,y)
#Тест системы перемещения клавиатурой :D
builder = TextFileMazeBuilder
maze = builder.buildFromFile('maze1.txt')
MS = MazeSolver(maze, DFS())
MS.solve()
MC = MoveCommand()
CV = MS.observers[0]
player1 = Player(CV.player_position)
instruct = '\nПеремещайтесь на W/A/S/D. Для отмены используйте ctrl+Z. Для выхода из режима перемещения команда X.\n'
def move(player, direction):
resCoords = (player.currentCell[0]+direction.dir[0], player.currentCell[1]+direction.dir[1])
resCell = maze.getCell(resCoords[0], resCoords[1])
if resCell == None or resCell.isWall:
return
MC.execute(player, direction)
CV.update(MazeEvent('move', maze, player.currentCell))
print(instruct)
def undo(player):
MC.undo(player)
CV.update(MazeEvent('move', maze, player.currentCell))
print(instruct)
keyboard.add_hotkey('w', move, args=[player1, Direction(0,1)])
keyboard.add_hotkey('s', move, args=[player1, Direction(0,-1)])
keyboard.add_hotkey('a', move, args=[player1, Direction(-1,0)])
keyboard.add_hotkey('d', move, args=[player1, Direction(1,0)])
keyboard.add_hotkey('ctrl+z', undo, args=[player1])
keyboard.wait('x')
keyboard.unhook_all()
#Эксперимент
res = []
strategyList = [BFS(),DFS(),Astar()]
sNamesList = ['BFS','DFS','Astar']
labNamesList = ['10x10','50x50','100x100','empty','no exit']
for strategy in range(3):
for i in range(1,6):
subres1 = []
subres2 = []
subres3 = []
maze_name = 'expmaze' + str(i) + '.txt'
maze = TextFileMazeBuilder.buildFromFile(maze_name)
MS = MazeSolver(maze, strategyList[strategy])
for j in range(10):
Stats = MS.solve()
subres1.append(Stats.timeMs)
subres2.append(Stats.visitedCells)
subres3.append(Stats.pathLength)
res.append([labNamesList[i-1],sNamesList[strategy],sum(subres1)/10., sum(subres2)/10., sum(subres3)/10.])
print(res)
with open("results.csv", "w", newline="") as f:
writer = csv.writer(f)
writer.writerows(res)

View File

@ -0,0 +1,6 @@
## ####S# ##
# ## # ##
## # # # #
# ### #
# ## ## E
# ##### ######

View File

@ -0,0 +1,128 @@
classDiagram
class Cell{
+tuple coords
+bool isWall
+bool isStart
+bool isExit
+isPassable(): bool
}
class Maze{
+np.array cells
+int width
+int height
+Cell st
+Cell ex
+getCell(x,y): Cell
+getNeighbors(cell): List~Cell~
}
class MazeBuilder{
<<interface>>
+buildFromFile(filename): Maze
}
class TextFileMazeBuilder{
+buildFromFile(filename): Maze
}
MazeBuilder <|.. TextFileMazeBuilder
class PathFindingStrategy{
<<interface>>
+findPath(maze,st,ex): list~Cell~
}
class BFS{
+set~tuple~ visited
+findPath(maze,st,ex): list~Cell~
}
class DFS{
+set~tuple~ visited
+findPath(maze,st,ex): list~Cell~
}
class Astar{
+dict~tuple, int~
+set~tuple~ visited
+findPath(maze,st,ex): list~Cell~
}
PathFindingStrategy <|.. BFS
PathFindingStrategy <|.. DFS
PathFindingStrategy <|.. Astar
class SearchStats{
+float timeMs
+int visitedCells
+int pathLength
}
class MazeSolver{
+Maze maze
+PathFindingStrategy strategy
+list~ConsoleView~ observers
+setStrategy(strategy)
+solve(): SearchStats
}
class MazeEvent{
+string event_type
+Maze maze
+tuple player_position
+list~tuple~ path
}
class Observer{
<<interface>>
+update(event)
}
class ConsoleView{
+Maze maze
+tuple player_position
+list~tuple~ path
+update(event)
+render(maze,player_position,path)
}
class Command{
<<interface>>
+execute()
+undo()
}
class MoveCommand{
+tuple previousCell
+execute(player,direction)
+undo(player)
}
Command <|.. MoveCommand
class Player{
+tuple currentCell
+moveTo(cell)
}
class Direction{
+tuple dir
}
MazeSolver --> PathFindingStrategy: uses
MazeBuilder --> Maze: creates
Maze --> Cell: contains
ConsoleView ..|> Observer
MazeSolver --> Observer: notifies
MazeSolver --> MazeEvent: creates
Observer --> MazeEvent: accepts
MoveCommand --> Player: moves
MoveCommand --> Direction: uses
ConsoleView --> Player: accepts position
ConsoleView --> Maze: renders
MazeSolver --> SearchStats: returns
MazeSolver --> Maze: accepts
MazeEvent --> Player: stores position
Player --> Cell: saves coords

Binary file not shown.

After

Width:  |  Height:  |  Size: 777 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 92 KiB

View File

@ -0,0 +1,16 @@
ëàáèðèíò;ñòðàòåãèÿ;âðåìÿ_ìñ;ïîñåùåíî_êëåòîê (ñð);äëèíà_ïóòè (ñð)
10x10;BFS;0.08966999594122171;36;21
50x50;BFS;2.187670022249222;1020;501
100x100;BFS;8.31503001973033;4172;414
empty;BFS;5.047210049815476;2500;99
no exit;BFS;2.197379991412163;1072;0
10x10;DFS;0.09059999138116837;37;21
50x50;DFS;1.264189975336194;593;581
100x100;DFS;5.151620041579008;2384;1122
empty;DFS;3.3813500544056296;2500;1275
no exit;DFS;2.2671299753710628;1072;0
10x10;Astar;0.11618996504694223;33;21
50x50;Astar;2.8455600142478943;973;501
100x100;Astar;9.197140019387007;2980;414
empty;Astar;7.771430024877191;2500;99
no exit;Astar;3.192879958078265;1072;0
1 ëàáèðèíò ñòðàòåãèÿ âðåìÿ_ìñ ïîñåùåíî_êëåòîê (ñð) äëèíà_ïóòè (ñð)
2 10x10 BFS 0.08966999594122171 36 21
3 50x50 BFS 2.187670022249222 1020 501
4 100x100 BFS 8.31503001973033 4172 414
5 empty BFS 5.047210049815476 2500 99
6 no exit BFS 2.197379991412163 1072 0
7 10x10 DFS 0.09059999138116837 37 21
8 50x50 DFS 1.264189975336194 593 581
9 100x100 DFS 5.151620041579008 2384 1122
10 empty DFS 3.3813500544056296 2500 1275
11 no exit DFS 2.2671299753710628 1072 0
12 10x10 Astar 0.11618996504694223 33 21
13 50x50 Astar 2.8455600142478943 973 501
14 100x100 Astar 9.197140019387007 2980 414
15 empty Astar 7.771430024877191 2500 99
16 no exit Astar 3.192879958078265 1072 0

View File

@ -0,0 +1,15 @@
10x10,BFS,0.08966999594122171,36.0,21.0
50x50,BFS,2.187670022249222,1020.0,501.0
100x100,BFS,8.31503001973033,4172.0,414.0
empty,BFS,5.047210049815476,2500.0,99.0
no exit,BFS,2.197379991412163,1072.0,0.0
10x10,DFS,0.09059999138116837,37.0,21.0
50x50,DFS,1.264189975336194,593.0,581.0
100x100,DFS,5.151620041579008,2384.0,1122.0
empty,DFS,3.3813500544056296,2500.0,1275.0
no exit,DFS,2.2671299753710628,1072.0,0.0
10x10,Astar,0.11618996504694223,33.0,21.0
50x50,Astar,2.8455600142478943,973.0,501.0
100x100,Astar,9.197140019387007,2980.0,414.0
empty,Astar,7.771430024877191,2500.0,99.0
no exit,Astar,3.192879958078265,1072.0,0.0
1 10x10 BFS 0.08966999594122171 36.0 21.0
2 50x50 BFS 2.187670022249222 1020.0 501.0
3 100x100 BFS 8.31503001973033 4172.0 414.0
4 empty BFS 5.047210049815476 2500.0 99.0
5 no exit BFS 2.197379991412163 1072.0 0.0
6 10x10 DFS 0.09059999138116837 37.0 21.0
7 50x50 DFS 1.264189975336194 593.0 581.0
8 100x100 DFS 5.151620041579008 2384.0 1122.0
9 empty DFS 3.3813500544056296 2500.0 1275.0
10 no exit DFS 2.2671299753710628 1072.0 0.0
11 10x10 Astar 0.11618996504694223 33.0 21.0
12 50x50 Astar 2.8455600142478943 973.0 501.0
13 100x100 Astar 9.197140019387007 2980.0 414.0
14 empty Astar 7.771430024877191 2500.0 99.0
15 no exit Astar 3.192879958078265 1072.0 0.0

BIN
GutovVM/docs/otchet2.docx Normal file

Binary file not shown.

BIN
GutovVM/docs/otchet2.pdf Normal file

Binary file not shown.

Binary file not shown.

BIN
GutovVM/docs/~$tchet2.docx Normal file

Binary file not shown.

BIN
GutovVM/docs/~WRL0005.tmp Normal file

Binary file not shown.