Code:
#include <WINDOWS.H>
#include <STDLIB.H>
#include <STDIO.H>
struct BOARD
{
CHAR umBoard[ 14 ][ 21 ];
CHAR uLines;
};
struct BLOCK
{
CHAR umBlock[ 4 ][ 4 ];
CHAR uX;
CHAR uY;
};
const CHAR g_mmBlockI[ 4 ][ 4 ] = { { 0, 1, 0, 0 }, { 0, 1, 0, 0 }, { 0, 1, 0, 0 }, { 0, 1, 0, 0 }, };
const CHAR g_mmBlockJ[ 4 ][ 4 ] = { { 0, 1, 0, 0 }, { 0, 1, 0, 0 }, { 1, 1, 0, 0 }, { 0, 0, 0, 0 }, };
const CHAR g_mmBlockL[ 4 ][ 4 ] = { { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, { 1, 1, 0, 0 }, { 0, 0, 0, 0 }, };
const CHAR g_mmBlockO[ 4 ][ 4 ] = { { 1, 1, 0, 0 }, { 1, 1, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, };
const CHAR g_mmBlockS[ 4 ][ 4 ] = { { 0, 1, 1, 0 }, { 1, 1, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, };
const CHAR g_mmBlockT[ 4 ][ 4 ] = { { 1, 1, 1, 0 }, { 0, 1, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, };
const CHAR g_mmBlockZ[ 4 ][ 4 ] = { { 1, 1, 0, 0 }, { 0, 1, 1, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, };
double g_fLastTime = 0.0;
HBRUSH g_hbrBlock = CreateSolidBrush( RGB( 100, 100, 120 ) );
HBRUSH g_hbrSpace = CreateSolidBrush( RGB( 0, 0, 0 ) );
BOARD g_Board = { 0 };
BLOCK g_Block = { 0 };
BOOL g_bDoUpdate = FALSE;
//-----------------------------------------------------------------------------
// Reset the game board
//
VOID ResetGameBoard( )
{
for ( int i = 0; i < 21; ++i )
for ( int j = 0; j < 14; ++j )
if ( i == 20 || j == 0 || j == 13 )
g_Board.umBoard[ j ][ i ] = 1;
else
g_Board.umBoard[ j ][ i ] = 0;
g_Board.uLines = 0;
}
//-----------------------------------------------------------------------------
// Generate a new random figure
//
VOID GenerateRandomBlock( )
{
CHAR uBlock = ( rand( ) % 7 ) + 1;
switch ( uBlock )
{
case 1: memcpy( g_Block.umBlock, g_mmBlockI, 16 ); break;
case 2: memcpy( g_Block.umBlock, g_mmBlockJ, 16 ); break;
case 3: memcpy( g_Block.umBlock, g_mmBlockL, 16 ); break;
case 4: memcpy( g_Block.umBlock, g_mmBlockO, 16 ); break;
case 5: memcpy( g_Block.umBlock, g_mmBlockS, 16 ); break;
case 6: memcpy( g_Block.umBlock, g_mmBlockT, 16 ); break;
case 7: memcpy( g_Block.umBlock, g_mmBlockZ, 16 ); break;
}
g_Block.uX = 6;
g_Block.uY = 0;
}
//-----------------------------------------------------------------------------
// Check for a collision on the board
//
BOOL CheckCollision
(
CHAR umBlock[ 4 ][ 4 ]
)
{
for ( int i = 0; i < 4; ++i )
for ( int j = 0; j < 4; ++j )
if ( umBlock[ j ][ i ] == 0 )
break;
else
if ( g_Board.umBoard[ j + g_Block.uX ][ i + g_Block.uY ] + umBlock[ j ][ i ] != umBlock[ j ][ i ] )
return TRUE;
return FALSE;
}
//-----------------------------------------------------------------------------
// Move a block
//
BOOL MoveBlock( int nDX, int nDY )
{
int nTempX, nTempY;
nTempX = g_Block.uX;
nTempY = g_Block.uY;
g_Block.uX += nDX;
g_Block.uY += nDY;
if ( TRUE == CheckCollision( g_Block.umBlock ) )
{
g_Block.uX = nTempX;
g_Block.uY = nTempY;
return TRUE;
}
return FALSE;
}
//-----------------------------------------------------------------------------
// Rotate a block 90 degrees
//
VOID RotateBlock( )
{
CHAR i, j, umFig[ 4 ][ 4 ];
for ( i = 0; i < 4; ++i )
for ( j = 0; j < 4; ++j )
umFig[ j ][ i ] = g_Block.umBlock[ 4 - i ][ j ];
if ( TRUE == CheckCollision( umFig ) )
return;
for ( i = 0; i < 4; ++i )
for ( j = 0; j < 4; ++j )
umFig[ j ][ i ] = g_Block.umBlock[ j ][ i ];
}
//-----------------------------------------------------------------------------
// Insert a block
//
VOID InsertBlock( )
{
for ( int i = 0; i < 4; ++i )
for ( int j = 0; j < 4; ++j )
if ( g_Block.umBlock[ j ][ i ] != 0 )
g_Board.umBoard[ g_Block.uX + j ][ g_Block.uY + i ] = g_Block.umBlock[ j ][ i ];
}
//-----------------------------------------------------------------------------
// Remove completed lines
//
VOID RemoveLine( UINT uIndex )
{
for ( int i = uIndex; i > 0; --i )
for ( int j = 1; j < 13; ++j )
g_Board.umBoard[ j ][ i ] = g_Board.umBoard[ j ][ i - 1 ];
}
//-----------------------------------------------------------------------------
// Search for completed lines
//
VOID SearchLines( )
{
CHAR uNumBlocks = 0;
for ( int i = 0; i < 21; ++i )
for ( int j = 1; j < 13; ++j )
if ( g_Board.umBoard[ j ][ i ] == 0 )
{
uNumBlocks = 0;
break;
}
else
{
++uNumBlocks;
if ( uNumBlocks >= 12 )
{
RemoveLine( i );
++g_Board.uLines;
--i;
}
}
}
//-----------------------------------------------------------------------------
// Paint the scene
//
VOID PaintScene( HWND hWnd )
{
CHAR cvBuffer[ 80 ];
RECT rcBlock;
HDC hDC;
int i, j;
hDC = GetDC( hWnd );
for ( i = 0; i < 20; ++i )
for ( j = 1; j < 13; ++j )
{
rcBlock.top = ( i * 16 ) + 4;
rcBlock.left = ( j * 16 ) + 4;
rcBlock.bottom = rcBlock.top + 16;
rcBlock.right = rcBlock.left + 16;
if ( g_Board.umBoard[ j ][ i ] == 0 )
FillRect( hDC, &rcBlock, g_hbrSpace );
else
FillRect( hDC, &rcBlock, g_hbrBlock );
}
for ( i = 0; i < 4; ++i )
for ( j = 0; j < 4; ++j )
if ( g_Block.umBlock[ j ][ i ] == 0 )
break;
else
{
rcBlock.top = ( ( g_Block.uY + i ) * 16 ) + 4;
rcBlock.left = ( ( g_Block.uX + j ) * 16 ) + 4;
rcBlock.bottom = rcBlock.top + 16;
rcBlock.right = rcBlock.left + 16;
if ( g_Block.umBlock[ j ][ i ] != 0 )
FillRect( hDC, &rcBlock, g_hbrBlock );
}
SetBkColor( hDC, RGB( 100, 120, 100 ) );
SetTextColor( hDC, RGB( 255, 240, 50 ) );
sprintf( cvBuffer, "Level: %i", ( g_Board.uLines / 15 ) );
TextOut( hDC, 210, 100, cvBuffer, ( int )strlen( cvBuffer ) );
sprintf( cvBuffer, "Lines: %i", g_Board.uLines );
TextOut( hDC, 210, 135, cvBuffer, ( int )strlen( cvBuffer ) );
ReleaseDC( hWnd, hDC );
}
//-----------------------------------------------------------------------------
// Process Win32 application messages
//
LRESULT CALLBACK WindowProc
(
HWND hWnd,
UINT uMessage,
WPARAM wParam,
LPARAM lParam
)
{
switch ( uMessage )
{
case WM_LBUTTONDOWN:
SendMessage( hWnd, WM_NCLBUTTONDOWN, HTCAPTION, lParam );
return 0L;
case WM_KEYDOWN:
switch ( LOWORD( wParam ) )
{
case VK_ESCAPE:
PostQuitMessage( 0 );
break;
case VK_LEFT:
MoveBlock( -1, 0 );
g_bDoUpdate = TRUE;
break;
case VK_RIGHT:
MoveBlock( 1, 0 );
g_bDoUpdate = TRUE;
break;
case VK_DOWN:
MoveBlock( 0, 1 );
g_bDoUpdate = TRUE;
break;
case VK_SPACE:
RotateBlock( );
g_bDoUpdate = TRUE;
break;
}
return 0L;
case WM_DESTROY:
PostQuitMessage( 0 );
return 0L;
}
return DefWindowProc( hWnd, uMessage, wParam, lParam );
}
//-----------------------------------------------------------------------------
// Application entry point
//
int WINAPI WinMain
(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nShowCmd
)
{
WNDCLASS sWC;
HWND hWnd;
MSG sMsg;
memset( &sWC, 0, sizeof( WNDCLASS ) );
sWC.hbrBackground = CreateSolidBrush( RGB( 100, 120, 100 ) );
sWC.hCursor = LoadCursor( NULL, IDC_ARROW );
sWC.hIcon = LoadIcon( NULL, IDI_WINLOGO );
sWC.hInstance = hInstance;
sWC.lpfnWndProc = WindowProc;
sWC.lpszClassName = "DEMO";
RegisterClass( &sWC );
hWnd = CreateWindow( "DEMO", "Demo", WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 270, 400, NULL, NULL, hInstance, NULL );
ResetGameBoard( );
GenerateRandomBlock( );
PeekMessage( &sMsg, NULL, 0U, 0U, PM_NOREMOVE );
while ( WM_QUIT != sMsg.message )
if ( PeekMessage( &sMsg, NULL, 0U, 0U, PM_REMOVE ) )
{
TranslateMessage( &sMsg );
DispatchMessage( &sMsg );
}
else
{
double fTime = GetTickCount( ) * 0.001;
if ( fTime - g_fLastTime > ( 1.0 - ( ( g_Board.uLines / 15 ) * 0.1 ) ) )
{
g_fLastTime = fTime;
if ( MoveBlock( 0, 1 ) )
{
InsertBlock( );
SearchLines( );
GenerateRandomBlock( );
}
g_bDoUpdate = TRUE;
}
if ( TRUE == g_bDoUpdate )
{
PaintScene( hWnd );
g_bDoUpdate = FALSE;
}
}
return ( int )sMsg.wParam;
}