forked from UNN/2026-rff_mp
173 lines
6.9 KiB
Markdown
173 lines
6.9 KiB
Markdown
|
|
# Структура:
|
|||
|
|
- **Описание задачи и выбранных паттернов** (с диаграммой классов из 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 структур, так же легко масштабировать проект, за счёт единых функций применимых для разных алгоритмов
|
|||
|
|
Сложно было бы изменить файлы лабиринтов, алгоритмы поиска пути,
|