📄 tetris.cpp
字号:
//=========================================================
// Project Win32 俄罗斯方块程序
// File Tetris.cpp 主程序
// Update 2009.04
// Author 沉淪 http://www.EasyIDE.cn
// Tools Visual C++ 6.0 & Editplus 3
//=========================================================
#include "Tetris.h"
//Windows 入口函数
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR szCmdLine,int iCmdShow)
{
static TCHAR szClsName[] = TEXT("Tetris");
HWND hwnd;
MSG msg;
WNDCLASSEX wndclass;
InitCommonControls(); //初始化通用控件类库
//程序启动时初始化数据
hInst = hInstance;
RandomBlock(&ii,&jj,&cc);
//x = 4; y = -1;
iLevel = 1; iSorce = 0;
iLayer = 0; iSorceMax = TetrisIni(0);
hDcAlert = CreateCompatibleDC(NULL);
//注册窗口类
wndclass.hInstance = hInstance;
wndclass.lpszClassName = szClsName;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.cbSize = sizeof(WNDCLASSEX);
wndclass.style = CS_HREDRAW|CS_VREDRAW;
wndclass.hIcon = LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON1));
wndclass.hIconSm = NULL;
wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
wndclass.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
if ( !RegisterClassEx(&wndclass) )
{
MessageBox(
NULL,
TEXT("This program requires Windows NT!"),
TEXT("RegisterClass ERROR"),
MB_ICONERROR);
return 0;
}
//创建主窗口
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
szClsName,
TEXT("俄罗斯方块Win32版"),
WS_MINIMIZEBOX|WS_SYSMENU,
GetSystemMetrics(SM_CXFULLSCREEN)/2-370/2,
GetSystemMetrics(SM_CYFULLSCREEN)/2-520/2,
370,
520,
NULL,
NULL,
hInstance,
NULL);
//显示窗口并刷新客户区
ShowWindow(hwnd,iCmdShow);
UpdateWindow(hwnd);
//构建消息循环
while ( GetMessage(&msg,NULL,0,0) )
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//主窗口过程
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
switch ( message )
{
case WM_CREATE:
GameUI(hwnd); //创建界面控件
GameStart(hwnd); //数据初始化
//背景音乐初始化
bMusicOn = TRUE;
iMusicBG = IDR_WAVE1;
hMenu = GetMenu(hwnd);
MusicItem(IDM_MUSIC1);
return 0;
case WM_PAINT:
hdc = BeginPaint(hwnd,&ps);
DrawMatrix(hdc); //绘制游戏区
DrawTetris(hdc,0,0,0); //绘制方块
DrawNext(hdc); //绘制预览区
BitBlt(hdc,40,200,160,50,hDcAlert,0,0,SRCCOPY);//绘制提示语
EndPaint(hwnd,&ps);
return 0;
case WM_TIMER:
DropTetris(hwnd);
return 0;
case WM_DRAWITEM:
DrawButton(lParam); //绘制方向按钮
return TRUE;
case WM_KEYDOWN:
switch ( (int)wParam )
{
case VK_LEFT:
if ( !bStart ) break;
if ( CheckBlock(x-1,y) )
{
x --;
hdc = GetDC(hwnd);
DrawTetris(hdc,-1,0,0);
ReleaseDC(hwnd,hdc);
}
break;
case VK_RIGHT:
if ( !bStart ) break;
if ( CheckBlock(x+1,y) )
{
x ++;
hdc = GetDC(hwnd);
DrawTetris(hdc,1,0,0);
ReleaseDC(hwnd,hdc);
}
break;
case VK_UP:
if ( !bStart || y<0 ) break;
RankTetris(hwnd);
break;
case VK_DOWN:
if ( !bStart ) break;
DropTetris(hwnd);
break;
case VK_SPACE:
GamePause(hwnd);
break;
}
return 0;
case WM_COMMAND:
switch ( LOWORD(wParam) )
{
case IDM_STOP:
if ( y == -1 ) break;
GameOver(hwnd);
break;
case IDM_NEW:
GameStart(hwnd);
GamePause(hwnd);
break;
case IDM_PAUSE:
GamePause(hwnd);
break;
case IDM_EXIT:
SendMessage(hwnd,WM_DESTROY,NULL,NULL);
break;
case IDM_ABOUT:
DialogBox(hInst,MAKEINTRESOURCE(IDD_DIALOG1),hwnd,AboutDlgProc);
break;
case IDM_HELP:
DialogBox(hInst,MAKEINTRESOURCE(IDD_DIALOG2),hwnd,HelpDlgProc);
break;
case IDM_MUSIC:
DialogBox(hInst,MAKEINTRESOURCE(IDD_DIALOG3),hwnd,MusicDlgProc);
break;
case IDM_MUSIC1:
MusicItem(IDM_MUSIC1);
break;
case IDM_MUSIC2:
MusicItem(IDM_MUSIC2);
break;
case IDM_MUSICOFF:
MusicItem(IDM_MUSICOFF);
break;
case IDM_LEFT:
SendMessage(hwnd,WM_KEYDOWN,VK_LEFT,0);
SetFocus(hwnd);
break;
case IDM_RIGHT:
SendMessage(hwnd,WM_KEYDOWN,VK_RIGHT,0);
SetFocus(hwnd);
break;
case IDM_UP:
SendMessage(hwnd,WM_KEYDOWN,VK_UP,0);
SetFocus(hwnd);
break;
case IDM_DOWN:
SendMessage(hwnd,WM_KEYDOWN,VK_DOWN,0);
SetFocus(hwnd);
break;
}
return 0;
case WM_CLOSE:
if ( iSorce > iSorceMax ) iSorceMax = iSorce;
TetrisIni(iSorceMax);
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd,message,wParam,lParam);
}
//关于对话框窗口过程
BOOL CALLBACK AboutDlgProc(HWND hDlg,UINT message,WPARAM wParam,LPARAM lParam)
{
switch ( message )
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
switch ( LOWORD(wParam) )
{
case IDOK:
EndDialog(hDlg,0);
break;
}
break;
}
return FALSE;
}
//帮助对话框窗口过程
BOOL CALLBACK HelpDlgProc(HWND hDlg,UINT message,WPARAM wParam,LPARAM lParam)
{
switch ( message )
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
switch ( LOWORD(wParam) )
{
case IDOK:
EndDialog(hDlg,0);
break;
}
break;
}
return FALSE;
}
//背景音乐对话框窗口过程
BOOL CALLBACK MusicDlgProc(HWND hDlg,UINT message,WPARAM wParam,LPARAM lParam)
{
switch ( message )
{
case WM_INITDIALOG:
if( iMusicBG == IDR_WAVE1 ) CheckRadioButton(hDlg,IDC_RADIO1,IDC_RADIO3,IDC_RADIO1);
if( iMusicBG == IDR_WAVE2 ) CheckRadioButton(hDlg,IDC_RADIO1,IDC_RADIO3,IDC_RADIO2);
if( !bMusicOn ) CheckRadioButton(hDlg,IDC_RADIO1,IDC_RADIO3,IDC_RADIO3);
return TRUE;
case WM_COMMAND :
switch ( LOWORD(wParam) )
{
case IDC_RADIO1:
CheckRadioButton(hDlg,IDC_RADIO1,IDC_RADIO3,IDC_RADIO1);
break;
case IDC_RADIO2:
CheckRadioButton(hDlg,IDC_RADIO1,IDC_RADIO3,IDC_RADIO2);
break;
case IDC_RADIO3:
CheckRadioButton(hDlg,IDC_RADIO1,IDC_RADIO3,IDC_RADIO3);
break;
case IDOK:
if ( IsDlgButtonChecked(hDlg,IDC_RADIO1) == BST_CHECKED )
{
bMusicOn = TRUE;
iMusicBG = IDR_WAVE1;
MusicItem(IDM_MUSIC1);
if ( bStart ) TetrisMusic(TRUE);
}
if ( IsDlgButtonChecked(hDlg,IDC_RADIO2) == BST_CHECKED )
{
bMusicOn = TRUE;
iMusicBG = IDR_WAVE2;
MusicItem(IDM_MUSIC2);
if ( bStart ) TetrisMusic(TRUE);
}
if ( IsDlgButtonChecked(hDlg,IDC_RADIO3) == BST_CHECKED )
{
bMusicOn = FALSE;
MusicItem(IDM_MUSICOFF);
TetrisMusic(FALSE);
}
EndDialog(hDlg,0);
break;
case IDCANCEL:
EndDialog(hDlg,0);
break;
}
break;
}
return FALSE;
}
//音乐菜单处理
void MusicItem(int iCheckID)
{
CheckMenuRadioItem(hMenu,IDM_MUSIC1,IDM_MUSICOFF,iCheckID,MF_BYCOMMAND);
if ( iCheckID == IDM_MUSIC1 )
{
bMusicOn = TRUE;
iMusicBG = IDR_WAVE1;
if ( bStart ) TetrisMusic(TRUE);
}else if ( iCheckID == IDM_MUSIC2 )
{
bMusicOn = TRUE;
iMusicBG = IDR_WAVE2;
if ( bStart ) TetrisMusic(TRUE);
}
else
{
bMusicOn = FALSE;
TetrisMusic(FALSE);
}
return;
}
//背景音乐
void TetrisMusic(BOOL start)
{
if ( start && bMusicOn && !bGOver )
PlaySound(MAKEINTRESOURCE(iMusicBG),NULL,SND_RESOURCE|SND_LOOP|SND_ASYNC);
else
PlaySound(NULL,NULL,NULL);
return;
}
//初始化游戏数据
void GameStart(HWND hwnd)
{
int m, n;
HDC hdc;
hDcBitmap = CreateCompatibleDC(NULL);
//初始化Matrix矩阵
for ( m=0; m<=18; m++ )
{
for ( n=0; n<=9; n++ )
{
Matrix[m][n] = -1; //Matrix[m][n]处初始颜色值为-1
}
}
//初始化方块位置
x = 4; y = -1;
//初始化标志变量
bStart = FALSE;
bGOver = FALSE;
//初始化游戏区
hdc = GetDC(hwnd);
DrawMatrix(hdc);
ReleaseDC(hwnd,hdc);
//初始化计分器
iLevel = 1;
wsprintf(szBuffer,TEXT("%i"),iLevel);
SetWindowText(hLevel,szBuffer); //级别
iLayer = 0;
wsprintf(szBuffer,TEXT("%i"),iLayer);
SetWindowText(hLayer,szBuffer); //满行
if ( iSorce > iSorceMax ) iSorceMax = iSorce;
wsprintf(szBuffer,TEXT("%i"),iSorceMax);
SetWindowText(hSorceMax,szBuffer); //最高分
iSorce = 0;
wsprintf(szBuffer,TEXT("%i"),iSorce);
SetWindowText(hSorce,szBuffer); //得分
//状态栏提示
SendMessage(hStatus,SB_SETTEXT,0,(LPARAM)TEXT("空格键开始/暂停"));
SendMessage(hStatus,SB_SETTEXT,1,(LPARAM)TEXT("方向键上键控制变形,左、右、下键控制移动"));
//清除提示DC在的位图
hDcAlert = CreateCompatibleDC(NULL);
return;
}
//暂停/继续游戏
void GamePause(HWND hwnd)
{
if( bGOver ) return;
if ( bStart )
{
KillTimer(hwnd, 1);
SendMessage(hStatus,SB_SETTEXT,0,(LPARAM)TEXT("游戏暂停"));
TetrisMusic(FALSE);
}
else
{
SetTimer(hwnd, 1, (550-55*iLevel), NULL);
SendMessage(hStatus,SB_SETTEXT,0,(LPARAM)TEXT("游戏中 ^-^"));
TetrisMusic(TRUE);
}
bStart = !bStart;
return;
}
//游戏结束
void GameOver(HWND hwnd)
{
HDC hdc;
KillTimer(hwnd, 1);
SelectObject(hDcAlert,LoadBitmap(hInst,MAKEINTRESOURCE(IDB_BITMAP9)));
hdc = GetDC(hwnd);
BitBlt(hdc,40,200,160,50,hDcAlert,0,0,SRCCOPY);//绘制提示语
ReleaseDC(hwnd,hdc);
SendMessage(hStatus,SB_SETTEXT,0,(LPARAM)TEXT("游戏结束"));
bGOver = TRUE;
x = 4; y = -1;
TetrisMusic(FALSE);
return;
}
//从INI文件中读/写最高分
int TetrisIni(int value)
{
int iSorceMax = 0;
TCHAR szBuffer[10];
TCHAR szIniFile[100];
SHGetSpecialFolderPath(0,szIniFile,CSIDL_APPDATA,0);
lstrcat(szIniFile,TEXT("\\Win32Tetris"));
CreateDirectory(szIniFile,NULL);
lstrcat(szIniFile,TEXT("\\Config.ini"));
if ( value == 0 )
{//读
iSorceMax = GetPrivateProfileInt(TEXT("Win32Tetris"),TEXT("SorceMax"),0,szIniFile);
}
else
{//写
wsprintf(szBuffer,TEXT("%i"),value);
WritePrivateProfileString(TEXT("Win32Tetris"),TEXT("Contact"),TEXT("www.EasyIDE.cn"),szIniFile);
WritePrivateProfileString(TEXT("Win32Tetris"),TEXT("SorceMax"),szBuffer,szIniFile);
}
return iSorceMax;
}
//用Matrix中的数据绘制游戏区
void DrawMatrix(HDC hdc)
{
int m, n;
//绘制Matrix矩阵
for ( m=0; m<=18; m++ )
{
for ( n=0; n<=9; n++ )
{
if ( Matrix[m][n] == -1 )
{
PatBlt(hdc,20+n*20,40+m*20,20,20,BLACKNESS);
}
else
{
SelectObject(hDcBitmap,LoadBitmap(hInst,MAKEINTRESOURCE(120+Matrix[m][n])));
BitBlt(hdc,20+n*20,40+m*20,20,20,hDcBitmap,0,0,SRCCOPY);
}
}
}
return;
}
//绘制方块
void DrawTetris(HDC hdc, int iOffsetX, int iOffsetY, int iRank)
{
int iX, iY, iJ;
if ( y == -1 ) return;
//如果方块平移过则擦除原来的方块位置
if ( iOffsetX != 0 || iOffsetY != 0 )
{
iX = x + Tetris[i][j].a.x - iOffsetX;
iY = y + Tetris[i][j].a.y - iOffsetY;
PatBlt(hdc,20+iX*20,40+iY*20,20,20,BLACKNESS);
iX = x + Tetris[i][j].b.x - iOffsetX;
iY = y + Tetris[i][j].b.y - iOffsetY;
PatBlt(hdc,20+iX*20,40+iY*20,20,20,BLACKNESS);
iX = x + Tetris[i][j].c.x - iOffsetX;
iY = y + Tetris[i][j].c.y - iOffsetY;
PatBlt(hdc,20+iX*20,40+iY*20,20,20,BLACKNESS);
iX = x + Tetris[i][j].d.x - iOffsetX;
iY = y + Tetris[i][j].d.y - iOffsetY;
PatBlt(hdc,20+iX*20,40+iY*20,20,20,BLACKNESS);
}
//如果方块旋转过则擦除原来的方块位置
if ( iRank != 0 )
{
iJ = j==0 ? 3 : j-1;
iX = x + Tetris[i][iJ].a.x;
iY = y + Tetris[i][iJ].a.y;
PatBlt(hdc,20+iX*20,40+iY*20,20,20,BLACKNESS);
iX = x + Tetris[i][iJ].b.x;
iY = y + Tetris[i][iJ].b.y;
PatBlt(hdc,20+iX*20,40+iY*20,20,20,BLACKNESS);
iX = x + Tetris[i][iJ].c.x;
iY = y + Tetris[i][iJ].c.y;
PatBlt(hdc,20+iX*20,40+iY*20,20,20,BLACKNESS);
iX = x + Tetris[i][iJ].d.x;
iY = y + Tetris[i][iJ].d.y;
PatBlt(hdc,20+iX*20,40+iY*20,20,20,BLACKNESS);
}
//绘制新位置方块
SelectObject(hDcBitmap,LoadBitmap(hInst,MAKEINTRESOURCE(120+c)));
iX = x + Tetris[i][j].a.x;
iY = y + Tetris[i][j].a.y;
BitBlt(hdc,20+iX*20,40+iY*20,20,20,hDcBitmap,0,0,SRCCOPY);
iX = x + Tetris[i][j].b.x;
iY = y + Tetris[i][j].b.y;
BitBlt(hdc,20+iX*20,40+iY*20,20,20,hDcBitmap,0,0,SRCCOPY);
iX = x + Tetris[i][j].c.x;
iY = y + Tetris[i][j].c.y;
BitBlt(hdc,20+iX*20,40+iY*20,20,20,hDcBitmap,0,0,SRCCOPY);
iX = x + Tetris[i][j].d.x;
iY = y + Tetris[i][j].d.y;
BitBlt(hdc,20+iX*20,40+iY*20,20,20,hDcBitmap,0,0,SRCCOPY);
return;
}
//绘制预览区
void DrawNext(HDC hdc)
{
RECT rc;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -