Проект “Симуляция” #
Суть проекта — пошаговая симуляция 2D мира, населённого травоядными и хищниками. Кроме существ, мир содержит ресурсы (траву), которыми питаются травоядные, и статичные объекты, с которыми нельзя взаимодействовать — они просто занимают место.
2D мир представляет собой матрицу N×M, каждое существо или объект занимают клетку целиком, нахождение в клетке нескольких объектов/существ — недопустимо.
Идея взята
отсюда и упрощена.
Комментарии по проекту —
https://www.youtube.com/watch?v=3Vrwx4iryhw.
Что нужно знать #
- Go — структуры, интерфейсы, композиция, embedding,
map, срезы, пакеты, методы - Понимание разницы между императивной логикой и данными: в Go логика обычно не “живёт” внутри сущностей
Мотивация проекта #
Основная цель — продемонстрировать архитектурный дизайн в Go, где:
- вместо иерархии классов — композиция и интерфейсы,
- вместо наследования — встраивание и интерфейсная типизация,
- вместо “умных объектов” — “глупые данные” + “умные сервисы”.
Дизайн проекта #
Position
#
Структура для обозначения координат для всех существ и объектов существующих в симуляции, содержит пару координат.
EntityType
#
Алиас над типом string для обозначения типа сущности: grass, rock, tree etc.
Occupier
#
Интерфейс определяющий все, что может занимать клетку. Примеры методов Type() EntityType, Pos() Position
Grass, Rock, Tree
#
Rock, Tree - статичные объекты. Grass - ресурс для травоядных. Будем реализовывать как имплементации интерфейса Occupier
Creature
#
Подмножество Occupier. Существо, имеет скорость (сколько клеток может пройти за 1 ход), количество HP. Интерфейс должен позволять реализовать движение по карте и работу с HP.
Herbivore
#
Травоядное, реализует интерфейс Creature. Стремятся найти ресурс (траву), может потратить свой ход на движение в сторону травы, либо на её поглощение.
Predator
#
Хищник, реализует интерфейс Creature. В дополнение к Creature, имеет силу атаки. На что может потратить ход хищник:
- Переместиться (чтобы приблизиться к жертве - травоядному)
- Атаковать травоядное. При этом количество HP травоядного уменьшается на силу атаки хищника. Если значение HP жертвы опускается до 0, травоядное исчезает
Map
#
Карта, содержит в себе коллекцию для хранения существ и их расположения. Советую не спешить использовать двумерный массив или список списков, а подумать какие ещё коллекции могут подойти.
Simulation
#
Главный класс приложения, включает в себя:
- Карту
- Счётчик ходов
- Рендерер поля
- Actions - список действий, исполняемых перед стартом симуляции или на каждом ходу (детали ниже)
Методы:
NextTurn()- просимулировать и отрендерить один ходStart()- запустить бесконечный цикл симуляции и рендерингаPause()- управляет работой симуляции
Actions
#
Action - действие, совершаемое над миром. Например - сходить всеми существами. Это действие итерировало бы существ и управляло передвижением. Логика поведения живет здесь - не в сущностях. Каждое действие описывается отдельной структурой и совершает операции над картой. Симуляция содержит 2 массива действий:
initActions- действия, совершаемые перед стартом симуляции. Пример - расставить объекты и существ на картеturnActions- действия, совершаемые каждый ход. Примеры - передвижение существ, добавить травы или травоядных, если их осталось слишком мало
Поиск пути #
Советую писать алгоритм поиска пути полностью с нуля, используя в качестве источника описание алгоритма на википедии. Проще всего начать с алгоритма поиска в ширину. Он относительно простой в реализации, но может работать медленно на больших полях, для которых лучше подойдет алгоритм A*.
Рендерер #
Рендерер ответственен за визуализацию состояния поля, его отрисовку. По желанию студента интерфейс приложения может быть консольным, либо графическим.
Конечная цель #
Реализовать симуляцию и подобрать различные значения так, чтобы взаимодействия внутри мира получились максимально интересными:
- Размер поля
- Диапазоны HP и скорости существ
- Диапазон атаки хищников
Опциональные идеи для усложнения проекта:
- Механика размножения существ
- Механика голода, когда от отсутствия пищи у них начинает уменьшаться HP
Ресурсы для работы над ошибками #
- Реализации проекта другими студентами и мои ревью этих реализаций
- Чеклист для самопроверки с типовыми ошибками (в конце страницы)
- Присылайте законченные проекты в чат, добавляю их в список, сообщество делает ревью проектов
Чеклист для самопроверки #
❗️Спойлеры: советую не читать этот список до того момента, пока не допишете первую самостоятельную работающую версию проекта❗️
Проблемы и ошибки в коде:
- Интеграция библиотеки графического интерфейса ценой чистоты и понятности кода. Достаточно консольного интерфейса
- Дублирование кода между структурами
- Класс Map
- Неоптимальный выбор коллекции для хранения состояния ячеек
- Не использование интерфейсов, параллельные коллекции для разных типов существ (для каждого типа своя коллекция)
- Заполнение карты “пустотами”
- Неоднозначное именование полей, переменных, методов. Несовпадение имён смысловой нагрузке
- Поиск пути в отдельном пакете
- Логика поведение не в сущностях
- Использование интерфейсов и duck typing
- Использован context для управления жизненным циклом
- Поиск пути
- Реализация алгоритма поиска пути внутри классов существ. Следует вынести это в отдельный класс
- Дублирование кода для поиска пути хищниками и травоядными
Мелочи:
- Неиспользование
.gitignore, из-за чего в репозиторий попадают лишние файлы и папки (например,logs,.env) - Неаккуратное форматирование кода
- Неиспользование пакетов для разделения логики, все лежит в main.go