Лабы по ООП 2023 / Baraeva_Elizaveta_lb2
.docМИНОБРНАУКИ РОССИИ
Санкт-Петербургский государственный
электротехнический университет
«ЛЭТИ» им. В. И. Ульянова (Ленина)
Кафедра МО ЭВМ
отчет
по лабораторной работе №2
по дисциплине «Объектно-ориентированное программирование»
Тема: Конструкторы и деструкторы
Студентка гр. 2383 |
|
Бараева Е. Н. |
Преподаватель |
|
Жангиров Т. Р. |
Санкт-Петербург
2023
Цель работы.
Создание класса клетки игрового поля, класса игрового поля для дальнейших передвижений игрока по этому полю. Редактирование класса управления игрока для добавления взаимодействия игрока с полем.
Задание.
а) Создать класс клетки игрового поля. Клетка игрового поля может быть проходимой или нет, тем самым определяя возможность игрока встать на эту клетку. Возможность задать проходимость клетки должна быть реализована через конструктор и через метод клетки. В будущем в клетке будет храниться указатель на интерфейс события.
б) Создать класс игрового поля. Игровое поле представляет собой прямоугольник из клеток (двумерный массив). В учебных целях, клетки хранятся как чистый массив на указателях (использовать контейнеры stl запрещено в этой лаб. работе). Размер поля передается в конструктор поля, в котором динамически выделяется память под массив клеток. Также должна быть возможность вызвать конструктор поля без аргументов. Так как происходит выделение память, то необходимо реализовать деструктор в котором будет происходить очистка память.
Также добавить в игровое поле добавьте информацию о входе (где в начале появляется игрок) и выходе (куда игрок должен дойти)
Также для класса поля необходимо реализовать конструкторы копирования и перемещения, а также соответствующие им операторы присваивания.
в) В класс управления игрока добавить взаимодействия с полем. При перемещении игрока должна быть проверка на проходимость клетки, если клетка непроходима, то перемещение не должно производиться.
Примечания:
Так как в клетке будет храниться указатель, то при копировании и перемещении должен быть предусмотрен механизм копирования объекта, хранящегося по указателю.
Убедитесь, что присутствует проверка контроля размера поля, чтобы его нельзя было сделать слишком маленьким или с отрицательными размерами.
В конструкторе перемещения и соответствующем ему операторе присваивания не должно происходить никакого копирования данных.
Через класс поля должен быть доступ к каждой индивидуальной клетке. Создавать метод, который возвращает указатель на весь массив или указатель на каждую клетку, плохая практика, так как появляется возможность очистки памяти.
Выполнение работы.
Class Cell
В данном классе были созданы приватное поле клетки: passability. Также был объявлен конструктор, который выставляет значение в приватное поле, передаваемое в конструктор, или по умолчанию. Для взаимодействия с полем у класса есть метод GetPassability, возвращающий значения поля, и SetPassability, изменяющие поле.
Class Field
Перед классом создана структура CellCoordinates для удобного хранения координат.
В данном классе были созданы приватные поля для координат входа и выхода, длина и высота поля и сам массив клеток. Также был объявлен конструктор, который инициализирует поля переданными данными, выделяет память для массива клеток и проверяет на корректность длину и высоту поля. Конструктор очищает память, выделенную в конструкторе. Также были созданы конструкторы копирования и перемещения, а также соответствующие им операторы присваивания. В конструкторе копирования и операторе присваивания была выделена новая память под массив клеток и скопированы значения, перенесены значения остальных полей. В конструкторе перемещения и операторе присваивания были скопированы значения полей, передан указатель на массив клеток, и у other были выставлены нулевые значения и обнулен указатель.
Метод GetCell принимает координаты и возвращает ссылку на клетку, проверяя можно ли вообще обратиться к ней.
В методе Move класса Controller было добалено взаимодействие с клеткой. Добавлена проверка на возможность сделать шаг в каком-либо напрвалении.
Разработанный программный код см. в приложении А.
Тестирование.
Результаты тестирования представлены в табл. 1.
Таблица 1 – Результаты тестирования
№ п/п |
Входные данные |
Выходные данные |
Комментарии |
1. |
Field p1(110, 110); Field p2(120, 120); Field p3 = p1; // конструктор копирования p2 = p1; // оператор копирования Field p4(140, 140); Field p5 = std::move(p4); // конструктор перемещения Field p6(160, 160); p6 = Field(); // оператор перемещения |
|
Проверка конструкторов копирования и перемещения, а также соответствующие им операторы присваивания. Верно. |
2. |
Cell kletka(true); kletka.SetPassability(false); |
|
Проверка создания клетки. Верно. |
Вывод.
Были изучены основные управляющие конструкции языка С++ для программирования в объектно-ориентированном стиле, создан класс игрового поля, класс клетки, реализованы методы для работы с характеристиками поля, а также добавлено взаимодействие с полем в класс управления игроком.
ПРИЛОЖЕНИЕ А ИСХОДНЫЙ КОД ПРОГРАММЫ
Название файла: Field.h
#ifndef OOP_FIELD_H
#define OOP_FIELD_H
#include "Cell.h"
struct CellCoordinates{
int x;
int y;
};
class Field {
private:
Cell** game_field = nullptr;
int height;
int length;
CellCoordinates entry;
CellCoordinates exit;
public:
explicit Field(int height = 100, int length = 100);
~Field();
Field(const Field& x) noexcept;
Field& operator=(Field& x);
Field(Field&& other) noexcept;
Field& operator=(Field&& other) noexcept;
void CheckSize(int height, int length) const;
Cell& GetCell(int x, int y) const;
};
#endif //OOP_FIELD_H
Название файла: Field.cpp
#include "Field.h"
#include <iostream>
#define MIN_FIELD 10
#define MAX_FIELD 500
Field::Field(int height, int length): height{height}, length{length}, entry({0, 0}), exit({height - 1, length - 1}){
CheckSize(height, length);
game_field = new Cell*[height];
for(int i = 0; i < height; i++)
game_field[i] = new Cell[length];
}
Field::~Field(){
for(int i = 0; i < height; i++)
delete[] game_field[i];
delete[] game_field;
game_field = nullptr;
}
Field::Field(const Field& x) noexcept: height{x.height}, length{x.length}, entry{x.entry}, exit{x.exit}, game_field{new Cell*[x.height]} {
for(int i = 0; i < height; i++)
game_field[i] = new Cell[length];
for(int i = 0; i < height; i++) {
for(int j = 0; j < length; j++)
game_field[i][j] = x.game_field[i][j];
}
}
Field& Field::operator=(Field& x){
if (this != &x){
delete[] game_field;
height = x.height;
length = x.length;
entry = x.entry;
exit = x.exit;
game_field = new Cell*[height];
for(int i = 0; i < height; i++)
game_field[i] = new Cell[length];
for(int i = 0; i < height; i++) {
for(int j = 0; j < length; j++)
game_field[i][j] = x.game_field[i][j];
}
}
return *this;
}
Field::Field(Field&& other) noexcept{
game_field = other.game_field;
height = other.height;
length = other.length;
entry = other.entry;
exit = other.exit;
other.game_field = nullptr;
other.height = 0;
other.length = 0;
other.entry = {-1, -1};
other.exit = {-1, -1};
}
Field& Field::operator=(Field&& other) noexcept{
if (this != &other){
for(int i = 0; i < height; i++)
delete[] game_field[i];
delete[] game_field;
game_field = other.game_field;
height = other.height;
length = other.length;
entry = other.entry;
exit = other.exit;
other.game_field = nullptr;
other.height = 0;
other.length = 0;
other.entry = {-1, -1};
other.exit = {-1, -1};
}
return *this;
}
void Field::CheckSize(int checked_height, int checked_length) const{
if (checked_length <= MIN_FIELD || checked_height <= MIN_FIELD || checked_length > MAX_FIELD || checked_height > MAX_FIELD)
throw std::invalid_argument("Размеры поля заданы неверно");
}
Cell& Field::GetCell(int x, int y) const{
if (x >= 0 && x < length && y >= 0 && y < height)
return game_field[y][x];
else
throw std::out_of_range("Координаты клетки выходят за границы поля");
}
Название файла: Cell.h
#ifndef OOP_CELL_H
#define OOP_CELL_H
#include "Event.h"
class Cell {
private:
bool passability;
// Event* event;
public:
explicit Cell(bool passab = true);
void SetPassability(bool value);
bool GetPassability() const;
};
#endif //OOP_CELL_H
Название файла: Cell.cpp
#include "Cell.h"
Cell::Cell(bool passab): passability{passab} {}
void Cell::SetPassability(bool value){
passability = value;
}
bool Cell::GetPassability() const{
return passability;
}
