Tetris Program

Hello everyone!

I am working on a Tetris game and there is one major issue that keeps occuring. Whenever I press the left key or right key to move the tetris shape, it leaves a trail. My code should work to get rid of the trail, but it isn't. Also, when I press the up key to rotate the shape, it cuts out some of the shape's blocks. It'd probably be easier to understand if you ran it.
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#include "stdafx.h"
#include <iostream>
#include <windows.h>
#include <string>
#include <cstdlib>
#include <ctime>
#include <conio.h>

using namespace std;

//Declaring globals
const int BUCKHEIGHT = 25;
const int BUCKWIDTH = 12;
//Setting up bucket width/height
char bucket[BUCKHEIGHT][BUCKWIDTH];
int newShapeTopLeftX, newShapeTopLeftY;
//Creating enum values to be used to move shapes
enum { UP_ARROW = 72, DOWN_ARROW = 80, LEFT_ARROW = 75, RIGHT_ARROW = 77 };
//Class creation where variables/functions within can only be used by class members
class TetrisShape {
public:
	char shapeArray[4][4];
	int shapeTopLeftX;
	int shapeTopLeftY;
	int shapeHeight;
	//Constructor to ensure that shapeTopLeftX is set to 6 upon object creation and shapeTopLeftY is 0
	TetrisShape() {
		shapeTopLeftX = 6;
		shapeTopLeftY = 0;

	}



	//Function that is passed a random number (between 0-6) via rand() and picks a random shape to display at top of screen
	void populateShapeArray(int shapeType) {
		/* shapeTopLeftX/Y are set to 6 and 0 once again to make sure that's where they're displayed
		on screen upon populateShapeArray function call in main */
		shapeTopLeftX = 6;
		shapeTopLeftY = 0;
		//Switch chooses random shape based on random shapeType number
		switch (shapeType)
		{
		case 0: // J shape
			shapeArray[0][0] = ' '; shapeArray[0][1] = ' '; shapeArray[0][2] = ' '; shapeArray[0][3] = ' ';
			shapeArray[1][0] = 'X'; shapeArray[1][1] = 'X'; shapeArray[1][2] = 'X'; shapeArray[1][3] = ' ';
			shapeArray[2][0] = ' '; shapeArray[2][1] = ' '; shapeArray[2][2] = 'X'; shapeArray[2][3] = ' ';
			shapeArray[3][0] = ' '; shapeArray[3][1] = ' '; shapeArray[3][2] = ' '; shapeArray[3][3] = ' ';
			shapeHeight = 3;
			break;
		case 1: // I shape
			shapeArray[0][0] = ' '; shapeArray[0][1] = ' '; shapeArray[0][2] = ' '; shapeArray[0][3] = ' ';
			shapeArray[1][0] = 'X'; shapeArray[1][1] = 'X'; shapeArray[1][2] = 'X'; shapeArray[1][3] = 'X';
			shapeArray[2][0] = ' '; shapeArray[2][1] = ' '; shapeArray[2][2] = ' '; shapeArray[2][3] = ' ';
			shapeArray[3][0] = ' '; shapeArray[3][1] = ' '; shapeArray[3][2] = ' '; shapeArray[3][3] = ' ';
			shapeHeight = 2;
			break;
		case 2: // L shape
			shapeArray[0][0] = ' '; shapeArray[0][1] = ' '; shapeArray[0][2] = ' '; shapeArray[0][3] = ' ';
			shapeArray[1][0] = 'X'; shapeArray[1][1] = 'X'; shapeArray[1][2] = 'X'; shapeArray[1][3] = ' ';
			shapeArray[2][0] = 'X'; shapeArray[2][1] = ' '; shapeArray[2][2] = ' '; shapeArray[2][3] = ' ';
			shapeArray[3][0] = ' '; shapeArray[3][1] = ' '; shapeArray[3][2] = ' '; shapeArray[3][3] = ' ';
			shapeHeight = 3;
			break;
		case 3: // [] shape
			shapeArray[0][0] = ' '; shapeArray[0][1] = ' '; shapeArray[0][2] = ' '; shapeArray[0][3] = ' ';
			shapeArray[1][0] = ' '; shapeArray[1][1] = 'X'; shapeArray[1][2] = 'X'; shapeArray[1][3] = ' ';
			shapeArray[2][0] = ' '; shapeArray[2][1] = 'X'; shapeArray[2][2] = 'X'; shapeArray[2][3] = ' ';
			shapeArray[3][0] = ' '; shapeArray[3][1] = ' '; shapeArray[3][2] = ' '; shapeArray[3][3] = ' ';
			shapeHeight = 3;
			break;
		case 4: // S shape
			shapeArray[0][0] = ' '; shapeArray[0][1] = ' '; shapeArray[0][2] = ' '; shapeArray[0][3] = ' ';
			shapeArray[1][0] = ' '; shapeArray[1][1] = 'X'; shapeArray[1][2] = 'X'; shapeArray[1][3] = ' ';
			shapeArray[2][0] = 'X'; shapeArray[2][1] = 'X'; shapeArray[2][2] = ' '; shapeArray[2][3] = ' ';
			shapeArray[3][0] = ' '; shapeArray[3][1] = ' '; shapeArray[3][2] = ' '; shapeArray[3][3] = ' ';
			shapeHeight = 3;
			break;
		case 5: // T shape
			shapeArray[0][0] = ' '; shapeArray[0][1] = ' '; shapeArray[0][2] = ' '; shapeArray[0][3] = ' ';
			shapeArray[1][0] = 'X'; shapeArray[1][1] = 'X'; shapeArray[1][2] = 'X'; shapeArray[1][3] = ' ';
			shapeArray[2][0] = ' '; shapeArray[2][1] = 'X'; shapeArray[2][2] = ' '; shapeArray[2][3] = ' ';
			shapeArray[3][0] = ' '; shapeArray[3][1] = ' '; shapeArray[3][2] = ' '; shapeArray[3][3] = ' ';
			shapeHeight = 3;
			break;
		case 6: // Z shape
			shapeArray[0][0] = ' '; shapeArray[0][1] = ' '; shapeArray[0][2] = ' '; shapeArray[0][3] = ' ';
			shapeArray[1][0] = 'X'; shapeArray[1][1] = 'X'; shapeArray[1][2] = ' '; shapeArray[1][3] = ' ';
			shapeArray[2][0] = ' '; shapeArray[2][1] = 'X'; shapeArray[2][2] = 'X'; shapeArray[2][3] = ' ';
			shapeArray[3][0] = ' '; shapeArray[3][1] = ' '; shapeArray[3][2] = ' '; shapeArray[3][3] = ' ';
			shapeHeight = 3;
			break;

		}
	}
};
//end of TetrisShape class

//Function that keeps the container in one spot at all times as the shape(s) go downward
void setCursorTo(int x, int y)
{
	HANDLE handle;
	COORD position;
	handle = GetStdHandle(STD_OUTPUT_HANDLE);
	position.X = x;
	position.Y = y;
	SetConsoleCursorPosition(handle, position);
}
//Creates the proper shape of the bucket
void initBucket() {
	for (int i = 0; i < BUCKHEIGHT; i++) {
		for (int j = 0; j < BUCKWIDTH; j++) {
			if (i == BUCKHEIGHT - 1 || j == 0 || j == BUCKWIDTH - 1) {
				bucket[i][j] = '#';
			}
			else {
				bucket[i][j] = ' ';
			}
		}
	}
}
//Uses the initBucket bucket creator to display it using nested for loops and cout
void dispBucket() {
	setCursorTo(0, 0);
	for (int i = 0; i < BUCKHEIGHT; i++) {
		for (int j = 0; j < BUCKWIDTH; j++) {
			cout << bucket[i][j];
		}
		cout << endl;
	}
}
//Helps to display new shape on screen and where to put it
void updateBucket(TetrisShape localTetrisShape, int shapeTopLeftX, int shapeTopLeftY) {
	for (int i = 0; i < localTetrisShape.shapeHeight; i++) {
		for (int j = 0; j < 4; j++) {
			bucket[i + shapeTopLeftY][j + shapeTopLeftX] = localTetrisShape.shapeArray[i][j];

		}
	}



}


bool isStuck(TetrisShape localTetrisShape)
{
	//This first part checks to see if the dropping tetris shape hits another shape. If so, it will return true, which stops the shape
	for (int j = 0; j < 4; j++)
	{
		int i = localTetrisShape.shapeHeight - 1;
		if (bucket[localTetrisShape.shapeTopLeftY + i][localTetrisShape.shapeTopLeftX + (j - 1)] == 'X') {
			return true;
		}
	}

	//This part checks to see if the shape has hit the bottom of the bucket, and if it has, it stops; otherwise, shape continues downward
	if (localTetrisShape.shapeTopLeftY + localTetrisShape.shapeHeight >= BUCKHEIGHT)
	{
		return true;
	}
	else
	{
		return false;
	}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
void dropRow(TetrisShape tetShape) {
	//Check to see if bottom row is full
	for (int j = 1; j <= BUCKWIDTH - 1; j++) {
		if (bucket[24][j] == 'X') { //If bottom row is full of X's, replace with ' ' spots
			bucket[24][j] == ' ';
			for (int i = 1; i < BUCKHEIGHT - 2; i++) { //selects all shapes above deleted row and drops them down one spot
				for (int k = 1; k < BUCKWIDTH; k++) {
					bucket[i++][k++];
				}
			}
		}

	}

	//If full, drop shapes above BUCKHEIGHT - 1

}



//Used when the UP_ARROW enum value is pressed. Shape rotates based on element value placements
void rotateShape(TetrisShape& currentShape) {
	char tempCellVal = currentShape.shapeArray[0][0];
	currentShape.shapeArray[0][0] = currentShape.shapeArray[0][3];
	currentShape.shapeArray[0][3] = currentShape.shapeArray[3][3];
	currentShape.shapeArray[3][3] = currentShape.shapeArray[3][0];
	currentShape.shapeArray[3][0] = tempCellVal;

	tempCellVal = currentShape.shapeArray[0][1];
	currentShape.shapeArray[0][1] = currentShape.shapeArray[1][3];
	currentShape.shapeArray[1][3] = currentShape.shapeArray[3][2];
	currentShape.shapeArray[3][2] = currentShape.shapeArray[2][0];
	currentShape.shapeArray[2][0] = tempCellVal;

	tempCellVal = currentShape.shapeArray[0][2];
	currentShape.shapeArray[0][2] = currentShape.shapeArray[2][3];
	currentShape.shapeArray[2][3] = currentShape.shapeArray[3][1];
	currentShape.shapeArray[3][1] = currentShape.shapeArray[1][0];
	currentShape.shapeArray[1][0] = tempCellVal;

	tempCellVal = currentShape.shapeArray[1][1];
	currentShape.shapeArray[1][1] = currentShape.shapeArray[1][2];
	currentShape.shapeArray[1][2] = currentShape.shapeArray[2][2];
	currentShape.shapeArray[2][2] = currentShape.shapeArray[2][1];
	currentShape.shapeArray[2][1] = tempCellVal;
}

void newShapeSpot(TetrisShape shape, int xAxis, int yAxis) {
	if (RIGHT_ARROW) {
		xAxis++;
		
		newShapeTopLeftX = xAxis - 1;
	}
	if (LEFT_ARROW) {
		xAxis--;
		newShapeTopLeftX = xAxis - 1;
	}
	if (DOWN_ARROW) {
		yAxis++;
		newShapeTopLeftY = yAxis - 1;
	}
	else {
		yAxis++;
	}
}


int main() {

	TetrisShape shape; //Creates an object, which also starts up the TetrisShape constructor
	bool hitBottom = false; //Set to false to continue shape drop
	bool gameOver = false; //Set to false to keep the game loop repeating until gameOver = true
	initBucket(); //Call to initialize tetris bucket
	srand(time(0)); //Sets random seed to ensure values passed to populateShapeArray function are truly random
	int random = rand() % 7; //Variable set equal to a random value, which is passed to populateShapeArray function
	shape.populateShapeArray(random); //Call to populate shape array, which puts the shape at the top of the bucket
	int input = 0; //Initializing an input value, which is used later to decide shape movement based on keys pressed
	int score = 0;
	int newShapeTopLeftY;
	//Game loop
	while (gameOver == false) {

		updateBucket(shape, shape.shapeTopLeftX, shape.shapeTopLeftY); //Updates empty bucket with a randomly generated shape

		shape.shapeTopLeftY++; //Ensures that the shape drops downward on the Y axis

		score += 10;
		//Gets key entry and does specified action based on specific user key entry
		if (_kbhit())
		{
			input = _getch();

			switch (input) {
			case UP_ARROW:
				rotateShape(shape);


				break;

			case DOWN_ARROW:
				shape.shapeTopLeftY++;
				newShapeTopLeftX = shape.shapeTopLeftX;
				newShapeTopLeftY = shape.shapeTopLeftY - 1;
				newShapeSpot(shape, newShapeTopLeftX, newShapeTopLeftY);
				break;

			case LEFT_ARROW:
				shape.shapeTopLeftX--;
				newShapeTopLeftX = shape.shapeTopLeftX - 1;
				newShapeTopLeftY = shape.shapeTopLeftY;
				newShapeSpot(shape, newShapeTopLeftX, newShapeTopLeftY);

				break;

			case RIGHT_ARROW:
				shape.shapeTopLeftX++;
				newShapeTopLeftX = shape.shapeTopLeftX;
				newShapeTopLeftY = shape.shapeTopLeftY;
				newShapeSpot(shape, newShapeTopLeftX, newShapeTopLeftY);

				break;

			}



		}
		dropRow(shape);
		hitBottom = isStuck(shape); //Sets isStuck(shape) to false, which makes the shape move downward on Y axis
									//Statement that decides that if isStuck(shape) is true, then it needs to stop, and a new shape needs to be generated
		if (hitBottom == true) {
			score += 20;
			random = rand() % 7;
			shape.populateShapeArray(random);
			hitBottom = false;
		}

		cout << "Score: " << score;
		dispBucket(); //Displays the new bucket 


		Sleep(300); //Changes the rate of speed at which the shape drops on the Y axis. The higher the number, the slower the speed and vice versa
	}
	return 0;
}
Topic archived. No new replies allowed.