add result.md and fix cod

This commit is contained in:
4eker 2026-05-25 16:02:23 +03:00
parent 18359cc7ad
commit 4a8728f3e0
15 changed files with 479 additions and 145 deletions

View File

@ -1,26 +1,22 @@
class Maze:
def __init__(self, grid, start = None, exit = None):
self.grid = grid
self.start = start
self.exit = exit
class Maze:
def __init__(self, grid, start=None, exit=None):
self.grid = grid
self.start = start
self.exit = exit
self.height = len(grid)
self.width = len(grid[0]) if grid else 0
# Создание новой ячейки
def getCell(self, x, y):
if 0 <= x < self.height and 0 <= y < self.width:
return self.grid[x][y]
def getCell(self, x, y):
if 0 <= x < self.width and 0 <= y < self.height:
return self.grid[y][x]
return None
# Ищет соседние проходимые клетки
def getNeighbors(self, cell):
directions = [(0,1),(1,0),(0,-1),(-1,0)]
result = []
for dx, dy in directions:
nx, ny = cell.x + dx, cell.y + dy
neighbor = self.getCell(nx, ny)
if neighbor and neighbor.isPassable():
result.append(neighbor)
return result
return result

View File

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

View File

@ -1,31 +1,103 @@
############################################################
#S # # # # # # # #
# ### ##### ##### ### ##### ### ### ##### ### ##### ### ### #
# # # # # # # # # # # # #
### ##### ##### ### ##### ######### ### ### ### ####### ### #
# # # # # # # # # # # # #
# ### # ##### ### ##### ####### # ### ### ######### ##### # #
# # # # # # # # # # # # # #
########### # # ### # ####### # ### ### ######### # # # #####
# # # # # # # # # # # # # #
# ####### # # ########### ### ### ####### ##### # # # ##### #
# # # # # # # # # # # # # # # # #
# # ### # # ####### # ##### ### ### ### # # # # # # ##### # #
# # # # # # # # # # # # # # # # # # # # # #
# # # ### ####### # ##### # # ##### # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # #
# # ### ####### # ##### # # ##### # # ##### ##### # # # #####
# # # # # # # # # # # # # # # # #
# ### # # ########### # # # # # # # ##### ######### # ##### #
# # # # # # # # # # # # # # # # # #
### # # # # ##### # ### # ##### # ##### # # ##### # ##### # #
# # # # # # # # # # # # # # # # # # #
# ####### ##### # # # ### # ######### # # ##### # # # # # # #
# # # # # # # # # # # # # # # # # # # # #
####### # # # # # # # # ######### # ### # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # #
# ### # # # # # # # # # # ##### # ### # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # #
# # ### # # # # # # # # ##### # # # ### # # # # # # # # # # #
# # # # # # # # # # # # # # #
###########################################################E#
#######################################################################################################
#S # # # # # # # # # # # # # #
# ### ##### # ##### # # ### ### ####### ####### # # ### ### ### # ### ### ### ### # ### # # # #########
# # # # # # # # # # # # # # # # # # # # # # # # # #
### ### ##### # ##### ### # # ##### ####### ### ### # # # ####### # ### # # ### # ### ### ##### # ### #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# ### ### # # # # ### ### # ### ##### # ### # # # # # ####### # # ##### ### # ### ### # ##### ### # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# ### ####### # ######### ##### # # ### # ### ### ### # ####### # # ### # ##### ##### ########### # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# ##### ### # ##### # ####### ### # # # ##### # ##### ##### # ######### # # # # # # ### ### # ### # ###
# # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # ####### # ##### # ### ##### ##### # ####### ######### # ##### # # # # # ### # ### # # # ### ### # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# ##### ######### ##### # # # # # # ##### ##### ### # # # ### ####### ########### # # # # ### # ### # #
# # # # # # # # # # # # # # # # # # # # #
####### # ####### ### ##### # # # # # # # ######### ##### # # # # ####### # ### ### # ### ########### #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# ### # # # ####### # # # ##### ### # ### # ### ### # ### ####### ### # # ### ##### ### ### ######### #
# # # # # # # # # # # # # # # # # # # # # # # # # # # #
# ### ### # ##### # ### ####### # ####### ##### # # # # # # # # # # ######### # ########### # ### # # #
# # # # # # # # # # # # # # # # # # # # # # # #
# # # ####### ### ####### ### # ##### # ##### ### # # # # # # # # ### # # ####### ### ### # ### ### ###
# # # # # # # # # # # # # # # # # # # # # # # # # # #
##### ### ##### ####### # # ### ### ##### ### ############# ### ### ### ####### ##### ####### # # #####
# # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# ######### ##### # # ### ### ### ####### ##### # ### ### ### # # # # # # # ##### # # # # # # ### # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# ####### ### ### ### ##### # # # # ####### # ##### ############# ### ### ### # # # # # ######### ### #
# # # # # # # # # # # # # # # # # # # # # # # # # # #
# ### # ### ### # ### ##### ### # ##### # ####### # ### ### ##### ### # ######### # ### # ### ### # # #
# # # # # # # # # # # # # # # # # # # # # # #
### # ### ######### # ##### # ### ### ### # # ##### # # # ### # # ####### # # ### ##### ### # ##### # #
# # # # # # # # # # # # # # # # # # # # # # # # #
### # ### ##### # ########### ##### ####### ########### # ### ######### # ### # # # # ### # # ##### # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
### ##### # # ### # # ##### ### # ### # ##### # # # ##### ### # # # ##### ####### ##### ### # ### ### #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # ############# ##### # # ### ### ### ### ### # # ####### # ### ### ##### ### ### ### ### # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # ##### # # # # # # # ### ### # ### # ##### # ### ### ### ##### # ### ### ### ### ### ##### # ### ###
# # # # # # # # # # # # # # # # # # # # # # # # # #
### ### ### ### # ### ### ##### ### # # # # ### # ##### ##### # # # # ### ######### ### # # # ##### ###
# # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # ### # ########### # # ### ######### # # ### # # # ##### # ### ##### # # ### ##### ##### # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # ##### ### ### # # # ####### ############# ##### # ### ############### ##### # ##### ##### # # #####
# # # # # # # # # # # # # # # # # # # # # # # # # # #
# ### ####### # ##### ### # # # # # # # # ##### # ##### ### ##### # # ##### # ### # # ### # # ### #####
# # # # # # # # # # # # # # # # # # # # # # # # # # #
### # ##### # ### ### ### ##### # # # ### # ### ### ##### # ### ### ##### # # ####### # ### ### # ### #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # ####### # ### # # # ### ####### # ################# # # ##### # # ### # # ### # # # ##### ### # #
# # # # # # # # # # # # # # # # # # # # # # # # # # #
### ##### # ### ### ### # # ########### # # # ##### ##### ##### ### ############# # # ### ### ### # # #
# # # # # # # # # # # # # # # # # # # # # # #
##### ### ##### ### ### # ############# ### # ##### # # # ######### ### ### ### ### # ##### ### #######
# # # # # # # # # # # # # # # # # # # # # # # # # # # #
################# ### # ### # # ### # ####### ### ### ### ### # ####### # # # ### ##### # # ######### #
# # # # # # # # # # # # # # # # # # # # # # # #
####### ##### ##### # ### ### ######### ### # # ######### ### ### ### ##### # ### # # # ### # ##### ###
# # # # # # # # # # # # # # # # # # # # # # # # # #
# ### ##### ##### ### # ### # # # # ### ### # # ##### ##### ### # # ##### # # # ######### # ##### # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # #
# # ####### ### # ##### ####### # ####### ####### # # ######### ### ####### ##### ### # ######### ### #
# # # # # # # # # # # # # # # # # # # # # # # #
# ### ### ##### ##### # ##### ### # ### # ########### # ### # ### # ######### # ### # ##### ### ### ###
# # # # # # # # # # # # # # # # # # # # # #
### ### ####### # # # ##### ##### ########### # # # # ####### # # # # # ########### # # # ######### ###
# # # # # # # # # # # # # # # # # # # # # # # # # # #
# ##### # # ### # # ### # ##### ### # ### ### ##### ### # ### ##### # ### # # ############### ####### #
# # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # ##### # # # ##### # ######### # # ####### ##### ### # ### ### # # # ### # ####### ### # ### # #
# # # # # # # # # # # # # # # # # # # # # # # # #
##### ##### # ### # ### # ##### ##### ##### ##### ##### # # ########### ##### ############# ### ##### #
# # # # # # # # # # # # # # # # # # #
### ### # # ############### # # ### # # ####### ### ### # ### ### # # ##### # # # ####### ####### # ###
# # # # # # # # # # # # # # # # # # # # # # # # # # # #
# ####### ##### # ### # # # ##### ### # ### # ### # ########### ### # # ##### # ##### ####### # ##### #
# # # # # # # # # # # # # # # # # # # # # # # # # #
########### # ######### # ### # ### ### ### # ### ####################### # ### # ####### # ### # ### #
# # # # # # # # # # # # # # # # # # # # # # #
# # ### ####### # ### ### ### ### ########### # ##### # ##### ### ### # ### # ##### # ########### # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
### ### # ####### # # # ### ### # # # ### # # # ### # ##### # # ########### ######### # ### ### # ### #
# # # # # # # # # # # # # # # # # # # # # # # # # #
# # # ####### # ### # # # ### # ### ### ### ######### # ### # ### # ### # # ### ##### ####### ### # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # #
### ##### ##### # # # # # # ##### # ### # ### ####### ####### ##### ### # ### ##### # # ### # # #######
# # # # # # # # # # # # # # # # # # # # # # # #
# # # ### # ####### # ####### # ##### # ### # ### # # ####### ##### # ##### ##### # ### # # ### ##### #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
### # ######### # ##### # ### ##### ### # ##### ##### ### # ##### ### # # ############# # # ### # ### #
# # # # # # # # # # # # # # # # # # # # # # # # # # #
# ### # # # # # ### # # ### ### ##### ### # # # ### ### # # # # # ### # ### # # # # # # ##### # ### ###
# # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# ####### ### # ### # ### # ### # # ####### # ##### # ### ### ##### # # # # ### # ### ### # ### ##### #
# # # # # # # # # # # # # # # # # # # # # # # # # # #
# ### ##### ### # # # ##### ############### ### # ### # # ### ##### ### # ##### ### ### ### ### # #####
# # # # # # # # # # # # # # # # # # # # # # # # # #
### # ### ####### ### ### ##### # # # ##### ##### ######### ### ##### # ####### # # ### ### # ### #####
# # # # # # # # # # # # # # # # E#
#######################################################################################################

View File

@ -1,5 +1,53 @@
##################################################
#S # # # # # # E#
# ## # #### # ### # ##### # #### # ##### # ##### #
# # # # # # # # # # # # # #
##################################################
#####################################################
#S # # # # # # # # #
# ### # ### ########### # ### ### # ### # ###########
# # # # # # # # # #
### ### # # ### ### ##### # ##### ### ### ##### ### #
# # # # # # # # # # # # #
# ######### ##### # # ### ####### # ####### # ##### #
# # # # # # # # # # # # # # # #
# ### # ##### # # ### # ### # # ##### ##### # ##### #
# # # # # # # # # # # # # # #
### ### # # ### # ### ### # ### # # # ##### # # # ###
# # # # # # # # # # # # # # #
# ##### ####### ### ### ##### ### # ### # ### ### ###
# # # # # # # # # # # # # #
# ### ####### ### ### # ##### ######### ### ##### # #
# # # # # # # # # # # # # # # #
# # # ### ### # # # ####### # # # ######### ### ### #
# # # # # # # # # # # # # # # # # #
### ####### # # ### # # ### ### # ### # ##### # # # #
# # # # # # # # # # # # # #
# ####### # # # ### # # # # # ### # # ### # # ### # #
# # # # # # # # # # # # # # #
### ### ### ##### ### ### ### ### ##### ### ####### #
# # # # # # # # # # #
##### # # # ### # # ####### ### # ##### ### # ### ###
# # # # # # # # # # # # # # # # #
# ####### ### ### # ########### # # ##### # ### ### #
# # # # # # # # # # # # # # # # #
# # ### ### ### ### ### ### # # ### # # ### ##### # #
# # # # # # # # # # # # # # # # #
# ### # ##### ### ##### ##### # # ### # ### ### ### #
# # # # # # # # # # # # #
# ##### ######### ### # ### # ### # ### ####### #####
# # # # # # # #
### # # ##### ##### ########### # ### ### # ### #####
# # # # # # # # # # # # # #
# # # ### ##### ##### # ############# ##### # ##### #
# # # # # # # # # # #
# ### # # # ### ### ### ##### # # ##### ##### #######
# # # # # # # # # # # # #
### # ##### ### # ####### ####### # # # # ##### # ###
# # # # # # # # # # # # # # # # #
### ### ### ####### ####### # ### # ### # # ### ### #
# # # # # # # # # # # # # # # # #
# # # # ### # # # # ##### ### ####### # # # ### # # #
# # # # # # # # # # # # # # # # # # # #
# # # ### ### # ##### # ### # # ### # ##### # # ### #
# # # # # # # # # # # #
### # # # # # # ##### # ### ### ##### ### # ##### ###
# # # # # # # # # # # # # # # # #
# # # ### ### ####### # ### # ### # ### ### ### ### #
# # # # # # # # # #E#
#####################################################

View File

@ -1,3 +1,10 @@
#####
#S###
#####
##########
#S #
# # #
# # #
# # #
# # #
# # #
# # #
# #
##########

View File

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

View File

@ -8,6 +8,9 @@ class AStar(PathFindingStrategy):
return abs(a.x - b.x) + abs(a.y - b.y)
def findPath(self, maze, start, exit):
if exit is None:
return [], 0
heap = []
counter = 0
heapq.heappush(heap, (0, counter, start))
@ -18,7 +21,7 @@ class AStar(PathFindingStrategy):
visited = set()
while heap:
_, _, current = heapq.heappop(heap) # распаковка трёх элементов
_, _, current = heapq.heappop(heap)
if current == exit:
break

View File

@ -3,7 +3,10 @@ from Strategies.path import restore
from collections import deque
class BFS(PathFindingStrategy):
def findPath(self, maze, start, exit):
def findPath(self, maze, start, exit):
if exit is None:
return [], 0
queue = deque([start])
visited = {start}
parent = {}
@ -18,6 +21,6 @@ class BFS(PathFindingStrategy):
if n not in visited:
visited.add(n)
parent[n] = current
queue.append(n)
queue.append(n)
return restore(parent, start, exit), len(visited)

View File

@ -1,9 +1,11 @@
from Strategies.strat import PathFindingStrategy
from Strategies.path import restore
class DFS(PathFindingStrategy):
def findPath(self, maze, start, exit):
if exit is None:
return [], 0
stack = [start]
visited = {start}
parent = {}
@ -20,4 +22,4 @@ class DFS(PathFindingStrategy):
parent[n] = current
stack.append(n)
return restore(parent, start, exit), len(visited)
return restore(parent, start, exit), len(visited)

View File

@ -1,11 +1,11 @@
def restore(parent, start, exit):
if exit not in parent and start != exit:
return[]
return []
path = []
current = exit
current = exit
while current != start:
while current != start:
path.append(current)
current = parent[current]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 88 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 914 KiB

View File

@ -0,0 +1,173 @@
# Структура:
- **Описание задачи и выбранных паттернов** (с диаграммой классов из Mermaid).
- **Листинги ключевых классов** (можно выборочно) **или ссылка на репозиторий**.
- **Результаты экспериментов** (таблицы, графики).
- **Анализ эффективности алгоритмов и применимости паттернов**.
- **Выводы: как ООП и паттерны помогли сделать код гибким и расширяемым. Что было бы сложно изменить без них**.
### Выводы:
#### 1) **Описание задачи и выбранных паттернов**
![[mermaid.png]]
>Диаграмма классов
| Паттерн | Реализация в проекте | Обоснование |
| ------------ | --------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Builder** | `MazeBuilders` (интерфейс)<br>`TextFileMazeBuilder` | Создание лабиринта из текстового файла.<br>Позволяя легко добавить другие форматы без изменения `Maze` |
| **Strategy** | `PathFindingStrategy` (интерфейс)<br>`BFS`<br>`DFS`<br>`AStar` | Алгоритмы поиска пути взаимозаменяемы<br>Strategy позволяет переключать их через `MazeSolver.setStrategy()` и добавлять новые (например, Дейкстра) без изменения кода |
| **Observer** | `Observer` (интерфейс)<br>`ConsoleView` | Отделяет визуализацию от логики поиска<br>`MazeSolver` может уведомлять подписчиков о событиях (начало/конец поиска), а `ConsoleView` реагирует на них<br>Легко добавить другие виды отображения (GUI, лог-файл) |
| **Command** | `Command` (интерфейс)<br>`Observer` (интерфейс)<br>`MoveCommand`<br>`ConsoleView` | Обеспечивает пошаговое наблюдение и отслеживание с возможностью отмены |
| | | |
#### 2) **Листинги ключевых классов**:
**Core:**
```python
class Cell:
def __init__(self, x = 0, y = 0, isWall = False, isStart = False, isExit = False):
self.x = x
self.y = y
self.isWall = isWall
self.isStart = isStart
self.isExit = isExit
# Возращает True, если посаседству стена
def isPassable(self):
return not self.isWall
class Maze:
def __init__(self, grid, start = None, exit = None):
self.grid = grid
self.start = start
self.exit = exit
self.height = len(grid)
self.width = len(grid[0]) if grid else 0
# Создание новой ячейки
def getCell(self, x, y):
if 0 <= x < self.height and 0 <= y < self.width:
return self.grid[x][y]
return None
# Ищет соседние проходимые клетки
def getNeighbors(self, cell):
directions = [(0,1),(1,0),(0,-1),(-1,0)]
result = []
for dx, dy in directions:
nx, ny = cell.x + dx, cell.y + dy
neighbor = self.getCell(nx, ny)
if neighbor and neighbor.isPassable():
result.append(neighbor)
return result
```
**Builder:**
```python
from abc import ABC, abstractmethod
class MazeBuilders(ABC):
@abstractmethod
def build_from_file(self, filename):
pass
from Core.Cell import Cell
from Core.Maze import Maze
from Builder.BuilderInterface import MazeBuilders
class TextFileMazeBuilder(MazeBuilders):
def build_from_file(self, filename):
grid = []
start = None
exit = None
with open(filename, "r", encoding="utf-8") as f:
lines = [line.rstrip("\n") for line in f]
for y, line in enumerate(lines):
row = []
for x, ch in enumerate(line):
cell = Cell(x, y, isWall = (ch == "#"), isStart = (ch == "S"), isExit = (ch == "E"))
if (ch == "S"):
start = cell
if (ch == "E"):
exit = cell
row.append(cell)
grid.append(row)
return Maze(grid, start, exit)
```
#### 3) **Результаты экспериментов**:
![[analysis 3.png]]
>График созданный на основе 5 попыток замеров и их усреднения
### 4) **Анализ эффективности алгоритмов и применимости паттернов:**
- **BFS**
Работает медленно и обходит гораздо больше клеток, но гарантирует кратчайший маршерут
- **DFS**
Работает быстро, но за это приходиться платить не самыми оптимальными путями и количеством обходимых маршерутов(из-за чего растёт время работы)
- **A****
Является золотой серединой между DFS и BFS ищет маршерут хуже BFS, но лучше чем DFS, обратная зависимость наблюдается в измерении времени
#### 5)**Выводы: как ООП и паттерны помогли сделать код гибким и расширяемым? Что было бы сложно изменить без них?**
ООП и паттерны помогли систематизировать код и написать единый код для 3 структур, так же легко масштабировать проект, за счёт единых функций применимых для разных алгоритмов
Сложно было бы изменить файлы лабиринтов, алгоритмы поиска пути,

View File

@ -1,16 +1,16 @@
maze,strategy,time_ms,visited_cells
small,BFS,0.031,8
small,DFS,0.027,8
small,A*,0.039,8
medium,BFS,0.033,10
medium,DFS,0.031,10
medium,A*,0.044,10
large,BFS,0.641,197
large,DFS,0.574,197
large,A*,1.016,197
empty,BFS,0.01,2
empty,DFS,0.008,2
empty,A*,0.01,2
no_exit,BFS,0.006,1
no_exit,DFS,0.005,1
no_exit,A*,0.006,1
maze,strategy,time_ms,visited_cells,path_length
small,BFS,0.379,58,15
small,DFS,0.076,31,19
small,A*,0.298,57,15
medium,BFS,5.197,1263,173
medium,DFS,3.898,1229,173
medium,A*,4.109,806,173
large,BFS,17.886,3918,269
large,DFS,7.197,1905,269
large,A*,10.377,2040,269
empty,BFS,0.195,64,15
empty,DFS,0.135,64,29
empty,A*,0.288,63,15
no_exit,BFS,0.007,0,0
no_exit,DFS,0.007,0,0
no_exit,A*,0.007,0,0

1 maze strategy time_ms visited_cells path_length
2 small BFS 0.031 0.379 8 58 15
3 small DFS 0.027 0.076 8 31 19
4 small A* 0.039 0.298 8 57 15
5 medium BFS 0.033 5.197 10 1263 173
6 medium DFS 0.031 3.898 10 1229 173
7 medium A* 0.044 4.109 10 806 173
8 large BFS 0.641 17.886 197 3918 269
9 large DFS 0.574 7.197 197 1905 269
10 large A* 1.016 10.377 197 2040 269
11 empty BFS 0.01 0.195 2 64 15
12 empty DFS 0.008 0.135 2 64 29
13 empty A* 0.01 0.288 2 63 15
14 no_exit BFS 0.006 0.007 1 0 0
15 no_exit DFS 0.005 0.007 1 0 0
16 no_exit A* 0.006 0.007 1 0 0