object oriented – Tetris C ++ game

Hello, I am a student. This is my first application / project that I did and that I finished today in C ++ using OOP and I want to know your opinion and your suggestions. should I exclude comments about anything that can help me improve and improve my code. Also, to test the code, you will need a "tiles.in" file with this: https://pastebin.com/raw/P8ye8LfE because it's from there that I'm going to get it. have read all the tiles in the game. I have created a diagram UML file for a better understanding of the code. https://i.stack.imgur.com/n31Ag.png Thanks in advance.

#understand 
#understand 
#understand 
#understand 
#understand 
#understand 
#understand 
#understand 

#define numberOfColumns 11 // number of rows and columns for the gaming table
#define numberOfLines 21

using namespace std;

class Drawable // abstract class used to draw different tiles of the game or coordinates
{
protected:
static short x;
static short y;
public:
static int getX ();
static empty hidecursor ();
Static static MoveTo (short _x, short _y); // used to move to a specific coordinate in the console
virtual void DeleteDraw () = 0;
virtual void Draw () = 0;
};

Drawable short: x = 5; // represents the coordinates where the game table will be positioned in the console
Drawable court :: y = 25;

int Drawable :: getX ()
{
return x;
}

void Drawable :: hidecursor ()
{
CONSOLE_CURSOR_INFO info = {100, FALSE};
SetConsoleCursorInfo (GetStdHandle (STD_OUTPUT_HANDLE), & info);
}

void Drawable :: MoveTo (short _x, short _y)
{
COORD coord = {y + _y, x + _x};
SetConsoleCursorPosition (GetStdHandle (STD_OUTPUT_HANDLE), coord);
}

class Coordinates: public Drawable // class that represents a coordinate in the console (x, y)
{
private:
x short;
there is running;
static form of character; // the shape that each piece (dot) of each tile will have
public:
Coordinates (short x = 0, short y = 0);
Coordinates & operator = (const Coordin & coord);
// getter and setter
getX short ();
getY short ();
static char getForm ();
void setX (x short);
empty setY (short y);
// functions using coordinates (x, y)
void moveCoordinatesInADirection (char direction); // used to move the coordinates in a specific direction (right, left, bottom)
// Will be used to move each piece (point) of a tile in one direction
void DeleteDraw () override;
void Draw () override;
};

char Coordinates :: form = & # 39 ;;

Coordinates :: Coordinates (short x, short y)
{
this-> x = x;
this-> y = y;
}

Contact & Coordinates :: operator = (const Coordinates & coord)
{
if (this! = & coord)
{
this-> x = coord.x;
this-> y = coord.y;
this-> form = coord.form;
}
return * this;
}

Charts :: getForm ()
{
return form;
}

Short Contact :: getX ()
{
return x;
}

Short Contact :: getY ()
{
return there;
}

void Coordinates :: setX (short x)
{
this-> x = x;
}

void Coordinates :: setY (short y)
{
this-> y = y;
}

void Coordinates :: moveCoordinatesInADirection (character direction)
{
switch (direction)
{
box: // move to the left
y--;
Pause;
case: // go right
y ++;
Pause;
case's: // goes down
x ++;
Pause;
default:
Pause;
}
}

void Coordinates :: DeleteDraw ()
{
MoveTo (x + Drawable :: x, y + Drawable :: y); // Moves to the coordinates (x, y) and removes a piece (point) from a tile
cost << "";
}

void Coordinates :: Draw ()
{
MoveTo (x + Drawable :: x, y + Drawable :: y); // Moves to the coordinates (x, y) and draws a piece (point) from a tile
cost << form;
}


class Tile: public Drawable // class that represents a tile and all its methods
{
private:
CoordinTile Coordinates[4]; // any tile is composed of 4 coordinates and a center
centerOfTile short;
public:
Tile & operator = (const Tile & tile);
// getter and setter
getcenterOfTile short (short position);
getcoordX short (short position);
short getcoordY (short position);
void setcenterOfTile (short centerOfTile);
void setcoordX (short position, int x);
empty setcoordY (short position, int y);
// methods using a tile
void moveTileInADirection (character direction); // move the tile in a specific direction (right, left, down)
void rotateTileInADirection (character direction); // rotate the tile in a specific direction (right, left)
void DeleteDraw () override; // replace the DeleteDraw () function of Drawable () and is used to remove the tile from the game table
void Draw () override; // replace the Draw () function from Drawable () and is used to draw the tile in the game table
};

Tile & Tile :: operator = (Tile & tile const)
{
if (this! = & tile)
{
for (brief i = 0; i < 4; i++)
        {
            this->coordTile[i] = tile.coordTile[i];
}
}
return * this;
}

Short Tile :: getcoordX (short position)
{
back coordTile[position].getX ();
}

short tile :: getcoordY (short position)
{
back coordTile[position].getY ();
}

Short Tile :: getcenterOfTile (short position)
{
return centerOfTile;
}

void Tile :: setcoordX (short position, int x)
{
coordTile[position].setX (x);
}

Empty tile :: setcoordY (short position, int y)
{
coordTile[position].setY (y);
}

void Tile :: setcenterOfTile (short centerOfTile)
{
this-> centerOfTile = centerOfTile;
}

void Tile :: moveTileInADirection (character direction)
{
for (brief i = 0; i <4; i ++)
{
coordTile[i].moveCoordinatesInADirection (direction);
}
}

void Tile :: rotateTileInADirection (character direction)
{
short dir = 0;

switch (direction)
{
box 'e': // to rotate the tile to the right, we need + 90 * check check down
dir = 1;
Pause;
box # q ;: // to rotate the tile to the left, it takes -90 * check formula down
dir = -1;
Pause;
default:
return;
}

if (centerOfTile! = -1) // If the tile can be rotated
{
float centerOfTileX = coordTile[centerOfTile].getX ();
float centerOfTileY = coordTile[centerOfTile].getY ();

float tileX;
floating tile;

for (short i = 0; i <4; i ++) // we rotate each piece (point) of the tile with 90 * (right) or -90 * (left) depends on dir
{
tileX = coordTile[i].getX ();
tileY = coordTile[i].getY ();
coordTile[i].setX (round ((tileX - centerOfTileX) * cos ((90 * 3,14 * dir) / 180) + (tileY - centerOfTileY)) * sin ((90 * 3,14 * dir) / 180) + centerOfTileX) );
coordTile[i].setY (round ((centerOfTileX - tileX) * sin ((90 * 3,14 * dir) / 180) + (carrelY - centerOfTileY)) * cos ((90 * 3,14 * dir) / 180) + centerOfTileY) );
}
}
}

voile Tile :: DeleteDraw ()
{
for (brief i = 0; i <4; i ++)
{
coordTile[i].DeleteDraw (); // Remove the tile by deleting each piece (point)
}
}


empty tile :: Draw ()
{
for (brief i = 0; i < 4; i++)
    {
        coordTile[i].Draw();             // Drawing the tile by drawing every piece(point) of it
    }
}

class Tiles                       // class that represents the number of tiles the game has and all tiles
{
private:
    short numberOfTiles;
    Tile *figuri;
public:
    Tiles();
    Tile getTile(short number);
    short getNumberOfTiles();
    ~Tiles();
};

Tiles::Tiles()
{
    ifstream input("tiles.in");               // reading from a file the number of tiles and than the coordinates of each tile and setting the center for every tile
    input >> numberOfTiles;

figuri = new tile[numberOfTiles];
short auxiliary = 0;
short counter = 0;

for (brief i = 0; i <numberOfTiles; i ++)
{
counter = 0;
for (short j = 0; j <4; j ++)
{
for (short k = 0; k < 4; k++)
            {
                input >> auxiliaryVar;
if (auxiliaryVar! = 0)
{
figurine[i].setcoordX (counter, j);
figurine[i].setcoordY (counter, k);
counter ++;
if ((j == 1) && (k == 2))
{
figurine[i].setcenterOfTile (counter - 1);
}
}
}
}
}

figurine[0].setcenterOfTile (2);
figurine[3].setcenterOfTile (-1);
input.close ();
}

Tile Tiles :: getTile (short number)
{
return figuri[number];
}

Short tiles :: getNumberOfTiles ()
{
return number of tiles;
}

Tiles :: ~ Tiles ()
{
wipe off[] figurine;
}


class Table: public Drawable // class that represents the game table
{
private:
short table **; // the game table = a matrix with 0 s there is nothing drawn in this point and 1 s there is something drawn
long score;
Tile actualTile; // the tile that moves in the game table (the actual tile)
Tiles allTiles; // the actual tile will be chosen randomly from all possible tiles

public:
Table();
getScore long ();
void informationAboutGame ();
void generateRandomTile ();
void deleteLineFromTable (short line); // after a row of the table is completed, it will be removed from the game table and the score will increase
void moveTileDownAutomatically ();
void moveTileInADirection (character direction);
void possibleMoves (short & time); // possible shots of a player (right, left, down)
void positionTileInTableAfterRotation ();
void rotateTileInADirection (character direction);
void start ();
cancel DeleteDraw ();
empty Draw ();
bool belongsToActualTile (short x, short y);
boolean checkIfCanMoveInADirection (char direction);
bool checkIfPlayerLost ();
~ Table ();
};

Table :: Table ()
{
// create the game table and initialize the table

time_t t;
srand ((unsigned) (time (& t)));

score = 0;

table = new short *[numberOfLines];
for (short i = 0; i <numberOfLines, i ++)
{
table[i] = new short[numberOfColumns];
}

for (short i = 0; i <numberOfLines, i ++)
{
for (short j = 0; j <numberOfColumns; j ++)
{
table[i][j]    = 0;
}
}
}

long table :: getScore ()
{
return score;
}

void Table :: informationAboutGame ()
{
cost << " n  n  n  t This is a game of tetris and the controls for the game are:  n";
cout << " n  t a - move the tile to the left";
cout << " n  t d - move the tile to the right";
cout << " n  t s - move the tile down";
cout << " n  t e - rotate the tile to the right";
cout << " n  t q - rotate the tile to the left";
cout << " n  n  t When ready, press any key to start the game. Good luck!";
_getch ();
}

void Table :: generateRandomTile ()
{
// generate a random tile from all possible tiles and set its coordinates for the game table

random shortTile;
randomTile = rand ()% allTiles.getNumberOfTiles ();

actualTile = allTiles.getTile (randomTile);
actualTile.setcenterOfTile (allTiles.getTile (randomTile) .getcenterOfTile (randomTile));

for (brief i = 0; i < 4; i++)
    {
        actualTile.setcoordY(i, numberOfColumns / 2 - actualTile.getcoordY(i) + 2);
    }
}

void Table::deleteLineFromTable(short line) 
{
    // Deleting the line which is completed
    // This is done by replacing every line starting that line by the previous one
    for (short i = line; i > 0; I--)
{
for (short j = 0; j <numberOfColumns; j ++)
{
Drawable :: MoveTo (i + Drawable :: x, j + Drawable :: y);
if (table[i - 1][j]    == 0)
{
cost << "";
}
other {
cost << Coordinates :: getForm ();
}

table[i][j]    = table[i - 1][j];
}
}

for (short i = 0; i <numberOfColumns, i ++)
{
Drawable :: MoveTo (0 + Drawable :: x, i + Drawable :: y);
cost << "";
table[0][i]    = 0;
}
}

void Table :: moveTileDownAutomatically ()
{
// Move the real tile every 0.5 s down and check if the player wants to move (right, left, down) or rotate (right, left) the tile
actualTile.Draw ();

make {
short time = 1;

while (time <500)
{
if (_kbhit ()) // if the player presses a key on the keyboard
{
possibleMoves (time);
}

Sleep (1);
hour = hour + 1;
}

if (checkIfCanMoveInADirection (& # 39; s))
{
actualTile.DeleteDraw ();
moveTileInADirection (& # 39; s);
actualTile.Draw ();
}
other {
Pause;
}
} while (true);
}

void Table :: moveTileInADirection (character direction)
{
// To move the tile in one direction, we must:
// - remove the previous tile from the game table by putting 0
// - move the tile to the new coordinates
// - update the game table by putting 1 on his coordinates
for (brief i = 0; i <4; i ++)
{
table[actualTile.getcoordX(i)][actualTile.getcoordY(i)]    = 0;
}

actualTile.moveTileInADirection (direction);

for (brief i = 0; i <4; i ++)
{
table[actualTile.getcoordX(i)][actualTile.getcoordY(i)]    = 1;
}
}

void Table :: possibleMoves (short & time)
{
// Possible moves that can be made on a tile (move and rotate)
char direction = _getch ();

if (checkIfCanMoveInADirection (direction))
{
actualTile.DeleteDraw (); // delete the old tile
moveTileInADirection (direction); // move the tile in the direction desired by the player
actualTile.Draw (); // draw the new tile
if (direction == & # 39; s)
{
time = 1;
}
}
// check if the player wanted to rotate the tile (right, left)
if ((direction == e) || (direction == q q))
{
actualTile.DeleteDraw ();
rotateTileInADirection (direction);
actualTile.Draw ();
}
}

void Table :: positioningTileInTableAfterRotation ()
{
// This method is used to check and correct a tile if it goes out of the game table after a rotation.
short index = 0;
short ok = 1;

while (index <4)
{
if (actualTile.getcoordY (index) <0)
{
// pass the left limit of the game table
for (short j = 0; j < 4; j++)
            {
                actualTile.setcoordY(j, actualTile.getcoordY(j) + 1);
            }
            ok = 0;
        }

        if (actualTile.getcoordY(index) > numberOfColumns - 1)
{
// pass the right limit of the game table
for (short j = 0; j <4; j ++)
{
actualTile.setcoordY (j, actualTile.getcoordY (j) - 1);
}
ok = 0;
}

if (actualTile.getcoordX (index) <0)
{
// pass the upper limit of the game table and there are cases where the player loses
for (short j = 0; j <4; j ++)
{
actualTile.setcoordX (j, actualTile.getcoordX (j) + 1);
}

for (short j = 0; j < 4; j++)
            {
                if ((actualTile.getcoordX(j) > 0) && (table[actualTile.getcoordX(j)][actualTile.getcoordY(j)]    == 1))
{
start 0;
}
}
ok = 0;
}

if ((actualTile.getcoordX (index)> numberOfLines - 1) ||
(table[actualTile.getcoordX(index)][actualTile.getcoordY(index)]    == 1))
{
// past the lower limit or reaching a busy position
for (short j = 0; j <4; j ++)
{
actualTile.setcoordX (j, actualTile.getcoordX (j) - 1);
}
ok = 0;
}

if (ok == 0)
{
index = 0;
ok = 1;
}
other {
index ++;
}
}
}

void Table :: rotateTileInADirection (character direction)
{
// To rotate the tile in one direction, we must:
// - remove the previous tile from the game table by putting 0
// - move the tile to the new coordinates and adjust it so that it does not exceed the limits of the game table
// - update the game table by putting 1 on his coordinates
for (brief i = 0; i <4; i ++)
{
table[actualTile.getcoordX(i)][actualTile.getcoordY(i)]    = 0;
}

actualTile.rotateTileInADirection (direction);
positionTileInTableAfterRotation ();

for (brief i = 0; i <4; i ++)
{
table[actualTile.getcoordX(i)][actualTile.getcoordY(i)]    = 1;
}
}

void Table :: start ()
{
Drawable :: hidecursor ();
informationAboutGame ();

DeleteDraw ();
Draw();

short ok = 1;

while (true)
{
// This time ends when the player loses and the program ends
// check if a line is complete and must be deleted
for (short i = 0; i <numberOfLines, i ++)
{
ok = 1;

for (short j = 0; j <numberOfColumns; j ++)
{
if (table[i][j]    == 0)
{
ok = 0;
Pause;
}
}
if OK)
{
deleteLineFromTable (i);
score ++;
}
}

generateRandomTile ();

if (checkIfPlayerLost () == 1)
{
moveTileDownAutomatically ();
}
other {
Drawable :: MoveTo (numberOfLines + 1 + Drawable :: x, 0);
cost << " n" << "Good job, you did" << score * 1000 << "points.  n";
Pause;
}
}
}

void Table :: DeleteDraw ()
{
// Method used to delete the table
system ("cls");
}

void Table :: Draw ()
{
// Method used to draw the table
for (short i = -1; i <= numberOfLines; i ++)
{
MoveTo (i + Drawable :: x, -1 + Drawable :: y);
cost << car (219);
MoveTo (i + Drawable :: x, numberOfColumns + Drawable :: y);
cost << car (219);
}
for (short i = -1; i <= numberOfColumns; i ++)
{
Drawable :: MoveTo (-1 + Drawable :: x, i + Drawable :: y);
cost << car (219);
Drawable :: MoveTo (numberOfLines + Drawable :: x, i + Drawable :: y);
cost << car (219);
}
}

bool Table :: belongsToActualTile (short x, short y)
{
// Check if a piece (a point) of a tile is related to the actual tile
for (brief i = 0; i <4; i ++)
{
if ((actualTile.getcoordX (i) == x) && (actualTile.getcoordY (i) == y))
{
returns 0;
}
}

returns 1;
}

bool Table :: checkIfCanMoveInADirection (character direction)
{
for (brief i = 0; i <4; i ++)
{
switch (direction)
{
// Check if the player can move left
box: a:
if ((actualTile.getcoordY (i) - 1 < 0) ||
                ((belongsToActualTile(actualTile.getcoordX(i), actualTile.getcoordY(i) - 1)) &&
                (table[actualTile.getcoordX(i)][actualTile.getcoordY(i) - 1] == 1)))
            {
                return 0;
            }
            break;
            // Check if the player can move right
        case'd':
            if ((actualTile.getcoordY(i) + 1 > numberOfColumns - 1) ||
((apartToActualTile (actualTile.getcoordX (i), actualTile.getcoordY (i) + 1)) &&
(table[actualTile.getcoordX(i)][actualTile.getcoordY(i) + 1]    == 1)))
{
returns 0;
}
Pause;
// Check if the player can go down
case of & # 39:
if ((actualTile.getcoordX (i) + 1> numberOfLines - 1) ||
((belongsToActualTile (actualTile.getcoordX (i) + 1, actualTile.getcoordY (i)))) &&
(table[actualTile.getcoordX(i) + 1][actualTile.getcoordY(i)]    == 1)))
{
returns 0;
}
Pause;
default:
Pause;
}
}
returns 1;
}

bool Table :: checkIfPlayerLost ()
{
for (brief i = 0; i <4; i ++)
{
if (table[actualTile.getcoordX(i)][actualTile.getcoordY(i)]    == 1)
{
returns 0;
}
}

returns 1;
}

Table :: ~ Table ()
{
for (short i = 0; i <numberOfLines, i ++)
{
wipe off[] table[i];
}
wipe off[] table;
}

int main ()
{
Table a;
try {
a beginning();
}
capture (...) {
Drawable :: MoveTo (numberOfLines + 1 + Drawable :: getX (), 0);
cost << " n" << "Good job, you have created" << a.getScore () *) 1000 "points.  n";
}

returns 0;
}