Alright, I am in college started last year for programming in C++.
Not even a year ago, I took fundamentals which was basically pseudocode and flow charts.
3 months ago, I finished my programming 1 class and this 11 week quarter is my Programming 2 class.

Well the final project, in which the teacher gave us only 2 weeks to complete was a complete working Tetris game in a win32 console.

First off, I am having trouble with just the borders, considering we have only learned basics of arrays, multi dimensional arrays, inheritence, a bunch of other simple stuff as well.

I looked on google for some tetris code to get an idea of what I am looking at, and its close to 1k lines of code in which I dont understand what is going on.

Does anyone think this is a bit to much for what I know, as I think it is?
Or is there an easier way to program this and I have no idea what it is.

Let me know what you all think.

BTW great site, I have found LOTS of useful info on here!

Glad to hear that you like Daniweb! It does sound like quite a task for a 2 week project. There is a game development forum here that may be able to help you out: http://www.daniweb.com/forums/forum71.html

It seems to me like the key will be to identify the intersection of the bottom of the falling piece with the top of every piece that has already fallen. When this intersection happens, stop the piece, drop the next piece, and update the "tops of all of the fallen pieces" data. This actually shouldn't be too bad since the game is inherently discrete.

Good luck!

Dave

Thanks for the fast response, and I had no idea that game dev section was even on here, Ill definitely haver to check it out and see whats in there. Thanks again.

The easiest approach that I could think of is to have:

1. 4x4 array to store current falling piece.
2. Height x Width array to store all information of pieces that have fallen.
3. Variables to store position of falling piece inside Height x Width array
4. Function to check collision between falling piece and fallen pieces.
5. Timer to update position of falling piece every second.

Not my code but maybe you can get ideas from it.

``````//TETRIS
#include <iostream>
#include <ctime>
#include <conio.h>
#include <windows.h>
using namespace std;
enum
{
KEY_ESC     = 27,
ARROW_UP    = 256 + 72,
ARROW_DOWN  = 256 + 80,
ARROW_LEFT  = 256 + 75,
ARROW_RIGHT = 256 + 77
};
//int timer (double t);
void clrscr();
void setscreensize();
void insertblock ( int array[][20], int array2[][4] );
void changeblock ( int array[][4] );
void displayo ( int matrix[10][20], int full );
void seta ( int array[][20] );
void gotoxy ( int x, int y );
void display ( int matrix[][20] );
bool canmove ( int array[][20], int arrayblock[0][4], int xblockx, int yblocky, int direction );
int playgame(); // This is what brings it all together into one big, happy, functional, family
int getkeypress();
int checkforfullrow ( int array[][20], int scr );
int rotate_array ( int array[][4] );
int board[10][20];  //board
int blockpreview[4][4] = {0}; //block on preview
int block[4][4] = {0};//block
int blocky = -1; //y location of the block
int blockx = 3;
int score = 0, level;
double timeitvl = .5;
//////////////////////////////////////////////////////////////
int main()
{
cout << "WELCOME TO TETRIS";
cin.get();
clrscr();
score = playgame();
clrscr();
cout << "You failed on level " << level << ". " << "Your score is: " << score << ".";
cin.get();
}
//////////////////////////////////////////////////////////////
//Timer Function
int timer ( double t )
{
double start = double ( clock() ) / 1000, end = double ( clock() ) / 1000;
for ( double dif = 0;dif <= t;dif = end - start )
{
end = double ( clock() ) / 1000;
}
}

//new block function
void changeblock ( int array[][4] )
{
for ( int y = 0;y < 4;y++ )
{
for ( int x = 0;x < 4;x++ )
{
array[x][y] = 0;
}
}
srand ( time ( NULL ) );
int r = ( rand() % 6 );
switch ( r )
{
case ( 0 ) :
{
array[1][1] = 2;
array[2][1] = 2;
array[2][2] = 2;
array[3][2] = 2;
break;
}
case ( 1 ) :
{
array[1][2] = 2;
array[2][2] = 2;
array[2][1] = 2;
array[3][1] = 2;
break;
}
case ( 2 ) :
{
array[1][1] = 2;
array[1][2] = 2;
array[2][1] = 2;
array[2][2] = 2;
break;
}
case ( 3 ) :
{
array[0][1] = 2;
array[1][1] = 2;
array[2][1] = 2;
array[3][1] = 2;
break;
}
case ( 4 ) :
{
array[1][1] = 2;
array[2][1] = 2;
array[3][1] = 2;
array[1][2] = 2;
break;
}
case ( 5 ) :
{
array[1][2] = 2;
array[2][2] = 2;
array[2][1] = 2;
array[3][2] = 2;
break;
}
default:
{
array[1][1] = 2;
array[2][1] = 2;
array[3][1] = 2;
array[3][2] = 2;
break;
}
}
//display the block in appropriate location
for ( int y = 0;y < 4;y++ )
{
for ( int x = 0;x < 4;x++ )
{
gotoxy ( x, y + 6 );
if ( array[x][y] == 2 )
{
cout << '#';
}
else
{
cout << ' ';
}
}
}

}
//insert Function
void insertblock ( int array[][20], int array2[][4] )
{
for ( int y = 0; y < 20;y++ )
{
for ( int x = 0;x < 10;x++ )
{
if ( array[x][y] == 2 )
{
array[x][y] = 0;
}
}
}
for ( int y = 0;y < 4;y++ )
{
for ( int x = 0;x < 4;x++ )
{
if ( array2[x][y] == 2 )
{
array[x+blockx][y+blocky] = array2[x][y];
}
}
}
}
//turn function
int rotate_array ( int array[][4] )
{
int new_array[4][4];
for ( int y = 0;y < 4;y++ )
{
for ( int x = 0;x < 4;x++ )
{
new_array[abs ( y-3 ) ][x] = array[x][y];
}
}
for ( int y = 0;y < 4;y++ )
{
for ( int x = 0;x < 4;x++ )
{
array[x][y] = new_array[x][y];
}
}
}
//set function
void seta ( int array[][20] )
{
for ( int y = 0; y < 20;y++ )
{
for ( int x = 0;x < 10;x++ )
{
if ( array[x][y] == 2 )
{
array[x][y] = 1;
}
}
}
blockx = 3;
blocky = -1;
}
//getkeypress
int getkeypress()
{
int ch;
ch = getch();
if ( ch == 0 || ch == 224 )
{
ch = 256 + getch();
}
switch ( ch )
{
case ARROW_UP:
{
return 4;
break;
}
case ARROW_DOWN:
{
return 1;
break;
}
case ARROW_LEFT:
{
return 2;
break;
}
case ARROW_RIGHT:
{
return 3;
break;
}
default:
{
return -1;
break;
}
}
}

//canmove
bool canmove ( int array[][20], int arrayblock[0][4], int xblockx, int yblocky, int direction )
{
int r = 1, movedown = 0, moveright = 0, array2[4][4], xxx = xblockx, yyy = yblocky;
for ( int y = 0;y < 4;y++ )
{
for ( int x = 0;x < 4;x++ )
{
array2[x][y] = arrayblock[x][y];
}
}
switch ( direction )
{
case ( 1 ) :
{
movedown = 1;
break;
}
case ( 2 ) :
{
moveright = -1;
break;
}
case ( 3 ) :
{
moveright = 1;
break;
}
case ( 4 ) :
{
rotate_array ( array2 );
break;
}
case ( 5 ) : //checks if a new block can be made
{
changeblock ( array2 );
xxx = 3;
yyy = 0;
break;
}
}
for ( int y = 0;y < 4;y++ )
{
for ( int x = 0;x < 4;x++ )
{
if ( array2[x][y] == 2 && ( array[xxx+x+moveright][yyy+y+movedown] == 1 || yyy + y + movedown > 19 || xxx + x + moveright > 9 || xxx + x + moveright < 0 ) )
{
r = 0;
}
}
}
return r;
}
//check for full row
int checkforfullrow ( int array[][20], int scr )
{
scr = 0;
int rowy = 1;
for ( ;rowy != 0; )
{
rowy = 0;
for ( int y = 0;y < 20;y++ )
{
if ( array[0][y] == 1 )
{
for ( int x = 0;x < 10;x++ )
{
if ( array[x][y] == 0 )
{
break;
}
if ( array[x][y] == 1 && x == 9 )
{
rowy = y;
scr = scr + 10;
}
}
}
}
if ( rowy != 0 )
{
for ( int y = rowy;y > 0;y-- )
{
for ( int x = 0;x < 10;x++ )
{
array[x][y] = array[x][y-1];
}
}
}
}
return scr;
}
/////// The new display function
void display ( int matrix[][20], int full )
{
gotoxy ( 5, 0 );
cout << "PRAISE THE ALMIGHTY TETRIS";
for ( int y = 2;y < 22;y++ )
{
gotoxy ( 11, y );
cout << '.';
gotoxy ( 22, y );
cout << '.';
}
for ( int x = 0;x < 12;x++ )
{
gotoxy ( x + 11, 1 );
cout << ':';
gotoxy ( x + 11, 22 );
cout << ':';
}
for ( int y = blocky - 1;y < 5 + blocky;y++ )
{
if ( y < 20 && y >= 0 )
{
for ( int x = blockx - 1;x < 5 + blockx;x++ )
{
if ( x < 10 && x >= 0 )
{
if ( matrix[x][y] == 1 || matrix[x][y] == 2 )
{
gotoxy ( x + 12, y + 2 );
cout << '#';
}
else
{
gotoxy ( x + 12, y + 2 );
cout << ' ';
}
}
}
}
}
if ( full == 1 )
{
for ( int y = 0;y < 20;y++ )
{
for ( int x = 0;x < 10;x++ )
{
if ( matrix[x][y] == 1 || matrix[x][y] == 2 )
{
gotoxy ( x + 12, y + 2 );
cout << '#';
}
else
{
gotoxy ( x + 12, y + 2 );
cout << ' ';
}
}
}
}
gotoxy ( 0, 3 );
cout << "score: " << score;
gotoxy ( 0, 4 );
cout << "level: " << level;
gotoxy ( 0, 5 );
cout << "Next: " ;
gotoxy ( 22, 22 );
}
int playgame()
{
changeblock ( blockpreview );
while ( canmove ( board, block, blockx, blocky, 5 ) ) // While a new block can be created
{
for ( int y = 0;y < 4;y++ )
{
for ( int x = 0;x < 4;x++ )
{
block[x][y] = blockpreview[x][y];
}
}
changeblock ( blockpreview );
insertblock ( board, block );
display ( board, 1 );
while ( canmove ( board, block, blockx, blocky, 1 ) ) //while the block can move down
{
blocky = blocky + 1;
insertblock ( board, block );
display ( board, 0 );
double start = double ( clock() ) / 1000, end = double ( clock() ) / 1000;
while ( end - start < timeitvl ) //pause between blocks falling
{
if ( kbhit() )
{
int kp = getkeypress();
if ( kp != -1 && canmove ( board, block, blockx, blocky, kp ) )
{
if ( kp == 1 )
{
blocky++;
}
else if ( kp == 2 )
{
blockx--;
}
else if ( kp == 3 )
{
blockx++;
}
else if ( kp == 4 )
{
rotate_array ( block );
}
insertblock ( board, block );
display ( board, 0 );
}
}
end = double ( clock() ) / 1000;
}
}
seta ( board );
score = checkforfullrow ( board, score ) + score;
level = score / 100;
timeitvl = .1 + 1.0 / ( double ( level + 2 ) );
display ( board, 0 );
}
return score;
}
////////////////////////////////////////////////////////////////////////////////////////
// These Functions I just copied and pasted, though the gotoxy one I understand mostly//
// I get lost trying to follow clscr one                                              //
////////////////////////////////////////////////////////////////////////////////////////
void gotoxy ( int x, int y )
{
COORD coord;
coord.X = x;
coord.Y = y;
SetConsoleCursorPosition ( GetStdHandle ( STD_OUTPUT_HANDLE ), coord );
}
void clrscr()
{
COORD coordScreen = { 0, 0 };
DWORD cCharsWritten;
CONSOLE_SCREEN_BUFFER_INFO csbi;
DWORD dwConSize;
HANDLE hConsole = GetStdHandle ( STD_OUTPUT_HANDLE );

GetConsoleScreenBufferInfo ( hConsole, &csbi );
dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
FillConsoleOutputCharacter ( hConsole, TEXT ( ' ' ), dwConSize,
coordScreen, &cCharsWritten );
GetConsoleScreenBufferInfo ( hConsole, &csbi );
FillConsoleOutputAttribute ( hConsole, csbi.wAttributes, dwConSize,
coordScreen, &cCharsWritten );
SetConsoleCursorPosition ( hConsole, coordScreen );
}``````

iamthwee, I don't know if you feel the same as I feel. I think it would be neater if you attach this code in .cpp file than "copy-paste" here.

iamthwee... doesn't compile in Visual Studio 2010. I had to make a few minor changes. Here's the revised code.

``````//TETRIS
#include <iostream>
#include <ctime>
#include <conio.h>
#include <windows.h>
using namespace std;
enum
{
KEY_ESC     = 27,
ARROW_UP    = 256 + 72,
ARROW_DOWN  = 256 + 80,
ARROW_LEFT  = 256 + 75,
ARROW_RIGHT = 256 + 77
};
//int timer (double t);
void clrscr();
void setscreensize();
void insertblock ( int array[][20], int array2[][4] );
void changeblock ( int array[][4] );
void displayo ( int matrix[10][20], int full );
void seta ( int array[][20] );
void gotoxy ( int x, int y );
void display ( int matrix[][20] );
bool canmove ( int array[][20], int arrayblock[1][4], int xblockx, int yblocky, int direction );
int playgame(); // This is what brings it all together into one big, happy, functional, family
int getkeypress();
int checkforfullrow ( int array[][20], int scr );
void rotate_array ( int array[][4] );
int board[10][20];  //board
int blockpreview[4][4] = {0}; //block on preview
int block[4][4] = {0};//block
int blocky = -1; //y location of the block
int blockx = 3;
int score = 0, level;
double timeitvl = .5;
//////////////////////////////////////////////////////////////
int main()
{
cout << "WELCOME TO TETRIS";
cin.get();
clrscr();
score = playgame();
clrscr();
cout << "You failed on level " << level << ". " << "Your score is: " << score << ".";
cin.get();
}
//////////////////////////////////////////////////////////////
//Timer Function
void timer ( double t )
{
double start = double ( clock() ) / 1000, end = double ( clock() ) / 1000;
for ( double dif = 0;dif <= t;dif = end - start )
{
end = double ( clock() ) / 1000;
}
}

//new block function
void changeblock ( int array[][4] )
{
for ( int y = 0;y < 4;y++ )
{
for ( int x = 0;x < 4;x++ )
{
array[x][y] = 0;
}
}
srand ( time ( NULL ) );
int r = ( rand() % 6 );
switch ( r )
{
case ( 0 ) :
{
array[1][1] = 2;
array[2][1] = 2;
array[2][2] = 2;
array[3][2] = 2;
break;
}
case ( 1 ) :
{
array[1][2] = 2;
array[2][2] = 2;
array[2][1] = 2;
array[3][1] = 2;
break;
}
case ( 2 ) :
{
array[1][1] = 2;
array[1][2] = 2;
array[2][1] = 2;
array[2][2] = 2;
break;
}
case ( 3 ) :
{
array[0][1] = 2;
array[1][1] = 2;
array[2][1] = 2;
array[3][1] = 2;
break;
}
case ( 4 ) :
{
array[1][1] = 2;
array[2][1] = 2;
array[3][1] = 2;
array[1][2] = 2;
break;
}
case ( 5 ) :
{
array[1][2] = 2;
array[2][2] = 2;
array[2][1] = 2;
array[3][2] = 2;
break;
}
default:
{
array[1][1] = 2;
array[2][1] = 2;
array[3][1] = 2;
array[3][2] = 2;
break;
}
}
//display the block in appropriate location
for ( int y = 0;y < 4;y++ )
{
for ( int x = 0;x < 4;x++ )
{
gotoxy ( x, y + 6 );
if ( array[x][y] == 2 )
{
cout << '#';
}
else
{
cout << ' ';
}
}
}

}
//insert Function
void insertblock ( int array[][20], int array2[][4] )
{
for ( int y = 0; y < 20;y++ )
{
for ( int x = 0;x < 10;x++ )
{
if ( array[x][y] == 2 )
{
array[x][y] = 0;
}
}
}
for ( int y = 0;y < 4;y++ )
{
for ( int x = 0;x < 4;x++ )
{
if ( array2[x][y] == 2 )
{
array[x+blockx][y+blocky] = array2[x][y];
}
}
}
}
//turn function
void rotate_array ( int array[][4] )
{
int new_array[4][4];
for ( int y = 0;y < 4;y++ )
{
for ( int x = 0;x < 4;x++ )
{
new_array[abs ( y-3 ) ][x] = array[x][y];
}
}
for ( int y = 0;y < 4;y++ )
{
for ( int x = 0;x < 4;x++ )
{
array[x][y] = new_array[x][y];
}
}
}
//set function
void seta ( int array[][20] )
{
for ( int y = 0; y < 20;y++ )
{
for ( int x = 0;x < 10;x++ )
{
if ( array[x][y] == 2 )
{
array[x][y] = 1;
}
}
}
blockx = 3;
blocky = -1;
}
//getkeypress
int getkeypress()
{
int ch;
ch = _getch();
if ( ch == 0 || ch == 224 )
{
ch = 256 + _getch();
}
switch ( ch )
{
case ARROW_UP:
{
return 4;
break;
}
case ARROW_DOWN:
{
return 1;
break;
}
case ARROW_LEFT:
{
return 2;
break;
}
case ARROW_RIGHT:
{
return 3;
break;
}
default:
{
return -1;
break;
}
}
}

//canmove
bool canmove ( int array[][20], int arrayblock[1][4], int xblockx, int yblocky, int direction )
{
int r = 1, movedown = 0, moveright = 0, array2[4][4], xxx = xblockx, yyy = yblocky;
for ( int y = 0;y < 4;y++ )
{
for ( int x = 0;x < 4;x++ )
{
array2[x][y] = arrayblock[x][y];
}
}
switch ( direction )
{
case ( 1 ) :
{
movedown = 1;
break;
}
case ( 2 ) :
{
moveright = -1;
break;
}
case ( 3 ) :
{
moveright = 1;
break;
}
case ( 4 ) :
{
rotate_array ( array2 );
break;
}
case ( 5 ) : //checks if a new block can be made
{
changeblock ( array2 );
xxx = 3;
yyy = 0;
break;
}
}
for ( int y = 0;y < 4;y++ )
{
for ( int x = 0;x < 4;x++ )
{
if ( array2[x][y] == 2 && ( array[xxx+x+moveright][yyy+y+movedown] == 1 || yyy + y + movedown > 19 || xxx + x + moveright > 9 || xxx + x + moveright < 0 ) )
{
r = 0;
}
}
}
return r;
}
//check for full row
int checkforfullrow ( int array[][20], int scr )
{
scr = 0;
int rowy = 1;
for ( ;rowy != 0; )
{
rowy = 0;
for ( int y = 0;y < 20;y++ )
{
if ( array[0][y] == 1 )
{
for ( int x = 0;x < 10;x++ )
{
if ( array[x][y] == 0 )
{
break;
}
if ( array[x][y] == 1 && x == 9 )
{
rowy = y;
scr = scr + 10;
}
}
}
}
if ( rowy != 0 )
{
for ( int y = rowy;y > 0;y-- )
{
for ( int x = 0;x < 10;x++ )
{
array[x][y] = array[x][y-1];
}
}
}
}
return scr;
}
/////// The new display function
void display ( int matrix[][20], int full )
{
gotoxy ( 5, 0 );
cout << "PRAISE THE ALMIGHTY TETRIS";
for ( int y = 2;y < 22;y++ )
{
gotoxy ( 11, y );
cout << '.';
gotoxy ( 22, y );
cout << '.';
}
for ( int x = 0;x < 12;x++ )
{
gotoxy ( x + 11, 1 );
cout << ':';
gotoxy ( x + 11, 22 );
cout << ':';
}
for ( int y = blocky - 1;y < 5 + blocky;y++ )
{
if ( y < 20 && y >= 0 )
{
for ( int x = blockx - 1;x < 5 + blockx;x++ )
{
if ( x < 10 && x >= 0 )
{
if ( matrix[x][y] == 1 || matrix[x][y] == 2 )
{
gotoxy ( x + 12, y + 2 );
cout << '#';
}
else
{
gotoxy ( x + 12, y + 2 );
cout << ' ';
}
}
}
}
}
if ( full == 1 )
{
for ( int y = 0;y < 20;y++ )
{
for ( int x = 0;x < 10;x++ )
{
if ( matrix[x][y] == 1 || matrix[x][y] == 2 )
{
gotoxy ( x + 12, y + 2 );
cout << '#';
}
else
{
gotoxy ( x + 12, y + 2 );
cout << ' ';
}
}
}
}
gotoxy ( 0, 3 );
cout << "score: " << score;
gotoxy ( 0, 4 );
cout << "level: " << level;
gotoxy ( 0, 5 );
cout << "Next: " ;
gotoxy ( 22, 22 );
}
int playgame()
{
changeblock ( blockpreview );
while ( canmove ( board, block, blockx, blocky, 5 ) ) // While a new block can be created
{
for ( int y = 0;y < 4;y++ )
{
for ( int x = 0;x < 4;x++ )
{
block[x][y] = blockpreview[x][y];
}
}
changeblock ( blockpreview );
insertblock ( board, block );
display ( board, 1 );
while ( canmove ( board, block, blockx, blocky, 1 ) ) //while the block can move down
{
blocky = blocky + 1;
insertblock ( board, block );
display ( board, 0 );
double start = double ( clock() ) / 1000, end = double ( clock() ) / 1000;
while ( end - start < timeitvl ) //pause between blocks falling
{
if ( _kbhit() )
{
int kp = getkeypress();
if ( kp != -1 && canmove ( board, block, blockx, blocky, kp ) )
{
if ( kp == 1 )
{
blocky++;
}
else if ( kp == 2 )
{
blockx--;
}
else if ( kp == 3 )
{
blockx++;
}
else if ( kp == 4 )
{
rotate_array ( block );
}
insertblock ( board, block );
display ( board, 0 );
}
}
end = double ( clock() ) / 1000;
}
}
seta ( board );
score = checkforfullrow ( board, score ) + score;
level = score / 100;
timeitvl = .1 + 1.0 / ( double ( level + 2 ) );
display ( board, 0 );
}
return score;
}
////////////////////////////////////////////////////////////////////////////////////////
// These Functions I just copied and pasted, though the gotoxy one I understand mostly//
// I get lost trying to follow clscr one                                              //
////////////////////////////////////////////////////////////////////////////////////////
void gotoxy ( int x, int y )
{
COORD coord;
coord.X = x;
coord.Y = y;
SetConsoleCursorPosition ( GetStdHandle ( STD_OUTPUT_HANDLE ), coord );
}
void clrscr()
{
COORD coordScreen = { 0, 0 };
DWORD cCharsWritten;
CONSOLE_SCREEN_BUFFER_INFO csbi;
DWORD dwConSize;
HANDLE hConsole = GetStdHandle ( STD_OUTPUT_HANDLE );

GetConsoleScreenBufferInfo ( hConsole, &csbi );
dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
FillConsoleOutputCharacter ( hConsole, TEXT ( ' ' ), dwConSize,
coordScreen, &cCharsWritten );
GetConsoleScreenBufferInfo ( hConsole, &csbi );
FillConsoleOutputAttribute ( hConsole, csbi.wAttributes, dwConSize,
coordScreen, &cCharsWritten );
SetConsoleCursorPosition ( hConsole, coordScreen );
}``````

The problems were that the code was using deprecated functions and was using functions with data types without returning anything. Also, it had declared some arrays with 0 as its size...

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.