-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtetris.cpp
More file actions
337 lines (325 loc) · 15.7 KB
/
tetris.cpp
File metadata and controls
337 lines (325 loc) · 15.7 KB
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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
// HEADER FILES USED
#include <iostream>
#include <vector>
#include <random>
#include <conio.h>
#include <windows.h> // header file for gotoxy
#include <stdio.h> //header file for standard input output
#include <dos.h>
#include <time.h>
using namespace std;
COORD coord={0,0}; //center of axis is set to the top left cornor of the screen
void gotoxy(int x,int y) // gotoxy function
{
coord.X=x;
coord.Y=y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),coord);
}
int getRandom() // random function
{
int random;
srand(time(NULL)); // giving time as input
random = rand()%7; // for random number b/w 0-6
return random; // return random number
}
// VARIABLES DECLARATION
int block[][4]={{ 0, 0, 0, 0 },{ 0, 0, 0, 0 },{ 0, 0, 0, 0 },{ 0, 0, 0, 0 }};
int stage[32][21]={};
int field[32][21]={};
int x = 8, y = 0; // coordinate
bool gameover = false; // check whether game is over or not
long long int GAMESPEED = 25000; // determines game speed
int score = 0,old_score=0; // calculate score
int high_score = 0; // to maintain high score
int block_list[7][4][4]= // blocks
{
{{ 0, 1, 0, 0 },
{ 0, 1, 0, 0 },
{ 0, 1, 0, 0 },
{ 0, 1, 0, 0 }}, // line
{{ 0, 0, 0, 0 },
{ 0, 1, 1, 0 },
{ 0, 1, 0, 0 },
{ 0, 1, 0, 0 }}, // inverted L
{{ 0, 0, 1, 0 },
{ 0, 1, 1, 0 },
{ 0, 1, 0, 0 },
{ 0, 0, 0, 0 }}, // rotated Z
{{ 0, 1, 0, 0 },
{ 0, 1, 1, 0 },
{ 0, 0, 1, 0 },
{ 0, 0, 0, 0 }}, // rotated S
{{ 0, 0, 0, 0 },
{ 0, 1, 0, 0 },
{ 1, 1, 1, 0 },
{ 0, 0, 0, 0 }}, // inverted T
{{ 0, 0, 0, 0 },
{ 0, 1, 1, 0 },
{ 0, 1, 1, 0 },
{ 0, 0, 0, 0 }}, // block
{{ 0, 0, 0, 0 },
{ 0, 1, 1, 0 },
{ 0, 0, 1, 0 },
{ 0, 0, 1, 0 }} // mirrored of inverted L
};
// FUNCTIONS USED
int gameOver(); // displays game over
void title(); // displays title tetris
void gameLoop(); // runs game
void display(); // display game board
bool makeBlocks(); // make blocks
void initGame(); // initializes game
void moveBlock(int, int); // move blocks
void collidable(); // fix the block
bool isCollide(int, int); // check collisions
void userInput(); // takes input from user
bool rotateBlock(); // rotates the block
void spawnBlock(); // moves block down
void speed(); // increases the speed
// MAIN FUNCTION
int main() // main function
{
title(); // calls title function
gameLoop(); // calls gameLoop function
return 0;
}
void title() // title function
{
system("cls"); // clears screen
cout << "================================================================================\n\n\n\n\n\n"
"\t\t####### ####### ####### ###### ### #####\n" // C++ merges separate constant strings automatically
"\t\t # # # # # # # #\n"
"\t\t # # # # # # #\n"
"\t\t # ##### # ###### # #####\n"
"\t\t # # # # # # #\n"
"\t\t # # # # # # # #\n"
"########\t # ####### # # # ### #####\t\t########\n\n\n"
"\n\n\n\n"
"================================================================================\n";
getch(); // displays tetris till user press any key
}
int gameOver() // gameOver function
{
system("cls"); // clears screen
cout << "\n\n\n\n"
"\t ##### # # # ####### ####### # # ####### ######\n"
"\t# # # # ## ## # # # # # # # #\n"
"\t# # # # # # # # # # # # # # #\n"
"\t# #### # # # # # ##### # # # # ##### ######\n"
"\t# # ####### # # # # # # # # # #\n"
"\t# # # # # # # # # # # # # #\n"
"\t ##### # # # # ####### ####### # ####### # #\n"
"\n\n\n\n";
cout<<"\t\t\t\tYour score is : "<<score; // displays score
cout<<"\n\n\n";
char ch;
cout<<"\t\t\tWant to start new game {y/n}: ";
cin>>ch;
if(ch=='y'){ // starts new game
gameover = false;
score = 0;
GAMESPEED = 25000;
old_score=0;
gameLoop();
}
}
void gameLoop() // gameLoop function
{
int time = 0;
initGame(); // initializes game
while(!gameover) // check whether game is over or not
{
if (kbhit()) // function to determine if key is pressed or not
userInput(); // calls function to take user input
if (time < GAMESPEED) // for by default down
time++;
else
{
spawnBlock(); // move the block down
time = 0;
}
}
}
void initGame() // initGame function
{
for(int i=0;i<=30;i++) // loop for number of rows
{
for(int j=0;j<=19;j++) // loop for number of columns
{
if((j==0)||(j==19)||(i==30)) // check for border and base
field[i][j] = stage[i][j] = 9;
else // remaining part of board
field[i][j] = stage[i][j] = 0;
}
}
makeBlocks(); // calls makesBlocks function
display(); // calls display function
}
void display() // display function
{
system("cls"); // clears the screen
cout<<"\n\n\n\n\t\t Your Score : "<<score<<"\t\t Highest Score : "<<high_score;// displays score & high_score
int a=10;
for (int i = 0; i < 31; i++) // loop for rows
{
gotoxy(32,a); // for starting position of row
a++; // updates row
for (int j = 0; j < 20; j++) // loop for column
{
switch (field[i][j])
{
case 0: cout<<" "<<flush; // for empty space
break;
case 9: cout<<"X"<<flush; // for border and base
break;
default: cout<<"#"<<flush; // for filled part
break;
}
}
cout<<endl;
}
cout << "\n\n\n\t\tA: left\tS: down\tD: right \t Rotation[Space]"; // for instructions
if (gameover) // check for game over
gameOver(); // calls gameOver function
}
bool makeBlocks() // makeBlocks function
{
x = 8; // for middle of game
y = 0; // for random block
int blockType = getRandom();
for (int i = 0; i < 4; i++) // loop for block
{
for (int j = 0; j < 4; j++)
{
block[i][j] = 0;
block[i][j] = block_list[blockType][i][j];
}
}
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
field[i][j + x] = stage[i][j + x] + block[i][j]; // copying block to field
if (field[i][j + x] > 1) // collision occurs
{
gameover = true; // denotes game over
return true;
}
}
}
return false;
}
void moveBlock(int x2, int y2) // moveBlock function
{
for (int i = 0; i < 4; i++) // remove block
for (int j = 0; j < 4; j++)
field[y + i][x + j] -= block[i][j];
x = x2; // update coordinates
y = y2;
for (int i = 0; i < 4; i++) // assign a block with the updated value
for (int j = 0; j < 4; j++)
field[y + i][x + j] += block[i][j];
display(); // calls display function
}
void collidable() // collidable function
{
int c=1,k=29;
for(int i=29;i>=0;i--) // for each row
{
c=1;
for(int j=0;j<20;j++) // for each column
{
if(field[i][j]==0) // check for the empty space in a line
{
c=0;
break;
}
}
if(c==0) // empty space found then copy as it is else don't do anything
{
for(int j=0;j<20;j++)
stage[k][j] = field[i][j]; // copying after eliminating filled lines
k--;
}
}
for (int i = 0; i<31; i++)
for (int j = 0; j<20; j++)
field[i][j] = stage[i][j]; // copying final field then
score += 10; // increase of 5 for fixing each block
score += (k+1)*20; // increase of 10 for removal of each line
if(k>=1) // if lines removed are more than one
score += 20; // then increase the score by 20
if(score> high_score) // updates high score if possible
high_score = score;
speed(); // calls speed function
}
bool isCollide(int x2, int y2) // check for collisions
{
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
if (block[i][j] && stage[y2 + i][x2 + j] != 0)
return true; // if collision then return true
return false; // else remove false
}
void spawnBlock() // spawn block function
{
if (!isCollide(x, y + 1)) // check for collision
moveBlock(x, y + 1); // if no collision then move the block down
else // else fix it
{
collidable(); // fix the block
makeBlocks(); // make new block
display(); // display it
}
}
void speed() // speed function
{
if(score - old_score >=200 )
{
old_score += 200;
GAMESPEED -= 5000; // increases speed
}
}
void userInput() // user input function
{
char key;
key = getch();
switch (key)
{
case 'd': if (!isCollide(x + 1, y)) // move right if(no collision
moveBlock(x + 1, y); // move it
break;
case 'a': if (!isCollide(x - 1, y)) // move left if no collision
moveBlock(x - 1, y); // move it
break;
case 's': if (!isCollide(x, y + 1)) // move down if no collision
moveBlock(x, y + 1); // move it
break;
case ' ': rotateBlock(); // rotate the block
}
}
bool rotateBlock() // rotate block function
{
int tmp[4][4];
for (int i = 0; i < 4; i++) // Save temporarily block
for (int j = 0; j < 4; j++)
tmp[i][j] = block[i][j];
for (int i = 0; i < 4; i++) // rotate
for (int j = 0; j < 4; j++)
block[i][j] = tmp[3 - j][i]; // rotates clockwise
if (isCollide(x, y))
{ // And stop if it overlaps not to be rotated
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
block[i][j] = tmp[i][j];
return true; // rotation occurs
}
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
{
field[y + i][x + j] -= tmp[i][j]; // remove original block
field[y + i][x + j] += block[i][j]; // adds rotated block
}
display(); // calls display function
return false;
}