⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tetris.cpp

📁 C语言写的俄罗斯方块
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//=========================================================
// 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 + -