源.cpp
#include
#include
#include
#include"tetromino.h"
using namespace std;
bool panel [ 1000 ][ 1000 ];
tetromino *p = nullptr;
tetromino *nextp = nullptr;
int score = 0;
bool loss;
void start ();
void initpanel ();
void createTetromino ();
void play ();
void eliminate ();
void goDown ( thread& );
void control ();
void endgame ();
bool leftable ( const tetromino& );
bool rightable ( const tetromino& );
bool spinnable ( const tetromino& );
int main ( void )
{
start ();
initpanel ();
while ( !loss )
{
createTetromino ();
play ();
eliminate ();
}
endgame ();
return 0;
}
void initpanel ()
{
for ( int i = 0; i < WIDTH; i++ )
{
for ( int j = 0; j < HEIGHT; j++ )
{
panel [ j ][ i ] = true;
}
}
}
void createTetromino ()
{
int choice;
if ( !( panel [ 0 ][ 4 ] && panel [ 0 ][ 5 ] && panel [ 0 ][ 6 ] ) )
{
loss = false;
endgame ();
}
if ( !nextp )
{
srand ( time ( 0 ) );
choice = rand () % 7;
switch ( choice )
{
case I:
nextp = new tetromino ( I );
break;
case J:
nextp = new tetromino ( J );
break;
case L:
nextp = new tetromino ( L );
break;
case O:
nextp = new tetromino ( O );
break;
case S:
nextp = new tetromino ( S );
break;
case Z:
nextp = new tetromino ( Z );
break;
case T:
nextp = new tetromino ( T );
break;
}
p = nextp;
}
else
{
p = nextp;
}
choice = rand () % 7;
switch ( choice )
{
case I:
nextp = new tetromino ( I );
break;
case J:
nextp = new tetromino ( J );
break;
case L:
nextp = new tetromino ( L );
break;
case O:
nextp = new tetromino ( O );
break;
case S:
nextp = new tetromino ( S );
break;
case Z:
nextp = new tetromino ( Z );
break;
case T:
nextp = new tetromino ( T );
break;
}
clearrectangle ( 11 * BORDER , 0 , 17 * BORDER , 4 * BORDER );
for ( int i = 0; i < 4; i++ )
{
solidrectangle ( ( 7.5 + nextp->block [ i ].X )*BORDER , ( nextp->block [ i ].Y )*BORDER , ( 8.5 + nextp->block [ i ].X )*BORDER , ( 1 + nextp->block [ i ].Y )*BORDER );
}
p->display ();
}
void play ()
{
thread controlThread ( control );
goDown ( controlThread );
}
void goDown ( thread& thr )
{
for ( int i = 0; i < HEIGHT; i++ )
{
for ( int j = 0; j < 4; j++ )
{
if ( !panel [ p->block [ j ].Y + 1 ][ p->block [ j ].X ] || i == HEIGHT - 1 )
{
for ( int k = 0; k < 4; k++ )
{
panel [ p->block [ k ].Y ][ p->block [ k ].X ] = false;
}
goto JUMPOUT;
}
}
p->moveDown ();
Sleep ( p->interval );
}
JUMPOUT:
thr.detach ();
}
void control ()
{
while ( 1 )
{
if ( _kbhit () )
{
switch ( _getch () )
{
case 'w':
if ( spinnable ( *p ) )
{
p->spin ();
p->decelerate ();
}
break;
case 'a':
if ( leftable ( *p ) )
{
p->moveLeft ();
p->decelerate ();
}
break;
case 'd':
if ( rightable ( *p ) )
{
p->moveRight ();
p->decelerate ();
}
break;
case 's':
p->accelerate ();
break;
}
}
}
}
void eliminate ()
{
bool flag = true;
int line = true;
while ( line )
{
line = 0;
for ( int i = 0; i < 20; i++ )
{
flag = true;
for ( int j = 0; j < 10; j++ )
{
if ( panel [ i ][ j ] )
{
flag = false;
}
}
if ( flag )
{
line = i;
}
}
if ( line )
{
score++;
for ( int i = line; i > 0; i-- )
{
for ( int j = 0; j < 10; j++ )
{
panel [ i ][ j ] = panel [ i - 1 ][ j ];
if ( !panel [ i ][ j ] )
{
solidrectangle ( j*BORDER , i*BORDER , ( j + 1 )*BORDER , ( i + 1 )*BORDER );
}
else
{
clearrectangle ( j*BORDER , i*BORDER , ( j + 1 )*BORDER , ( i + 1 )*BORDER );
}
}
}
}
}
clearrectangle ( 11 * BORDER , 5 * BORDER , 16 * BORDER , 9 * BORDER );
char str [ 5 ];
sprintf_s ( str , "%d" , score );
outtextxy ( 13 * BORDER , 7 * BORDER , str );
}
void endgame ()
{
cleardevice ();
closegraph ();
cout << "GAME OVER!" << endl << "YOUR SCORE:" << score << endl;
system ( "pause" );
exit ( 0 );
}
void start ()
{
initgraph ( 401 , 400 );
char str1 [] = "Press any key to start!";
outtextxy ( 100 , 200 , str1 );
char str2 [] = "使用WASD操控";
outtextxy ( 100 , 300 , str2 );
while ( !_kbhit () );
cleardevice ();
line ( 201 , 0 , 201 , 401 );
line ( 0 , 401 , 201 , 401 );
rectangle ( 11 * BORDER - 1 , 0 , 16 * BORDER + 1 , 4 * BORDER + 1 );
rectangle ( 11 * BORDER - 1 , 5 * BORDER + 1 , 16 * BORDER + 1 , 9 * BORDER + 1 );
}
bool leftable ( const tetromino& tet )
{
for ( int i = 0; i < 4; i++ )
{
if ( !panel [ tet.block [ i ].Y ][ tet.block [ i ].X - 1 ] )
{
return false;
}
}
return true;
}
bool rightable ( const tetromino& tet )
{
for ( int i = 0; i < 4; i++ )
{
if ( !panel [ tet.block [ i ].Y ][ tet.block [ i ].X + 1 ] )
{
return false;
}
}
return true;
}
bool spinnable ( const tetromino& tet )
{
for ( int i = 0; i < 4; i++ )
{
if ( !panel [ -p->block [ i ].X + p->center.X + p->center.Y ][ p->block [ i ].Y - p->center.Y + p->center.X ] )
{
if ( -p->block [ i ].X + p->center.X + p->center.Y <= 10 && p->block [ i ].Y - p->center.Y + p->center.X <= 20 )
{
return false;
}
}
}
return true;
}
tetromino.h
#ifndef TETROMINO_H
#define TETROMINO_H
#define BORDER 20
#define HEIGHT 20
#define WIDTH 20
#include
enum tetromino_type
{
I , J , L , O , S , Z , T
};
class tetromino
{
public:
tetromino ( tetromino_type index );
tetromino_type type;
int interval = 300;
COORD block [ 4 ];
COORD center;
void display ();
void moveLeft ();
void moveRight ();
void moveDown ();
void spin ();
void accelerate ();
void decelerate ();
bool left ();
bool right ();
};
#endif
tetromino.cpp
#include
#include"tetromino.h"
using namespace std;
tetromino::tetromino ( tetromino_type index )
{
switch ( index )
{
case I:
block [ 0 ] = { 5 , 0 };
block [ 1 ] = { 5 , 1 };
block [ 2 ] = { 5 , 2 };
block [ 3 ] = { 5 , 3 };
center = { 5 , 1.5 };
type = I;
break;
case J:
block [ 0 ] = { 5 , 0 };
block [ 1 ] = { 5 , 1 };
block [ 2 ] = { 5 , 2 };
block [ 3 ] = { 4 , 2 };
center = block [ 1 ];
type = J;
break;
case L:
block [ 0 ] = { 5 , 0 };
block [ 1 ] = { 5 , 1 };
block [ 2 ] = { 5 , 2 };
block [ 3 ] = { 6 , 2 };
center = block [ 1 ];
type = L;
break;
case O:
block [ 0 ] = { 5 , 0 };
block [ 1 ] = { 6 , 0 };
block [ 2 ] = { 5 , 1 };
block [ 3 ] = { 6 , 1 };
center = { 5.5 , 0.5 };
type = O;
break;
case S:
block [ 0 ] = { 6 , 0 };
block [ 1 ] = { 5 , 0 };
block [ 2 ] = { 5 , 1 };
block [ 3 ] = { 4 , 1 };
center = block [ 1 ];
type = S;
break;
case Z:
block [ 0 ] = { 4 , 0 };
block [ 1 ] = { 5 , 0 };
block [ 2 ] = { 5 , 1 };
block [ 3 ] = { 6 , 1 };
center = block [ 1 ];
type = Z;
break;
case T:
block [ 0 ] = { 4 , 0 };
block [ 1 ] = { 5 , 0 };
block [ 2 ] = { 6 , 0 };
block [ 3 ] = { 5 , 1 };
center = block [ 1 ];
type = T;
break;
}
}
void tetromino::display ()
{
for ( int i = 0; i < 4; i++ )
{
solidrectangle ( block [ i ].X*BORDER , block [ i ].Y*BORDER , ( block [ i ].X + 1 )*BORDER , ( block [ i ].Y + 1 )*BORDER );
}
}
void tetromino::moveLeft ()
{
if ( !left () )
{
for ( int i = 0; i < 4; i++ )
{
clearrectangle ( block [ i ].X*BORDER , block [ i ].Y*BORDER , ( block [ i ].X + 1 )*BORDER , ( block [ i ].Y + 1 )*BORDER );
block [ i ].X--;
}
center.X--;
display ();
}
}
void tetromino::moveRight ()
{
if ( !right () )
{
for ( int i = 0; i < 4; i++ )
{
clearrectangle ( block [ i ].X*BORDER , block [ i ].Y*BORDER , ( block [ i ].X + 1 )*BORDER , ( block [ i ].Y + 1 )*BORDER );
block [ i ].X++;
}
center.X++;
display ();
}
}
void tetromino::moveDown ()
{
for ( int i = 0; i < 4; i++ )
{
clearrectangle ( block [ i ].X*BORDER , block [ i ].Y*BORDER , ( block [ i ].X + 1 )*BORDER , ( block [ i ].Y + 1 )*BORDER );
block [ i ].Y++;
}
center.Y++;
display ();
}
void tetromino::spin ()
{
if ( type != O )
{
for ( int i = 0; i < 4; i++ )
{
clearrectangle ( block [ i ].X*BORDER , block [ i ].Y*BORDER , ( block [ i ].X + 1 )*BORDER , ( block [ i ].Y + 1 )*BORDER );
int x = block [ i ].X;
int y = block [ i ].Y;
block [ i ].X = y - center.Y + center.X;
block [ i ].Y = -x + center.X + center.Y;
}
display ();
}
}
void tetromino::accelerate ()
{
interval = 100;
}
void tetromino::decelerate ()
{
interval = 300;
}
bool tetromino::left ()
{
for ( int i = 0; i < 4; i++ )
{
if ( block [ i ].X == 0 )
{
return true;
}
}
return false;
}
bool tetromino::right ()
{
for ( int i = 0; i < 4; i++ )
{
if ( block [ i ].X == 9 )
{
return true;
}
}
return false;
}