Оценка за семестр
Оценку за семестр можно получить на основании набранных баллов за работы
Можно воспользоваться возможностью поменять оценку сдав зачет
Для допуска к зачету (получению оценки) необходимо сдать первых 5 работ
Если сданы 5 работ, но не набрано достаточное кол-во баллов, то зачет сдается в обязательном порядке
Если сдано меньше 5 работ, даже если набрано достаточное кол-во баллов, то ставится не аттестация
Если сдано 5 работ, и кол-во баллов вас удовлетворяют, то работы 6-8 сдавать необязательно
Соотношение оценки и кол-ва баллов (включительно)
Оценка |
Баллы |
Отлично |
63 |
Хорошо |
49 |
Удовлетворительно |
35 |
Лабораторные работы
В ходе выполнения лабораторных работ, вам самостоятельно необходимо прорабатывать архитектуру программы, какие классы разработать, как они будут взаимодействовать между собой.
Можно добавлять дополнительные классы, которые не описаны в самих лабораторных работах.
При проверке лаб. работ, основной упор будет делать на гибкость и масштабируемость кода. То есть должно быть минимальное количество сильно связанных классов. А также корректное использование классов и придерживании ООП парадигмы.
Использование паттернов проектирования приветствуется, и корректное их использование может закрыть какие-то недочеты.
При невыполнении какого-то требования лабораторная работа не принимается и отправляется на доработку.
Каждая лаб. работа должна сопровождаться отчетом в электронном виде.
Градация баллов. Для лаб работ оцениваемых в 5 баллов максимум, значения делятся на 2.
Балл |
Статус |
10 |
замечаний нет |
9 |
всё корректно, но есть замечания, которые можно не исправлять |
7-8 |
незначительные ошибки/замечания |
4-6 |
ошибки/проблемы с архитектурой |
1-3 |
грубые ошибки/серьезные проблемы с архитектурой/ не соблюдены принципы ООП |
Не прием |
программа не запускается/падает/не выполнены какие-то требования |
№1 - Создание классов
Для данной лаб. работы UML диаграмма классов в отчете не обязательна.
а) Создать класс игрока. У игрока должны быть поля, которые определяют его характеристики, например кол-во жизней, очков и.т.д. Также в классе игрока необходимо реализовать ряд методов для работы с его характеристиками. Данные методы должны контролировать значения характеристик (делать проверку на диапазон значений).
б) Создать класс, передвигающий игрока по полю и работу с характеристиками. Данный класс всегда должен знать об объекте игрока, которым управляет, но не создавать класс игрока. В следующих лаб. работах данный класс будет проводить проверку, может ли игрок совершить перемещение по карте.
Примечания:
Не забывайте для полей и методов определять модификатор доступа
Для указания направления движения можно использовать перечисление enum или дополнительную систему классов. Использования чисел или строк является для указания направления является плохой практикой
Делать отдельный метод под каждое направление делает класс перегруженным, и в будущем ограничивает масштабирование класса
№2 - Конструкторы и деструкторы
а) Создать класс клетки игрового поля. Клетка игрового поля может быть проходимой или нет, тем самым определяя возможность игрока встать на эту клетку. Возможность задать проходимость клетки должна быть реализована через конструктор и через метод клетки. В будущем в клетке будет храниться указатель на интерфейс события.
б) Создать класс игрового поля. Игровое поле представляет собой прямоугольник из клеток (двумерный массив). В учебных целях, клетки хранятся как чистый массив на указателях (использовать контейнеры stl запрещено в этой лаб. работе). Размер поля передается в конструктор поля, в котором динамически выделяется память под массив клеток. Также должна быть возможность вызвать конструктор поля без аргументов. Так как происходит выделение память, то необходимо реализовать деструктор в котором будет происходить очистка память.
Также добавить в игровое поле добавьте информацию о входе (где в начале появляется игрок) и выходе (куда игрок должен дойти)
Также для класса поля необходимо реализовать конструкторы копирования и перемещения, а также соответствующие им операторы присваивания.
в) В класс управления игрока добавить взаимодействия с полем. При перемещении игрока должна быть проверка на проходимость клетки, если клетка непроходима, то перемещение не должно производиться.
Примечания:
Так как в клетке будет храниться указатель, то при копировании и перемещении должен быть предусмотрен механизм копирования объекта хранящегося по указателю.
Убедитесь, что присутствует проверка контроля размера поля, чтобы его нельзя было сделать слишком маленьким или с отрицательными размерами.
В конструкторе перемещения и соответствующем ему операторе присваивания не должно происходить никакого копирования данных.
Через класс поля должен быть доступ к каждой индивидуальной клетке. Создавать метод, который возвращает указатель на весь массив или указатель на каждую клетку, плохая практика, так как появляется возможность очистки памяти.
№3 - Полиморфизм
а) Создать интерфейс игрового события. Интерфейс должен обеспечивать срабатывание события когда игрок наступает на клетку.
б) Реализовать интерфейс игрового события тремя конкретными событиями. Одно событие должно положительно влиять на характеристики игрока, второе должно негативно влиять на характеристики игрока, третье изменять координаты игрока на поле. При желании можно реализовать больше событий и/или события меняющие само поле (например, делать из непроходимой клетки проходимую).
в) В классе управления игроком добавить проверку на наличие события на клетке, если событие присутствует, то оно должно сработать. Срабатывание должно происходить через интерфейс события, и не должно быть никаких проверок на тип события (реализация через динамический полиморфизм)
г) Создать класс создающий поле. Предусмотреть возможность создания 2 разных уровней. По желанию можно сделать случайную генерацию уровней. Должно гарантироваться, что игрок может дойти от входа до выхода.
Примечания:
События должны быть такими, чтобы был сценарий проигрыша игрока.
В событиях и клетках не должно быть полей сообщающих информацию о типе события
№4 - Уровни абстракции
а) Создать класс игры. Класс игры отвечает за запуск игры (в начале и во время текущей сессии), выход из игры, выбор уровня, а также инициализирующего перемещение игрока. Также класс должен проводить проверку проигрыша или выигрыша игрока и давать возможность начать новую игру или завершить работу программы.
б) Создать класс (или набор классов) считывания ввода пользователя. Данный класс(ы) должен сопоставить ввод пользователя с командой, которую необходимо выполнить. И передать эту информацию в класс игры. Клавиши управления должны считываться из файла. Класс(ы) должен быть разработан так, чтобы:
потенциально можно было масштабировать управление с минимальным количеством изменений в коде
можно было заменить схему управления, например, заменить ввод команду через терминал на чтение команд из файла или из сети с другого устройства
Примечания:
После считывания клавиши, считанный символ должен сразу обрабатываться, и далее работа должна проводить с сущностью, которая представляет команду.
Для представления команды можно разработать системы классов или использовать перечисление enum.
Хорошей практикой является создание “прослойки” между считыванием/обработкой команды и классом игры, которая сопоставляет команду и вызываемым методом игры. Существуют альтернативные решения без явной “прослойки”
При считывания управления необходимо делать проверку, что на все команды назначена клавиша, что на одну клавишу не назначено две команды, что на одну команду не назначено две клавиши.
При работе с файлом используйте идиому RAII.
№5 - Отслеживание изменений
а) Реализовать класс, который связывается с игрой, и отслеживает изменения в игре: перемещение игрока, победа или выигрыш, срабатывание событий. Данный класс должен реагировать на изменения и отрисовывать игровое поле, а также выводить информацию для игрока (например, предлагать начать новую игру).
б) При отрисовке поля должна считываться информация с поля и об игроке, и в зависимости от расположения происходит вывод представления поля в терминал. В представлении поля непроходимые клетки, игрок, события должны отображаться различными символами. Игрок, события, клетки и другие игровые сущности не должны знать ничего о том, каким символом они отрисовываются. За выбор символа отвечает класс выполняющий отрисовку
Примечания:
Класс отслеживания и класс отрисовки рекомендуется делать отдельными сущностями. Таким образом, класс отслеживания инициализирует отрисовку, и при необходимости можно заменить отрисовку (например, на GUI) без изменения самого отслеживания
При проверке типов события можно использовать dynamic_cast / typeinfo, либо сделать связывание модель-представление
№6* - Перегрузка операторов / Логирование
а) Реализовать набор классов “сообщений” с общим интерфейсом, который будут срабатывать в определенные моменты и хранить информацию о событии, но не должны хранить сообщение в виде строки. Должны быть реализованы класс для следующих событий:
Игрок выиграл. Хранится информация о характеристиках игрока
Игрок проиграл. Хранится информация о координатах клетки на которой событие произошло
Была запущена новая игра. Хранится информация о размерах поля и стартовой позиции игрока.
Была введена клавиша и сработала команда. Информация о введенном символе и какая команда сработала.
Была введена клавиша, но никакая команда не сработала. Информация о введенном символе.
б) Для сообщений перегрузить оператор вывода в поток. Таким образом можно выводить сообщение в различные потоки (cout, файл). При выводе в поток сообщения, должна формироваться строка и подставляться хранимая информация.
в) Разработать систему классов, которые отслеживают сообщения и выводят их в файл и/или консоль. Куда выводить запрашивается у пользователя при запуске программы: никуда, в файл, в консоль, в файл и консоль. Классы, в которых происходит отслеживаемое событие, должны только отправлять сообщение, но не знать куда, то есть только создают сообщение, инициализируя его информацию, и отправляют.
Примечания:
Система отслеживания должна масштабируема для новых потоков вывода без изменения кода. Для этого вывод в файл и терминал можно обернуть в отдельные классы с общим интерфейсом.
Для записи в файл придерживайтесь идиомы RAII
Отслеживаемые сущности не должны знать о том, кто и как их логирует.
№7* - Шаблонные классы
а) Создать шаблонный класс врага (не должен наследовать от события), который размещается на игровом поле и может по нему перемещаться и взаимодействовать с игроком. В качестве шаблонов указывается схема управления (то как двигается враг) и схема взаимодействия с игроком (то как враг взаимодействует на игрока)
б) Создать минимум 2 схемы управле2ния для врага. Например, враг, который ищет игрока и идет к нему, и враг, который случайно бродить по игровому полю.
в) Создать минимум 2 схемы взаимодействия врага в игроком. Например, враг наносящий урон и враг толкающий игрока.
г) Внедрить врагов на игровое поле, чтобы они совершали ход после хода игрока, а также взаимодействовали с игроком.
Примечания:
Схемы не должно иметь общий базовый класс. В данном работе применяется принцип статического полиморфизма через шаблоны.
Не забудь добавить добавление врагов на поле в классе создающих уровни.
№8* - Исключения
а) Реализуйте класс, который сохраняет информацию об игре в один файл. Информация должна быть такова, чтобы по ней можно было полностью восстановить состояние игрового поля и продолжить играть. Должна быть возможность произвести сохранение в любой момент по нажатию клавиши. Реализуйте и обрабатывайте исключение, если файл невозможно открыть на запись.
б) Реализуйте класс, который загружает игру из файла. Загрузку можно произвести во время запуска программы или уже во время игры по нажатию клавиши. Реализуйте и обрабатывайте исключения для следующих ситуаций при загрузке:
Файла не существует
Файл невозможно открыть на чтение
Файл с сохранением содержит некорректные данные, поэтому загрузка невозможно. Под каждый тип некорректности должно быть свое исключение
Примечания:
Исключения не обязательно должны иметь общий базовый тип
Исключения должны хранить информацию, которая может потом преобразована в сообщение (например, название файла, какие данные некорректны и их значения)
Исключения обрабатываются выше по уровню относительно их возбуждения
Обработка исключения не должна завершать программу.
Блок try-catch должен покрывать только те строчки кода, где может возникнуть исключение
Для проверки корректности можно рассчитывать хэш и также записывать его в файл
