Question
I'm trying again - Okay, I'm in need of some help - this is the code I have so far for a C++ project on
I'm trying again -
Okay, I'm in need of some help - this is the code I have so far for a C++ project on Tetris that uses the Visual Studio (which is why the #stdafx.h file is in the header). I need to add to this code to complete the tasks as listed in the assignment. Here's the assignment as I recieved it, followed by the code:
You have already displayed the Tetris Bucket, started dropping the shapes, stopped them at the bottom of the Bucket, dropped another shape from the top, got the user input and moved/rotated the shape in response to the user input.
In this assignment, you need to:
1. Determine whether any of the rows are complete.
2. If a row is complete, remove that line and drop all the shapes above the line by one cell.
3. Compute and display the score.
4. Add plenty of narrative comments. Your program must be compilable and executable.
#include "stdafx.h"
#include
#include
#include
#include
using namespace std;
#define GAME_INTERVAL 2
#define GO_DOWN 2
#define GO_LEFT 4
#define GO_RIGHT 6
#define GO_ROTATE 5
class TetrisShape
{
public:
char shapeArray[4][4];
int shapeTopLeftX = 6;
int shapeTopLeftY = 0;
void populateShapeArray(int shape);
void rotate();
template
void setShape(char(&shape)[rows][cols]);
TetrisShape(int shape) { populateShapeArray(shape); };
TetrisShape() {};
};
void TetrisShape::rotate()
{
char _shapeArray[4][4];
_shapeArray[0][0] = shapeArray[0][3]; _shapeArray[1][0] = shapeArray[0][2]; _shapeArray[2][0] = shapeArray[0][1]; _shapeArray[3][0] = shapeArray[0][0];
_shapeArray[0][1] = shapeArray[1][3]; _shapeArray[1][1] = shapeArray[1][2]; _shapeArray[2][1] = shapeArray[1][1]; _shapeArray[3][1] = shapeArray[1][0];
_shapeArray[0][2] = shapeArray[2][3]; _shapeArray[1][2] = shapeArray[2][2]; _shapeArray[2][2] = shapeArray[2][1]; _shapeArray[3][2] = shapeArray[2][0];
_shapeArray[0][3] = shapeArray[3][3]; _shapeArray[1][3] = shapeArray[3][2]; _shapeArray[2][3] = shapeArray[3][1]; _shapeArray[3][3] = shapeArray[3][0];
for (int _s = 0; _s < 4; _s++)
{
for (int _a = 0; _a < 4; _a++)
{
shapeArray[_s][_a] = _shapeArray[_s][_a];
}
}
}
void TetrisShape::populateShapeArray(int shape)
{
switch (shape)
{
case 1:
shapeArray[0][0] = ' '; shapeArray[1][0] = ' '; shapeArray[2][0] = ' '; shapeArray[3][0] = ' ';
shapeArray[0][1] = ' '; shapeArray[1][1] = 'X'; shapeArray[2][1] = ' '; shapeArray[3][1] = ' ';
shapeArray[0][2] = ' '; shapeArray[1][2] = 'X'; shapeArray[2][2] = ' '; shapeArray[3][2] = ' ';
shapeArray[0][3] = ' '; shapeArray[1][3] = 'X'; shapeArray[2][3] = 'X'; shapeArray[3][3] = ' ';
break;
case 2:
shapeArray[0][0] = ' '; shapeArray[1][0] = 'X'; shapeArray[2][0] = ' '; shapeArray[3][0] = ' ';
shapeArray[0][1] = ' '; shapeArray[1][1] = 'X'; shapeArray[2][1] = ' '; shapeArray[3][1] = ' ';
shapeArray[0][2] = ' '; shapeArray[1][2] = 'X'; shapeArray[2][2] = ' '; shapeArray[3][2] = ' ';
shapeArray[0][3] = ' '; shapeArray[1][3] = 'X'; shapeArray[2][3] = ' '; shapeArray[3][3] = ' ';
break;
case 3:
shapeArray[0][0] = ' '; shapeArray[1][0] = ' '; shapeArray[2][0] = ' '; shapeArray[3][0] = ' ';
shapeArray[0][1] = ' '; shapeArray[1][1] = 'X'; shapeArray[2][1] = ' '; shapeArray[3][1] = ' ';
shapeArray[0][2] = ' '; shapeArray[1][2] = 'X'; shapeArray[2][2] = 'X'; shapeArray[3][2] = ' ';
shapeArray[0][3] = ' '; shapeArray[1][3] = ' '; shapeArray[2][3] = 'X'; shapeArray[3][3] = ' ';
break;
case 4:
shapeArray[0][0] = ' '; shapeArray[1][0] = ' '; shapeArray[2][0] = ' '; shapeArray[3][0] = ' ';
shapeArray[0][1] = ' '; shapeArray[1][1] = ' '; shapeArray[2][1] = 'X'; shapeArray[3][1] = ' ';
shapeArray[0][2] = ' '; shapeArray[1][2] = 'X'; shapeArray[2][2] = 'X'; shapeArray[3][2] = ' ';
shapeArray[0][3] = ' '; shapeArray[1][3] = 'X'; shapeArray[2][3] = ' '; shapeArray[3][3] = ' ';
break;
case 5:
shapeArray[0][0] = ' '; shapeArray[1][0] = ' '; shapeArray[2][0] = ' '; shapeArray[3][0] = ' ';
shapeArray[0][1] = ' '; shapeArray[1][1] = ' '; shapeArray[2][1] = 'X'; shapeArray[3][1] = ' ';
shapeArray[0][2] = ' '; shapeArray[1][2] = ' '; shapeArray[2][2] = 'X'; shapeArray[3][2] = ' ';
shapeArray[0][3] = ' '; shapeArray[1][3] = 'X'; shapeArray[2][3] = 'X'; shapeArray[3][3] = ' ';
break;
case 6:
shapeArray[0][0] = ' '; shapeArray[1][0] = ' '; shapeArray[2][0] = ' '; shapeArray[3][0] = ' ';
shapeArray[0][1] = ' '; shapeArray[1][1] = ' '; shapeArray[2][1] = ' '; shapeArray[3][1] = ' ';
shapeArray[0][2] = ' '; shapeArray[1][2] = 'X'; shapeArray[2][2] = 'X'; shapeArray[3][2] = ' ';
shapeArray[0][3] = ' '; shapeArray[1][3] = 'X'; shapeArray[2][3] = 'X'; shapeArray[3][3] = ' ';
break;
}
}
int currentShape = -1; // this is the shape that is currently in play.
int x[4] = { -1, -1, -1, -1 };
int y[4] = { -1, -1, -1, -1 }; // the x, y location for each of the shapes.
bool isDropping = false; // gameTick globals.
int currentTick = 0;
template
void generateBucket(char(&bucket)[rows][cols]); // create the bucket
void generateShapeStream(); // shapes, in drop and in queue, constantly
void dropShape(); // drop the shape
bool moveShape(int direction); // GO_DOWN (falling)
template
bool gameTick(char(&bucket)[rows][cols], char(&perm_bucket)[rows][cols]); // handles game events
template
void landShape(char(&bucket)[rows][cols]); // shape hitting the bottom
template
void drawBucket(char(&bucket)[rows][cols]); // display bucket
int getUserInput(); // gets the key pressed from the user.
template
bool canEnter(int direction, char(&bucket)[rows][cols]); // is space available for the block
void setCursorTo(int x, int y); // set cursor to appropriate position
int previousX = 6, previousY = 0;
int shapes[256];
TetrisShape activeShape;
int main()
{
// set 2 buckets, one permanent and one for display
char bucket[12][25];
char _bucket[12][25];
int shapes[256] = {};
int shapeIndex = 0;
bool gameOver = false;
generateBucket(bucket);
generateBucket(_bucket);
generateShapeStream();
drawBucket(bucket);
while (!gameOver)
{
gameOver = gameTick(bucket, _bucket);
Sleep(500);
currentTick++;
}
setCursorTo(25, 6);
cout << "GAME OVER" << endl;
system("pause");
}
void setCursorTo(int x, int y)
{
HANDLE handle;
COORD position;
handle = GetStdHandle(STD_OUTPUT_HANDLE);
position.X = x;
position.Y = y;
SetConsoleCursorPosition(handle, position);
}
/* generateBucket */
template
void generateBucket(char(&bucket)[rows][cols])
{
for (int w = 0; w < 12; w++)
{
for (int z = 0; z < 25; z++)
{
if (((w == 0) || (w == 11)) && (z == 0))
{
bucket[w][z] = '.';
}
else if (((w % 12 == 0) || (w % 12 == 11)) && ((z > 0) && (z < 24)))
{
bucket[w][z] = '|';
}
else if (((w == 0) || (w == 11)) && (z == 24))
{
bucket[w][z] = '+';
}
else if (z == 24)
{
bucket[w][z] = '-';
}
else
{
bucket[w][z] = ' ';
}
}
}
}
/* generateShapeStream - generates the shapes preparing to fall */
void generateShapeStream()
{
// Initialize the random number generator
srand(time(NULL));
for (int p = 0; p < 256; p++)
{
shapes[p] = rand() % 6 + 1;
}
}
/* drawBucket -displays bucket and shapes to fall */
template
void drawBucket(char(&bucket)[rows][cols])
{
setCursorTo(0, 0);
for (int m = 0; m < 25; m++)
{
for (int k = 0; k < 12; k++)
{
cout << bucket[k][m];
}
cout << endl;
}
}
/* gameTick - everything happening in game, and game over procedures*/
template
bool gameTick(char(&bucket)[rows][cols], char(&perm_bucket)[rows][cols])
{
drawBucket(bucket);
if (!isDropping)
{
currentShape++;
activeShape = TetrisShape(shapes[currentShape]);
if (!canEnter(GO_DOWN, perm_bucket))
{
return true;
}
else
{
isDropping = true;
updateBucket(bucket, false);
}
}
else
{
if (currentTick % GAME_INTERVAL == 1)
{
// we are on a drop interval.
if (canEnter(GO_DOWN, perm_bucket))
{
updateBucket(bucket, moveShape(GO_DOWN));
}
else
{
landShape(perm_bucket);
}
}
}
int direction = getUserInput();
if (canEnter(direction, perm_bucket))
{
updateBucket(bucket, moveShape(direction));
}
if (!canEnter(GO_DOWN, perm_bucket))
{
landShape(perm_bucket);
}
return false;
}
/* moveShape - handles the shape dropping down. */
bool moveShape(int direction)
{
previousX = activeShape.shapeTopLeftX;
previousY = activeShape.shapeTopLeftY;
switch (direction)
{
case GO_DOWN:
activeShape.shapeTopLeftY++;
return false;
break;
case GO_RIGHT:
activeShape.shapeTopLeftX++;
return false;
break;
case GO_LEFT:
activeShape.shapeTopLeftX--;
return false;
break;
case GO_ROTATE:
activeShape.rotate();
return true;
break;
}
}
/* updateBucket - place new shape into bucket, and removing old shape*/
template
void updateBucket(char(&bucket)[rows][cols], bool isRotation)
{
for (int _l = 0; _l < 4; _l++)
{
for (int _g = 0; _g < 4; _g++)
{
if (!isRotation)
{
if ((activeShape.shapeArray[_l][_g] != ' ') && (bucket[_l + previousX][_g + previousY] != '|') && (bucket[_l + previousX][_g + previousY] != '-'))
{
bucket[_l + previousX][_g + previousY] = ' ';
}
}
else {
if ((bucket[_l + previousX][_g + previousY] != '|') && (bucket[_l + previousX][_g + previousY] != '-'))
{
bucket[_l + previousX][_g + previousY] = ' ';
}
}
}
}
for (int _l = 0; _l < 4; _l++)
{
for (int _g = 0; _g < 4; _g++)
{
if (activeShape.shapeArray[_l][_g] != ' ')
{
bucket[_l + activeShape.shapeTopLeftX][_g + activeShape.shapeTopLeftY] = activeShape.shapeArray[_l][_g];
}
}
}
}
/* landShape - Sets the shape in place once it hits the bottom of the bucket. Moves the shape to the permanent bucket (_bucket)*/
template
void landShape(char(&bucket)[rows][cols])
{
updateBucket(bucket, false);
previousX = 6; previousY = 0;
isDropping = false;
}
/* getUserInput - Reads the user input from the player*/
int getUserInput() {
setCursorTo(35, 9);
if ((GetKeyState(VK_DOWN) != 0) && (GetKeyState(VK_DOWN) != 1)) { return GO_DOWN; }
if ((GetKeyState(VK_RIGHT) != 0) && (GetKeyState(VK_RIGHT) != 1)) { return GO_RIGHT; }
if ((GetKeyState(VK_LEFT) != 0) && (GetKeyState(VK_LEFT) != 1)) { return GO_LEFT; }
if ((GetKeyState(VK_UP) != 0) && (GetKeyState(VK_UP) != 1)) { return GO_ROTATE; }
return 0;
}
/* canRotate - can we rotate? if we are adjacent to another shape NO! */
template
bool canRotate(char(&bucket)[rows][cols])
{
// creating a copy of the shape, rotating it so we can determine where in the bucket it will land.
TetrisShape _tmp = TetrisShape(activeShape);
_tmp.rotate();
for (int _t = 0; _t < 4; _t++)
{
for (int _z = 0; _z < 4; _z++)
{
if (_tmp.shapeArray[_t][_z] != ' ')
{
if (bucket[_tmp.shapeTopLeftX + _t][_tmp.shapeTopLeftY + _z] != ' ')
{
return false;
}
}
}
}
return true;
}
/* canEnter - Tests the direction in which a shape can enter*/
template
bool canEnter(int dir, char(&bucket)[rows][cols])
{
// Check for collisions between shapes or with the bucket
// Determining in which direction the shapes are moving
int delta_x = 0, delta_y = 0;
switch (dir)
{
case GO_DOWN:
delta_y++;
break;
case GO_LEFT:
delta_x--;
break;
case GO_RIGHT:
delta_x++;
break;
case GO_ROTATE:
return canRotate(bucket);
break;
}
// Create the starting {x, y} position to test for collision
int test_b = activeShape.shapeTopLeftX + delta_x;
int test_k = activeShape.shapeTopLeftY + delta_y;
for (int _b = 0; _b < 4; _b++)
{
for (int _k = 0; _k < 4; _k++)
{
if (activeShape.shapeArray[_b][_k] != ' ')
{
if (bucket[test_b + _b][test_k + _k] != ' ')
{
return false;
}
}
}
}
return true;
}
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started