Конструктор по умолчанию




Конструктор по умолчанию — это конструктор без параметров. Если он не задан явно и при этом не создано других конструкторов с параметрами, то конструктор по умолчанию создастся автоматически. При этом все свойства нового объекта не будут никак проинициализированы (получат «мусорные» значения из памяти).

Копирующий конструктор

Часто при создании нового объекта бывает удобным инициализировать его поля теми же значениями, что уже имеются у какого-то существующего объекта того же типа. Проще говоря, создавая новый объект порой удобно создать его как копию уже существующего. Конструктор, который в качестве аргумента принимает другой объект того же типа — называется копирующим конструктором. Обычно аргумент копирующего конструктора объявляется как ссылка на константу, чтобы копия никак не влияла на оригинал.

Статические члены класса

Члены класса, объявленные с модификатором доступа static, называются статическими членами класса. Статические поля и методы доступны без создания объекта данного класса. Доступ к статическому элементу осуществляется с использованием оператора принадлежности::, а не через имя экземпляра класса с точкой.

Статические методы могут вызывать и использовать только другие статические методы и статические переменные. Из статического метода нельзя выполнять вызов не статического метода класса.

Статическую переменную можно рассматривать как аналог глобальной переменной, которая связана с конкретным классом.

Часто статические переменные называют переменными класса, а «не статические» переменные — переменными экземпляра. Для статических переменных могут использоваться указатели.

Указатель this

Указатель this — это константный указатель на текущий объект (т. е. на объект, к которому применяется вызываемый метод). Этот указатель существует всюду внутри класса, его не надо как-то явно объявлять, к нему можно обращаться внутри любого метода класса.

Предположим, что в классе у нас есть поле с именемf и есть метод, который к этому свойству должен обращаться, но в котором имеется локальная переменная с тем же именем f. Указательthis поможет одновременно использовать поле и локальную переменную: через указатель поле будет доступно как this->f.Пример:

ClassExample {

private:

float f; // Какое-то поле класса

public:

void func(float f) {

this->f = f;

}

};

Данные у каждого объекта свои, а методы класса общие для всех объектов. Указатель this помогает, определить с данными какого объекта будет работать метод.

Разыменовав указатель this можно получить ссылку на объект.

Перегрузка операторов

ВС++ можно создавать методы со специальными именами вида: operator *, где * — это один из существующих операторов языка (например, +, -, /, *, = и т.д.).

При создании такого метода, говорят, что оператор * был перегружен, т.е. теперь его можно использовать для взаимодействия с объектами создаваемого класса. Перегружать можно многие, но не любые операторы.

Вызывать этот метод можно обращаясь к нему по указанному символу (в данном случае, *). При этом аргументом метода будет считаться объект стоящий справа от символа, а вызываться метод будет для объекта, стоящего слева от символа.

Так, например, удобно для объектов своего класса использовать символ + в качестве метода, складывающего объекты, вместо именованного метода (например, sum).

Перегрузка операторов, как и перегрузка функций в целом, реализует принцип полиморфизма.

Структура программы

Исходный текст программы хранится в 5-х файлах: tetris.cpp, main.cpp, tetris.h, Console.cpp, Console.h.

 
Название файла Содержимое  
tetris.cpp Функция main и 2 функции класса tetris - PutArea и Randomize - перекрывшие виртуальные функции класс Main  
main.cpp реализация классов ConsoleиTetris  
tetris.h определения констант, описание используемых структур данных, интерфейс классов Tetris и Console  
Console.cpp    
Console.h    
     

Проверка программы

Проверка работоспособности программы осуществляется в следующих случаях:

- независание фигуры при падении;

- падение фигуры до дна ящика;

- невыход фигуры за границы ящика;

- сдвиг фигуры и поворот её на расстоянии от стенок;

- сдвиг фигуры вблизи стенки и поворот её (при этом не должно происходить наложение фигуры на границу ящика);

- неналожение фигуры при достижении лежащих на дне ящика других фигур;

- изъятие слоя, не содержащего пустых ячеек (все ячейки заполнены квадратами фигур);

- "оседание" слоев при изъятии слоя, не содержащего пустых ячеек;

- окончание игры при заполнении ящика или по команде игрока.

Описание и обоснование выбора метода организации данных:

В соответствии с принципами объектно-ориентированного программирования в программе данные организованы в несколько объектов:

- ящик:

#ifndef TETRIS_H

#define TETRIS_H

 

#include <windows.h>

 

class Figure;

 

class Matrix {

public:

Matrix();

 

enum {

Size = 20

};

 

bool IsFull() const;

 

bool CaneMoveLeft(const Figure &figure) const;

bool CaneMoveRight(const Figure &figure) const;

bool CaneRotate(const Figure &figure) const;

 

bool IsDown(const Figure &figure) const;

void AddFigure(const Figure &figure);

intGetFullRow() const;

void DeleteRow(int row);

 

void DebugDraw(int x, int y) const;

 

private:

char m_matix[Size][Size];

};

 

enumFigureRotate {

FIGURE_ROTATE_0 = 0,

FIGURE_ROTATE_90,

FIGURE_ROTATE_180,

FIGURE_ROTATE_270

};

 

class Figure {

public:

Figure();

 

enum {

Size = 4

};

 

void SetRandomType();

 

void SetDrawXY(int x, int y) { m_drawCoord.X = x; m_drawCoord.Y = y; };

void Draw(bool black = false) const;

 

void MoveDown() { m_coord.Y++; };

void MoveLeft() { m_coord.X--; };

void MoveRight() { m_coord.X++; };

 

void Rotate();

void SetRotate(FigureRotate rotate) { m_rotate = rotate; };

FigureRotateGetRotate() const { return m_rotate; }

 

WORD GetFigure() const { return Figures[m_type][m_rotate]; };

 

void SetXY(int x, int y) { m_coord.X = x; m_coord.Y = y; };

COORD GetXY() const { return m_coord; };

 

void operator=(const Figure &figure);

 

private:

enumFigureType {

FIGURE_TYPE_I = 0,

FIGURE_TYPE_J,

FIGURE_TYPE_L,

FIGURE_TYPE_O,

FIGURE_TYPE_S,

FIGURE_TYPE_T,

FIGURE_TYPE_Z,

};

 

enum {

FigureCount = 7,

FigureRotateCount = 4

};

 

static const WORD Figures[FigureCount][FigureRotateCount];

static const WORD FigureColors[FigureCount];

 

FigureTypem_type;

FigureRotatem_rotate;

COORD m_coord;

COORD m_drawCoord;

};

 

class TetrisGame {

public:

TetrisGame();

 

void Play();

};

 

#endif

Создание интерфейса

Начальный интерфейс выполняется тремя функциями:

а) вывод и движение слева на право зеленного окна;

б) падение на окно фигуры;

в) движение и развертывание выбора трех вариантов скорости.

Интерфейс рабочей области игры обеспечивает процедура класса Tetris, осуществляющая вывод квадрата фигуры или пустой ячейки на экран.

Ввод данных с клавиатуры

При первоначальном старте программы, во время движения фигур по экрану, можно прекратить выполнение, нажатием любой клавиши. После вывода на экран трех вариантов скорости, ее выбор осуществляется нажатием клавиши клавиатуры, номер которой она соответствует.

Подтверждение ввода клавишей Enter не требуется.

Далее на экране появляется ящик с падающими фигурами. Управление игрой осуществляется следующими клавишами:

 
Название клавиши Выполняемая функция  
Стрелка вправо Сдвиг фигуры вправо  
Стрелка влево Сдвиг фигуры влево  
Стрелка вверх Поворот фигуры вокруг собственной оси по часовой стрелке  
Enter Падение фигуры до дна ящика  
ESC Окончание игры  
     

Игру можно прекратить в любое время клавишей Esc, после ее нажатия открывается диалоговое окно выбора вариантов скорости, повторный Esc окончательный выход из программы.

Обработка данных

После выбора варианта скорости игры программа циклически опрашивает клавиатуру и генерирует новую фигуру: voidFigure(void) с использованием генератора случайных чисел вычисляется номер фигуры в списке фигур и цвет фигуры (iAttribute), проверяется наложение: если ящик полон (Check(GET_CUBE)==

BE_SUPERPOSITION), то новая фигура появиться не может, и переменной состояния присваивается значение "конец игры": iStatus=BE_END.

Если ящик не заполнен (iStatus=BE_FREE), на экран выводится новая фигура (iStatus=BE_FALL). Определяем наложение фигуры и заполненные строки(Check(SET_CUBE)), если заполненных строк нет - генерируем новую(iStatus=BE_NEW), есть - удаляем строку, перерисовываем экран и генерируем новую фигуру (iStatus=BE_NEW).

Проектная часть

Постановка задачи

Цель работы: Разработать программу в среде C++, прорисовывающую графический объект и реализующую возможность управляемого перемещения, с использованием основных средств ООП в соответствии с заданием.

Программа должна выполнять в общем три задачи:

1. Прорисовка объекта.

2. Перемещение объекта по экрану.

3. Взаимодействие объектов между собой.

Все полученные результаты отобразить на экране.

Название игры: Тетрис

Правила игра: Случайные фигурки тетрамино падают сверху в прямоугольный стакан. В полёте игрок может поворачивать фигурку на 90° и двигать её по горизонтали. Также можно «сбрасывать» фигурку, то есть ускорять её падение, когда уже решено, куда фигурка должна упасть. Фигурка летит до тех пор, пока не наткнётся на другую фигурку либо на дно стакана. Если при этом заполнился горизонтальный ряд, он пропадает и всё, что выше него, опускается на одну клетку. Дополнительно показывается фигурка, которая будет следовать после текущей — это подсказка, которая позволяет игроку планировать действия. Темп игры постепенно увеличивается. Игра заканчивается, когда новая фигурка не может поместиться в стакан. Игрок получает очки за каждый заполненный ряд, поэтому его задача — заполнять ряды, не заполняя сам стакан (по вертикали) как можно дольше, чтобы таким образом получить как можно больше очков.

Взаимосвязь классов:

               
   
Класс-потомок Console
 
     
Класс-потомок Tetris
 
   
Класс-потомок Tetris
 
 

 


Программирование задачи

В языке С++ формат описания класса выглядит следующим образом:

Class<имя класса>

{

элементы класса

<метка видимости>:< элементы класса>

<метка видимости>:< элементы класса>

};

объекты класса

 

Синтаксис объявления класса-потомка следующий:

Class base1

{…….};

Class baseN

{…….};

Class potomok:<спецификатордоступа> base1, baseN

Реализация

1)Для начала создаем форму.


В Unit1.h

 

#ifndef TETRIS_H

#define TETRIS_H

 

#include <windows.h>

 

class Figure;

 

class Matrix {

public:

Matrix();

 

enum {

Size = 20

};

 

bool IsFull() const;

 

bool CaneMoveLeft(const Figure &figure) const;

bool CaneMoveRight(const Figure &figure) const;

bool CaneRotate(const Figure &figure) const;

 

bool IsDown(const Figure &figure) const;

void AddFigure(const Figure &figure);

intGetFullRow() const;

void DeleteRow(int row);

 

void DebugDraw(int x, int y) const;

 

private:

char m_matix[Size][Size];

};

 

enumFigureRotate {

FIGURE_ROTATE_0 = 0,

FIGURE_ROTATE_90,

FIGURE_ROTATE_180,

FIGURE_ROTATE_270

};

 

class Figure {

public:

Figure();

 

enum {

Size = 4

};

 

void SetRandomType();

 

void SetDrawXY(int x, int y) { m_drawCoord.X = x; m_drawCoord.Y = y; };

void Draw(bool black = false) const;

 

void MoveDown() { m_coord.Y++; };

void MoveLeft() { m_coord.X--; };

void MoveRight() { m_coord.X++; };

 

void Rotate();

void SetRotate(FigureRotate rotate) { m_rotate = rotate; };

FigureRotateGetRotate() const { return m_rotate; }

 

WORD GetFigure() const { return Figures[m_type][m_rotate]; };

 

void SetXY(int x, int y) { m_coord.X = x; m_coord.Y = y; };

COORD GetXY() const { return m_coord; };

 

void operator=(const Figure &figure);

 

private:

enumFigureType {

FIGURE_TYPE_I = 0,

FIGURE_TYPE_J,

FIGURE_TYPE_L,

FIGURE_TYPE_O,

FIGURE_TYPE_S,

FIGURE_TYPE_T,

FIGURE_TYPE_Z,

};

 

enum {

FigureCount = 7,

FigureRotateCount = 4

};

 

static const WORD Figures[FigureCount][FigureRotateCount];

static const WORD FigureColors[FigureCount];

 

FigureTypem_type;

FigureRotatem_rotate;

COORD m_coord;

COORD m_drawCoord;

};

 

class TetrisGame {

public:

TetrisGame();

 

void Play();

};

 

#endif

__fastcall TForm1(TComponent* Owner);

};

//---------------------------------------------------------------------------

Вигреиспользуютсяобъекты. Фишки реализуются в объекте, клетки игровой доски тоже реализуются объектом, сама доска является потомком клетки и имеет свойства доски.

Для того чтобы создать игровую доску, я сначала создаю клетку в классе “TCells - Клетка”. Voidinit (_size) -это метод, устанавливает размер клеток.

Intsize-свойство, хранит размер клеток.


class TCells

{

private:

void init (_size);

intsize;

};

//---------------------------------------------------------------------------

Класс “TDoska- Доска” будет производным(потомок) от класса “TCells-Клетка”. Я рисую игровую доску с помощью функции draw, в которую ничего не передается. Эта игровая доска размером 12:12, зеленого цвета. В данном примере функции TDoska(),draw() объявлены как private, т.е. как частные.

TDoska()-конструктор – устанавливает значение размера клетки.

Init-Устанавливает размер клетки, в данном случае 30.

voiddraw() метод рисует доску белого цвета.

Чтоб нарисовать квадрат и выбрать для него цвет на форме используем свойство Canvas. Оно имеет тип TCanvas. У этого типа есть целый ряд методов, которые позволяют рисовать различные примитивы, выводить текст, показывать картинки из файла и др.

С помощью Brush->Color и Rectangle рисуем квадрат выбираем для него зеленый цвет.

 



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2018-03-19 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: