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

📄 russian.cpp

📁 一个MFC实例
💻 CPP
字号:
//===============================================================================================
#include "Russian.h"


//================================================================================================
						//类的实现
//===============================================================================================

//===============================================================================================
//静态变量初始化
int RussianCube::m_iShapeCode[] = {
										0x145,							//0
										0x123,0x48c,					//1 , 2
										0x159,0x2456,0x489,0x124,		//3,4,5,6
										0x148,0x126,0x1589,0x456,		//7,8,9 10
										0x125,0x1459,0x1456,0x458,		//11,12,13,14
										0x459,0x1245,					//15,16
										0x1458,0x156					//17,18;
									};	

//construction
RussianCube::RussianCube(int iRow,int iColumn,HWND hWindow)
{
	m_iRow			= iRow;								//行
	m_iColumn		= iColumn;							//列
	m_hWindow		= hWindow;							//窗口句柄 
	m_bShouldStop	= false;							//方块不停止
	m_iLevel		= 1;								//等级为1
	m_iScore		= 0;								//得分清零
	m_iVolecity		= 2;
	m_iNext			= rand() % 19;						//生成第一个方块;
	//创建背景和方块
	HDC	hDC			= GetDC(hWindow);
	m_pBackground	= new Bitmap(hDC,IDB_BACKGROUND,g_hInstance);
	m_pCubePic[0]	= new Bitmap(hDC,IDB_CUBE1,g_hInstance);
	m_pCubePic[1]	= new Bitmap(hDC,IDB_CUBE2,g_hInstance);
	m_pCubePic[2]	= new Bitmap(hDC,IDB_CUBE3,g_hInstance);
	m_pCubePic[3]	= new Bitmap(hDC,IDB_CUBE4,g_hInstance);

	m_pCube			= new bool*[m_iRow];				//分配二维数组;
	for(int i = 0; i < m_iRow; ++i)
	{
		m_pCube[i]	= new bool [m_iColumn];
	}

	//不显示所有方块
	for(i = 0; i< m_iRow; ++i)
	{
		for(int j = 0; j < m_iColumn; ++j)
		{
			m_pCube[i][j] = false;
		}
	}

	Refresh();											//刷新生成新的方块;
}

//distruction
RussianCube::~RussianCube()
{
	delete m_pBackground;
	delete m_pCubePic[0];
	delete m_pCubePic[1];
	delete m_pCubePic[2];
	delete m_pCubePic[3];
	for(int i = 0 ;i < m_iRow; ++ i)
	{
		delete []m_pCube[i];
	}
	delete []m_pCube;
}

//刷新生成新的方块
void RussianCube::Refresh(void)
{
	m_ptMain.y		= 0;
	m_ptMain.x		= m_iColumn / 2 * m_pCubePic[0]->GetWidth();			
	m_iShape		= m_iNext;
	m_iNext			= rand() % 19;
	Calculation();				//计算方块的的位置;
}

//绘制
void RussianCube::Draw(HDC hDC)
{
	m_pBackground->Draw(hDC,0,0);								//背景
	
	int iWidth = m_pCubePic[0]->GetWidth();
	int iHeight = m_pCubePic[0]->GetHeight();

	for(int iRow = 0; iRow < m_iRow; ++iRow)		//从左到右每一列扫描方块
	{
		for(int iColumn = 0 ; iColumn < m_iColumn;++iColumn)
		{
			if(m_pCube[iRow][iColumn])					//如果该位置不为空
			{
				m_pCubePic[rand() % 4]->Draw(hDC, iColumn * iWidth ,iRow * iHeight );
			}
		}
	}

	for(int i = 0; i < 4; ++i)								//绘制四个小方块组成的图形								
	{
		m_pCubePic[rand() % 4]->Draw(hDC,m_ptCube[i].x,m_ptCube[i].y);
	}
	
	//计算并绘制下一个方块
	POINT	ptNext[4];
	int iTempShape = m_iShapeCode[m_iNext];		//译码
	int iBit;//取位
	
	
	i = 0;
	while(iTempShape && i < 4)//计算四个方块的坐标
	{
		iBit = iTempShape % 16;
		ptNext[i].x = (iBit % 4) * iWidth + 211;
		ptNext[i].y = (iBit / 4) * iHeight + 60;
		++i;
		iTempShape /=16;
	}
	if(i <= 3)
	{
		ptNext[3].x = 211;
		ptNext[3].y = 60;
	}
	for(i = 0; i < 4; ++i)								//绘制四个小方块组成的图形								
	{
		m_pCubePic[rand() % 4]->Draw(hDC,ptNext[i].x,ptNext[i].y);
	}

	//显示得分
	char	szMessage[64];
	wsprintf(szMessage,"%d",m_iScore);
	TextOut(hDC,249,218,szMessage,strlen(szMessage));
	
	//显示等级
	wsprintf(szMessage,"%d",m_iLevel);
	TextOut(hDC,249,300,szMessage,strlen(szMessage));

	if(IsGameOver())
	{
		TextOut(hDC,60,140,TEXT("GAME OVER !!"),12);
	}
}

//方块下落
void RussianCube::FallDown(void)
{
	for(int i = 0; i < 4; ++i)
	{
		m_ptCube[i].y += m_iVolecity;
	}
	m_ptMain.y += m_iVolecity;
}



//是否可以左移
bool RussianCube::CanLeft(void)
{
	int iHeight	= m_pCubePic[0]->GetHeight();
	int iWidth	= m_pCubePic[0]->GetWidth();
	for(int i = 0; i < 4; ++i)
	{
		//如果方块没有到达边界,并且左边没有方块
		if(m_ptCube[i].x <= 0 || m_pCube[m_ptCube[i].y /iHeight][m_ptCube[i].x / iWidth -1] )
		{
			return false;
		}
	}
	return true;
}

//是否可以右移
bool RussianCube::CanRight()
{
	int iHeight	= m_pCubePic[0]->GetHeight();
	int iWidth	= m_pCubePic[0]->GetWidth();
	for(int i = 0; i < 4; ++i)
	{
		//如果方块没有到达边界,并且右边没有方块
		if(m_ptCube[i].x >= 180 || m_pCube[m_ptCube[i].y /iHeight][m_ptCube[i].x / iWidth + 1])
		{
			return false;
		}
	}
	return true;
}

//游戏是否结束
bool RussianCube::IsGameOver(void)
{
	for(int iX = 0; iX < m_iColumn; ++iX)
	{
		if(m_pCube[0][iX])				//如果顶部已经有方块,游戏结束
		{
			return true;
		}
	}
	return false;
}

//变形
void RussianCube::Change(void)
{
	switch(m_iShape)
	{
	case 1:case 2:
		if(m_ptMain.x <= 120)
		{
			if(m_iShape == 1)
			{
				m_iShape = 2;
			}
			else
			{
				m_iShape = 1;
			}
		}
		break;

	case 3: case 4: case 5: case 6:
		if(m_ptMain.x <= 140)
		{
			m_iShape += 1;
		}
		if(m_iShape > 6)
		{
			m_iShape = 3;
		}
		break;

	case 7: case 8: case 9: case 10:
		if(m_ptMain.x <= 140)
		{
			m_iShape += 1;
		}
		if(m_iShape > 10)
		{
			m_iShape = 7;
		}
		break;

	case 11: case 12: case 13: case 14:
		if(m_ptMain.x <= 140)
		{
			m_iShape += 1;
		}
		if(m_iShape > 14)
		{
			m_iShape = 11;
		}
		break;

	case 15: case 16:
		if(m_ptMain.x <= 140)
		{
			if(m_iShape == 15)
			{
				m_iShape = 16;
			}
			else
			{
				m_iShape = 15;
			}
		}
		break;

	case 17: case 18:
		if(m_ptMain.x <= 140)
		{
			if(m_iShape == 17)
			{
				m_iShape = 18;
			}
			else
			{
				m_iShape = 17;
			}
		}
		break;

	default:							//
		break;
	}
}

//保存坐标
void RussianCube::SaveCoordinate(void)
{
	int iWidth = m_pCubePic[0]->GetWidth();
	int iHeight	= m_pCubePic[0]->GetHeight();

	for(int i = 0; i < 4; ++i)
	{
		m_pCube[m_ptCube[i].y / iHeight][m_ptCube[i].x / iWidth] = true;
	}

	//扫描方块,是否已经填满
	for(int y = m_iRow-1; y >= 0; --y)						//扫描Y轴
	{
		for(int x = 0; x < m_iColumn; ++x)					//扫描X轴
		{
			if(!m_pCube[y][x])//如果还有空白,				
			{
				break;
			}
		}

		if(x >= m_iColumn)// 如果没有空白,则消除这一行
		{
			PlaySound((LPCSTR)IDW_ELIMINATE,g_hInstance,SND_ASYNC | SND_RESOURCE);
			m_iScore += 10;			//得分增加
			for(int i = y; i > 0; --i)
			{
				for(int j = 0; j < m_iColumn; ++j)
				{
					m_pCube[i][j] = m_pCube[i-1][j];
				}
			}
			y++;
		}
	}
}

//计算坐标
void RussianCube::Calculation(void)
{
	int iTempShape = m_iShapeCode[m_iShape];		//译码
	int iBit;//取位
	int i = 0;
	int iWidth = m_pCubePic[0]->GetWidth();
	int iHeight = m_pCubePic[0]->GetHeight();
	while(iTempShape && i < 4)//计算四个方块的坐标
	{
		iBit = iTempShape % 16;
		m_ptCube[i].x = (iBit % 4) * iWidth + m_ptMain.x;
		m_ptCube[i].y = (iBit / 4) * iHeight + m_ptMain.y;
		++i;
		iTempShape /=16;
	}
	if(i <= 3)
	{
		m_ptCube[3].x = m_ptMain.x;
		m_ptCube[3].y = m_ptMain.y;
	}
}

//左右 或下移动方块
void RussianCube::SetDrection(int iDrection)
{
	PlaySound((LPCSTR)IDW_KEYS,g_hInstance,SND_ASYNC | SND_RESOURCE);
	int iWidth	= m_pCubePic[0]->GetWidth();
	int iHeight = m_pCubePic[0]->GetHeight();
	
	int iDown;				//向下的偏移量
	int iTemp = 0;			//各块向下量
	int i,iX,iY;

	switch(iDrection)
	{
	case LEFT:								//左移
		if(CanLeft())						//如果还能左移
		{
			m_ptMain.x	  -= iWidth;
			m_ptCube[0].x -= iWidth;
			m_ptCube[1].x -= iWidth;
			m_ptCube[2].x -= iWidth;
			m_ptCube[3].x -= iWidth;
		}
		break;
	case RIGHT:								//右移
		if(CanRight())						//如果还能左移
		{
			m_ptMain.x    += iWidth;
			m_ptCube[0].x += iWidth;
			m_ptCube[1].x += iWidth;
			m_ptCube[2].x += iWidth;
			m_ptCube[3].x += iWidth;
		}
		break;

	case CHANGE:						//变形
		Change();						//进行方块变换
		Calculation();					//重新计算坐标
		break;
		
	case DOWN:							//向下
		iDown = 40;						//向下偏移量为最大
		
		for( i = 0; i < 4; ++i)
		{
			 iY = m_ptCube[i].y / iHeight + 1;
			 iX = m_ptCube[i].x / iWidth;
			 iTemp = 0;
			while(iY < m_iRow && !m_pCube[iY][iX] )
			{
				++iY;
				++iTemp;
			}
			if(iTemp < iDown )
			{
				iDown = iTemp;
			}
		}
		m_ptMain.y	  += iDown * iHeight;
		m_ptCube[0].y += iDown * iHeight;
		m_ptCube[1].y += iDown * iHeight;
		m_ptCube[2].y += iDown * iHeight;
		m_ptCube[3].y += iDown * iHeight;

		break;
	default:
		break;
	}
}

//方块是否应该停止

bool RussianCube::ShouldStop(void)
{
	int iHeight = m_pCubePic[0]->GetHeight();
	int iWidth	= m_pCubePic[0]->GetWidth();
	for(int i = 0; i < 4; ++i)
	{
		int iY = m_ptCube[i].y / iHeight + 1;
		int iX = m_ptCube[i].x / iWidth;
		//取坐标
		if(iY == m_iRow)			//方块已经到窗口底部
		{
			return true;
		}
		else if(m_pCube[iY][iX])	//下面已经有方块
		{
			return true;
		}
	}
	return false;
}

//===============================================================================================
//游戏初始化
bool GameInitialize(HINSTANCE hInstance)
{
	//创建游戏引擎
	g_pGame = new GameEngine(hInstance,TEXT("RUSSIAN CUBE"),TEXT("RUSSIAN CUBE"),IDI_RUSSIAN,
		IDI_RUSSIAN_SM,300,400);
	if(g_pGame==NULL)
	{
		return false;
	}
	g_hInstance = hInstance;
	g_pGame->SetFrameRate(15);	//设置帧频
	
	return true;
}

//=================================================================================================
//游戏开始
void GameStart(HWND hWindow)
{
	srand(GetTickCount());	

	//20行,10列
	g_pRussian			= new RussianCube(20,10,hWindow);
}

//===================================================================================================
//游戏结束
void GameEnd(void)
{
	delete g_pGame;
	delete g_pRussian;
}

//=================================================================================================
//游戏绘制

void GamePaint(HDC hDC)
{
	g_pRussian->Draw(hDC);
}

//==================================================================================================
//游戏循环
void GameCycle(void)
{
	if(!g_pRussian->IsGameOver())
	{
		if(!g_pRussian->ShouldStop())		//如果方块还不应该停止
		{
			g_pRussian->FallDown();			//方块继续下落
		}
		else
		{
			g_pRussian->SaveCoordinate();	//保存小方块的坐标;
			
			//随机生成新的方块
			g_pRussian->Refresh();
		
		}
		InvalidateRect(g_pGame->GetWindow(),NULL,false);
	}
	else
	{
		PlaySound((LPCSTR)IDW_GAMEOVER,g_hInstance,SND_ASYNC | SND_RESOURCE);
		g_pGame->SetSleep(true);
		//TCHAR	szMessage[64];
		//wsprintf(szMessage,"GAME OVER !");
		//MessageBox(g_pGame->GetWindow(),szMessage,TEXT("俄罗斯方块"),MB_OK);
	}
}

//=================================================================================================
//激活与停用

void GameActivate(HWND hWindow)
{}
void GameDeactivate(HWND hWindow)
{}

//===================================================================================================
//处理键盘输入
void HandleKeys(void)
{
	if(GetAsyncKeyState(VK_LEFT) < 0)
	{
		g_pRussian->SetDrection(LEFT);
	}
	else if(GetAsyncKeyState(VK_RIGHT) < 0)
	{
		g_pRussian->SetDrection(RIGHT);
	}
	else if(GetAsyncKeyState(VK_UP) < 0)
	{
		g_pRussian->SetDrection(CHANGE);
	}
	else if(GetAsyncKeyState(VK_DOWN)< 0)
	{
		g_pRussian->SetDrection(DOWN);
	}
}

//===================================================================================================
//鼠标左键

void MouseButtonDown(int x, int y, bool bLeft)
{}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -