forked from UNN/2026-rff_mp
213 lines
7.3 KiB
Markdown
213 lines
7.3 KiB
Markdown
|
|
Лабораторная работа 2
|
|||
|
|
|
|||
|
|
Поиск выхода из лабиринта
|
|||
|
|
|
|||
|
|
Цель работы
|
|||
|
|
-----------
|
|||
|
|
Цель работы состоит в реализации программы для поиска выхода из лабиринта с использованием объектно ориентированного подхода и паттернов проектирования
|
|||
|
|
|
|||
|
|
В программе реализована загрузка лабиринта из файла несколько алгоритмов поиска и сравнение их работы
|
|||
|
|
|
|||
|
|
Структура программы
|
|||
|
|
-------------------
|
|||
|
|
В программе используются классы Cell для отдельной клетки лабиринта и Maze для самого лабиринта
|
|||
|
|
|
|||
|
|
Для загрузки используется MazeBuilder и его реализация TextFileMazeBuilder
|
|||
|
|
|
|||
|
|
Для поиска пути используется общий класс PathFindingStrategy и три алгоритма BFSStrategy DFSStrategy и AStarStrategy
|
|||
|
|
|
|||
|
|
За хранение результатов отвечает SearchStats а запуск поиска выполняет MazeSolver
|
|||
|
|
|
|||
|
|
Для вывода информации используются Observer и ConsoleView
|
|||
|
|
|
|||
|
|
Использованные паттерны
|
|||
|
|
-----------------------
|
|||
|
|
В работе использованы три паттерна Builder Strategy и Observer
|
|||
|
|
|
|||
|
|
Builder используется для загрузки лабиринта из текстового файла
|
|||
|
|
|
|||
|
|
TextFileMazeBuilder читает файл и создаёт объект Maze
|
|||
|
|
|
|||
|
|
В файле символ # обозначает стену пробел обозначает свободную клетку S является началом а E выходом
|
|||
|
|
|
|||
|
|
Использование Builder позволяет отдельно реализовать загрузку лабиринта и сам класс лабиринта
|
|||
|
|
|
|||
|
|
Strategy используется для выбора алгоритма поиска
|
|||
|
|
|
|||
|
|
В программе реализованы BFS DFS и A*
|
|||
|
|
|
|||
|
|
Все алгоритмы имеют общий интерфейс PathFindingStrategy поэтому в MazeSolver можно менять алгоритм без изменения самого решателя
|
|||
|
|
|
|||
|
|
Observer используется для вывода информации о поиске
|
|||
|
|
|
|||
|
|
MazeSolver отправляет события а ConsoleView получает их и выводит информацию в консоль
|
|||
|
|
|
|||
|
|
Таким образом вывод отделён от основной логики поиска
|
|||
|
|
|
|||
|
|
Алгоритмы поиска
|
|||
|
|
----------------
|
|||
|
|
BFS использует очередь и при обычных условиях находит кратчайший путь в лабиринте без весов
|
|||
|
|
|
|||
|
|
DFS использует стек и может найти путь быстрее но найденный путь не обязательно будет кратчайшим
|
|||
|
|
|
|||
|
|
A* использует очередь с приоритетом и манхэттенскую эвристику поэтому старается в первую очередь проверять клетки которые находятся ближе к выходу
|
|||
|
|
|
|||
|
|
Схема классов
|
|||
|
|
-------------
|
|||
|
|
classDiagram
|
|||
|
|
|
|||
|
|
class Cell {
|
|||
|
|
x
|
|||
|
|
y
|
|||
|
|
is_wall
|
|||
|
|
is_start
|
|||
|
|
is_exit
|
|||
|
|
is_passable()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
class Maze {
|
|||
|
|
width
|
|||
|
|
height
|
|||
|
|
cells
|
|||
|
|
start
|
|||
|
|
exit
|
|||
|
|
get_cell()
|
|||
|
|
get_neighbors()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
class MazeBuilder {
|
|||
|
|
build_from_file()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
class TextFileMazeBuilder {
|
|||
|
|
build_from_file()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
class PathFindingStrategy {
|
|||
|
|
find_path()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
class BFSStrategy {
|
|||
|
|
find_path()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
class DFSStrategy {
|
|||
|
|
find_path()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
class AStarStrategy {
|
|||
|
|
find_path()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
class SearchStats {
|
|||
|
|
path
|
|||
|
|
time_ms
|
|||
|
|
visited_count
|
|||
|
|
path_length
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
class MazeSolver {
|
|||
|
|
maze
|
|||
|
|
strategy
|
|||
|
|
set_strategy()
|
|||
|
|
solve()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
class Observer {
|
|||
|
|
update()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
class ConsoleView {
|
|||
|
|
update()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
MazeBuilder <|-- TextFileMazeBuilder
|
|||
|
|
PathFindingStrategy <|-- BFSStrategy
|
|||
|
|
PathFindingStrategy <|-- DFSStrategy
|
|||
|
|
PathFindingStrategy <|-- AStarStrategy
|
|||
|
|
Observer <|-- ConsoleView
|
|||
|
|
MazeSolver --> Maze
|
|||
|
|
MazeSolver --> PathFindingStrategy
|
|||
|
|
MazeSolver --> Observer
|
|||
|
|
Maze --> Cell
|
|||
|
|
Тестирование
|
|||
|
|
------------
|
|||
|
|
Для проверки использовалось пять разных лабиринтов
|
|||
|
|
|
|||
|
|
simple.txt представляет простой лабиринт dead.txt содержит тупики large.txt является большим запутанным лабиринтом empty.txt не содержит стен а в noexit.txt выход недостижим
|
|||
|
|
|
|||
|
|
Каждый алгоритм запускался пять раз
|
|||
|
|
|
|||
|
|
Во время эксперимента измерялось время поиска количество посещённых клеток и длина найденного пути
|
|||
|
|
|
|||
|
|
Результаты сохранялись в файл results.csv
|
|||
|
|
|
|||
|
|
Результаты
|
|||
|
|
----------
|
|||
|
|
simple.txt
|
|||
|
|
Алгоритм Время мс Посещено Путь
|
|||
|
|
BFS 0.01464 11 6
|
|||
|
|
DFS 0.01018 9 8
|
|||
|
|
A* 0.01774 9 6
|
|||
|
|
|
|||
|
|
Все алгоритмы работают быстро
|
|||
|
|
|
|||
|
|
BFS и A* нашли более короткий путь чем DFS
|
|||
|
|
|
|||
|
|
dead.txt
|
|||
|
|
Алгоритм Время мс Посещено Путь
|
|||
|
|
BFS 0.36430 307 35
|
|||
|
|
DFS 0.23494 279 151
|
|||
|
|
A* 0.38374 235 35
|
|||
|
|
|
|||
|
|
DFS работал немного быстрее но нашёл более длинный путь
|
|||
|
|
|
|||
|
|
BFS и A* нашли короткий путь
|
|||
|
|
|
|||
|
|
large.txt
|
|||
|
|
Алгоритм Время мс Посещено Путь
|
|||
|
|
BFS 23.89446 6812 2329
|
|||
|
|
DFS 84.77876 6796 4537
|
|||
|
|
A* 28.69542 6791 2329
|
|||
|
|
|
|||
|
|
На большом лабиринте DFS показал худшее время и самый длинный путь
|
|||
|
|
|
|||
|
|
BFS и A* нашли одинаковый путь
|
|||
|
|
|
|||
|
|
empty.txt
|
|||
|
|
Алгоритм Время мс Посещено Путь
|
|||
|
|
BFS 1.277
|
|||
|
|
|
|||
|
|
|
|||
|
|
04 1176 48
|
|||
|
|
DFS 7.60228 2304 1176
|
|||
|
|
A* 0.10094 48 48
|
|||
|
|
|
|||
|
|
В лабиринте без стен лучше всего показал себя A*
|
|||
|
|
|
|||
|
|
Он посетил меньше всего клеток и работал быстрее
|
|||
|
|
|
|||
|
|
noexit.txt
|
|||
|
|
Алгоритм Время мс Посещено Путь
|
|||
|
|
BFS 0.00370 1 0
|
|||
|
|
DFS 0.00320 1 0
|
|||
|
|
A* 0.00412 1 0
|
|||
|
|
|
|||
|
|
В этом лабиринте выход недостижим поэтому все алгоритмы быстро закончили поиск
|
|||
|
|
|
|||
|
|
Графики
|
|||
|
|
-------
|
|||
|
|
Для сравнения времени работы были построены графики для каждого лабиринта
|
|||
|
|
|
|||
|
|
Графики находятся в папке docs/data
|
|||
|
|
|
|||
|
|
simple_time.png dead_time.png large_time.png empty_time.png и noexit_time.png
|
|||
|
|
|
|||
|
|
Вывод
|
|||
|
|
-----
|
|||
|
|
В работе была создана программа для поиска выхода из лабиринта
|
|||
|
|
|
|||
|
|
Были реализованы BFS DFS и A* а также использованы паттерны Builder Strategy и Observer
|
|||
|
|
|
|||
|
|
По результатам эксперимента BFS хорошо подходит для поиска кратчайшего пути DFS может найти путь быстрее но он не всегда получается коротким A* хорошо показывает себя на больших и открытых лабиринтах
|