2048游戏控制及绘制源码

2 篇文章 0 订阅
2 篇文章 0 订阅

数据定义:

2048游戏界面如下,界面为一个4乘4的方格,在游戏设计中定义一个16个元素的数组即可,因为每个格子有多个游戏属性,比如数值,颜色,方格坐标中心位置等,方格行列编号,这里定义了以下的数据结构:

class CGameNumBlock
{
public:
	int m_iBlockID;
	int m_iGameNumShow;
	CRect m_RectBlock;
	int   m_iFlashCount;
};

 

游戏方块颜色值的映射表,每种数字对应一个颜色:

map<int,COLORREF> g_mapColor;

g_mapColor[0] = RGB(205,194,181);

g_mapColor[2] = RGB(238,226,213);

g_mapColor[4] = RGB(238,222,197);

g_mapColor[8] = RGB(238,178,115);

g_mapColor[16] = RGB(246,149,98);

g_mapColor[32] = RGB(246,125,90);

g_mapColor[64] = RGB(246,93,49);

g_mapColor[128] = RGB(238,206,106);

游戏启动时方块坐标及数值的初始化:

CRect rectCore;
	m_wndCore.GetClientRect(rectCore);
	m_BlockGapX = 10;
	m_BlockGapY = 8;
	m_BlockWidth = (rectCore.Width() - m_BlockGapX*5)/4;
	m_BlockHeight = (rectCore.Height() -m_BlockGapY*5)/4;
	int iLeftX(0),iLeftY(0);
	for (int i=0;i<4;i++) // 行
	{
		iLeftY = ((1+i)*m_BlockGapY + i*m_BlockHeight);
		iLeftX = 0;
		for (int j=0;j<4;j++) // 列
		{
			iLeftX = ((j+1)*m_BlockGapX + j*m_BlockWidth);
			m_RectBlocks[i*4+j].m_RectBlock = CRect(CPoint(iLeftX,iLeftY),CSize(m_BlockWidth,m_BlockHeight));
			m_RectBlocks[i*4+j].m_iBlockID = i*4+j;
			m_RectBlocks[i*4+j].m_iGameNumShow = 0;
			m_RectBlocks[i*4+j].m_iFlashCount  = 0;
		}
	}

void CGame2048Dlg::IntilizeGame()
{
	for (int i=0;i<16;i++)
	{
		m_RectBlocks[i].m_iGameNumShow = 0;
	}
	// 随机选两块数字重置为2
	static int iIDArry[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};

	vector<int> vIds(16,0);
	std::copy(iIDArry,iIDArry+16,vIds.begin());
	vector<int>::iterator iter = vIds.begin();
	int iBlockID[2] = {0,0};
	iBlockID[0] = vIds[rand()%16];
	iter += iBlockID[0];
	vIds.erase(iter);
	iBlockID[1] = vIds[rand()%15];

	m_RectBlocks[iBlockID[0]].m_iGameNumShow = 2;
	m_RectBlocks[iBlockID[1]].m_iGameNumShow = 2;

	GetDlgItem(IDC_STATIC_ADD_SCORE)->SetWindowText("");

	m_GameCtrler.SetSumScore(0);
	GetDlgItem(IDC_STATIC_SUM_SCORE)->SetWindowText("当前总分:0");

}

上下左右移动的事件处理:

BOOL CGame2048Dlg::PreTranslateMessage(MSG* pMsg)
{
	// TODO: 在此添加专用代码和/或调用基类
	if (pMsg->message == WM_KEYDOWN)
	{
		if(pMsg-> wParam == VK_LEFT|| pMsg-> wParam == 'A') 
			m_GameCtrler.MoveLeft();
		else if(pMsg-> wParam == VK_RIGHT|| pMsg-> wParam == 'D')
			m_GameCtrler.MoveRight();
		else if(pMsg-> wParam == VK_UP || pMsg-> wParam == 'W')
			m_GameCtrler.MoveUp();
		else if(pMsg-> wParam == VK_DOWN|| pMsg-> wParam == 'S')
			m_GameCtrler.MoveDown();
		else if (pMsg->wParam == VK_ESCAPE)
			TRUE;
		else
			return CBCGPDialog::PreTranslateMessage(pMsg);

		CString strAddScore;
		strAddScore.Format("+%d",m_GameCtrler.GetAddScore());
		GetDlgItem(IDC_STATIC_ADD_SCORE)->SetWindowText(strAddScore);

		CString strSumSocre;
		strSumSocre.Format("当前总分:%d",m_GameCtrler.GetSumScore());
		GetDlgItem(IDC_STATIC_SUM_SCORE)->SetWindowText(strSumSocre);
		return TRUE;
	}

	return CBCGPDialog::PreTranslateMessage(pMsg);
}

控制器完整源码:

CGameCtrler::CGameCtrler(CGame2048Dlg * pMainWnd)
{
	m_pMainWnd = pMainWnd;
	m_iSumScore = 0;
	m_iCurScore = 0;
	srand(time(NULL));
}
CGameCtrler::~CGameCtrler(void)
{
}
void CGameCtrler::MoveUp()
{
	RestoreStatus();
	m_iCurScore = 0;
	for (int j=0;j<4;j++)
		ProcessOneColumToUp(j);

	MakeNewBlockInEmptyErea();
	m_pMainWnd->Invalidate(FALSE);
}
void CGameCtrler::MoveRight()
{
	RestoreStatus();
	m_iCurScore = 0;
	for (int j=0;j<4;j++)
		ProcessOneRowToRight(j);

	MakeNewBlockInEmptyErea();
	m_pMainWnd->Invalidate(FALSE);
}
void CGameCtrler::MoveLeft()
{
	RestoreStatus();
	m_iCurScore = 0;
	for (int j=0;j<4;j++)
		ProcessOneRowToLeft(j);

	MakeNewBlockInEmptyErea();
	m_pMainWnd->Invalidate(FALSE);
}
void CGameCtrler::MoveDown()
{
	RestoreStatus();
	m_iCurScore = 0;
	for (int j=0;j<4;j++)
		ProcessOneColumToDown(j);

	MakeNewBlockInEmptyErea();
	m_pMainWnd->Invalidate(FALSE);
}
void CGameCtrler::MakeNewBlockInEmptyErea()
{
	vector<int> vEmptyID;
	for (int i=0;i<16;i++)
	{
		if (m_pMainWnd->m_RectBlocks[i].m_iGameNumShow ==0)
			vEmptyID.push_back(i);
	}
	if (vEmptyID.empty())
	{
		//if (IsGameOver()) // 不能产生空白
		//	MessageBox(m_pMainWnd->m_hWnd,"游戏结束!","提示",MB_OK|MB_ICONINFORMATION|MB_TOPMOST);
		return;
	}
	if (!StatusChanged())
		return;

	int iIndex = rand()%vEmptyID.size();
	int iNewID = vEmptyID[iIndex]; // 的到新数字块的id

	int iNewNum = (rand()%8)==7 ? 4:2; // 新生成2或者4
	m_pMainWnd->m_RectBlocks[iNewID].m_iGameNumShow = iNewNum;
	m_pMainWnd->m_RectBlocks[iNewID].m_iFlashCount = FLASH_COUNT;
	m_iFlashBlockID = iNewID;
	m_pMainWnd->SetTimer(TIMER_FLASH_BLOCK,TIMER_SPACE_FLASH,NULL);
	if (IsGameOver()) // 不能产生空白
		MessageBox(m_pMainWnd->m_hWnd,"游戏结束!","提示",MB_OK|MB_ICONINFORMATION|MB_TOPMOST);
}
void CGameCtrler::ProcessOneColumToDown(int iColumId)
{
	BlockNode node[4];
	for (int i=0;i<4;i++)
	{
		int iId =(3-i)*4 + iColumId;
		int iNum = m_pMainWnd->m_RectBlocks[iId].m_iGameNumShow;

		node[i].m_iID = iId;
		node[i].m_iShowNum = iNum;
		if (i<3)
			node[i].m_pNextBlock = &node[i+1];
	}

	ProcessDataListNode(node);
	for (int i=0;i<4;i++)
	{
		int iId =(3-i)*4 + iColumId;
		m_pMainWnd->m_RectBlocks[iId].m_iGameNumShow = node[i].m_iShowNum;
	}
}
void CGameCtrler::ProcessOneColumToUp(int iColumId)
{
	BlockNode node[4];
	for (int i=0;i<4;i++)
	{
		int iId = i*4 + iColumId;
		int iNum = m_pMainWnd->m_RectBlocks[iId].m_iGameNumShow;

		node[i].m_iID = iId;
		node[i].m_iShowNum = iNum;
		if (i<3)
			node[i].m_pNextBlock = &node[i+1];
	}

	ProcessDataListNode(node);
	for (int i=0;i<4;i++)
	{
		int iId = i*4 + iColumId;
		m_pMainWnd->m_RectBlocks[iId].m_iGameNumShow = node[i].m_iShowNum;
	}
}
void CGameCtrler::ProcessOneRowToLeft(int iRowId)
{
	BlockNode node[4];
	for (int i=0;i<4;i++) // 列循环
	{
		int iId = iRowId*4 + i;
		int iNum = m_pMainWnd->m_RectBlocks[iId].m_iGameNumShow;

		node[i].m_iID = iId;
		node[i].m_iShowNum = iNum;
		if (i<3)
			node[i].m_pNextBlock = &node[i+1];
	}

	ProcessDataListNode(node);
	for (int i=0;i<4;i++) // 列循环
	{
		int iId = iRowId*4 + i;
		m_pMainWnd->m_RectBlocks[iId].m_iGameNumShow = node[i].m_iShowNum;
	}
}
void CGameCtrler::ProcessOneRowToRight(int iRowId)
{
	BlockNode node[4];
	for (int i=0;i<4;i++) // 列循环
	{
		int iId = iRowId*4 +(3-i);
		int iNum = m_pMainWnd->m_RectBlocks[iId].m_iGameNumShow;

		node[i].m_iID = iId;
		node[i].m_iShowNum = iNum;
		if (i<3)
			node[i].m_pNextBlock = &node[i+1];
	}

	ProcessDataListNode(node);
	for (int i=0;i<4;i++) // 列循环
	{
		int iId = iRowId*4 +(3-i);
		m_pMainWnd->m_RectBlocks[iId].m_iGameNumShow = node[i].m_iShowNum;
	}
}
void CGameCtrler::ProcessDataListNode(BlockNode * pNodeHeader)
{
	// 移动紧促
	BlockNode *pNodeCur = pNodeHeader;
	vector<int> vNums(4,0);
	int iIndexNoneZero = 0;
	while(pNodeCur)
	{
		if (pNodeCur->m_iShowNum!=0)
		{
			vNums[iIndexNoneZero] = pNodeCur->m_iShowNum;
			iIndexNoneZero++;
		}
		pNodeCur = pNodeCur->m_pNextBlock;
	}
	pNodeCur = pNodeHeader;
	int i = 0;
	while(pNodeCur)
	{
		pNodeCur->m_iShowNum = vNums[i];
		pNodeCur = pNodeCur->m_pNextBlock;
		i++;
	}
	// 检查相加
	BOOL bAddSuccess = FALSE;
	for (int i=0;i<3;i++)
	{
		if (vNums[i] == vNums[i+1] && vNums[i]!=0)
		{
			vNums[i] += vNums[i+1];
			vNums[i+1] = 0;
			m_iCurScore += vNums[i];
			m_iSumScore += vNums[i];
			bAddSuccess = TRUE;
			i++;
		}
	}

	if (bAddSuccess) // 相邻的相加成功
	{
		vector<int> vNumTmp(4,0);
		iIndexNoneZero = 0;
		for (int i=0;i<4;i++)
		{
			if (vNums[i]!=0)
				vNumTmp[iIndexNoneZero++] = vNums[i];
		}
		vNums.clear();
		vNums = vNumTmp;

		pNodeCur = pNodeHeader;
		int i = 0;
		while(pNodeCur)
		{
			pNodeCur->m_iShowNum = vNums[i];
			pNodeCur = pNodeCur->m_pNextBlock;
			i++;
		}
	}
}
BOOL CGameCtrler::IsGameOver()
{ 
	// 检查每一行是否有可相加的或者有空白位置
	for (int i=0;i<4;i++)
	{
		int iPreNum = m_pMainWnd->m_RectBlocks[i*4].m_iGameNumShow;
		if (iPreNum==0)
			return FALSE;

		for (int j=1;j<4;j++)
		{
			int iCurNum = m_pMainWnd->m_RectBlocks[i*4 + j].m_iGameNumShow;
			if (iCurNum==0 || iPreNum==iCurNum)
				return FALSE;

			iPreNum = iCurNum;
		}
	}

	// 检查每一列是否有可相加的
	for (int j=0;j<4;j++)
	{
		int iPreNum = m_pMainWnd->m_RectBlocks[j].m_iGameNumShow;
		if (iPreNum==0)
			return FALSE;

		for (int i=1;i<4;i++)
		{
			int iCurNum = m_pMainWnd->m_RectBlocks[i*4 + j].m_iGameNumShow;
			if (iCurNum==0 || iPreNum==iCurNum)
				return FALSE;

			iPreNum = iCurNum;
		}
	}

	return TRUE;
}
void  CGameCtrler::RestoreStatus()
{
	for(int i=0;i<16;i++)
		m_iRestoreStatus[i] = m_pMainWnd->m_RectBlocks[i].m_iGameNumShow;
}
BOOL CGameCtrler::StatusChanged()
{
	for(int i=0;i<16;i++)
		if(m_iRestoreStatus[i] != m_pMainWnd->m_RectBlocks[i].m_iGameNumShow)
			return TRUE;

	return FALSE;
}
void CGameCtrler::UpdateFlashTimeCount()
{
	m_pMainWnd->m_RectBlocks[m_iFlashBlockID].m_iFlashCount --;
	if (m_pMainWnd->m_RectBlocks[m_iFlashBlockID].m_iFlashCount==0)
	{
		m_pMainWnd->KillTimer(TIMER_FLASH_BLOCK);
	}
}

主窗口MainGlg中需要定义游戏数据和控制器:

CGameNumBlock   m_RectBlocks[16];

CGameCtrler m_GameCtrler;

视图更新及绘制:

void  CGame2048Dlg::DrawBlocks(CDC & dc)
{
	for (int i=0;i<16;i++)
	{
		DrawBlock(dc,i);
	}
}
void CGame2048Dlg::DrawBlock(CDC & dc,const int & iBlockID)
{
	CRect rectBlock = m_RectBlocks[iBlockID].m_RectBlock;
	int  iShowNum = m_RectBlocks[iBlockID].m_iGameNumShow;
	if (iShowNum  ==0)
	{
		CBrush brush(g_ColorNullBlock);
		dc.FillRect(rectBlock,&brush);
		return;
	}
	if (m_RectBlocks[iBlockID].m_iFlashCount > 0)
	{
		int iW = m_RectBlocks[iBlockID].m_iFlashCount*FLASH_INFALTE_PIXEL;
		int iH = m_RectBlocks[iBlockID].m_iFlashCount*FLASH_INFALTE_PIXEL;
		rectBlock.InflateRect(-iW,-iH,-iW,-iH);
	}
	int iTemp =iShowNum > 128 ? 128:iShowNum;
	CBrush brush(g_mapColor[iTemp]);
	dc.FillRect(rectBlock,&brush);
}

// paint 函数中调用DrawBlocks
        CDC MemDC;
		MemDC.CreateCompatibleDC(&dc);

		CRect rectCore;
		m_wndCore.GetClientRect(rectCore);

		CBitmap bitmap;
		bitmap.CreateCompatibleBitmap(&dc,rectCore.Width(),rectCore.Height());
		MemDC.SelectObject(&bitmap);

		CBrush brush(g_ColorBackGround);
		MemDC.FillRect(rectCore,&brush);
		DrawBlocks(MemDC);

 

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧校园整体解决方案是响应国家教育信息化政策,结合教育改革和技术创新的产物。该方案以物联网、大数据、人工智能和移动互联技术为基础,旨在打造一个安全、高效、互动且环保的教育环境。方案强调从数字化校园向智慧校园的转变,通过自动数据采集、智能分析和按需服务,实现校园业务的智能化管理。 方案的总体设计原则包括应用至上、分层设计和互联互通,确保系统能够满足不同用户角色的需求,并实现数据和资源的整合与共享。框架设计涵盖了校园安全、管理、教学、环境等多个方面,构建了一个全面的校园应用生态系统。这包括智慧安全系统、校园身份识别、智能排课及选课系统、智慧学习系统、精品录播教室方案等,以支持个性化学习和教学评估。 建设内容突出了智慧安全和智慧管理的重要性。智慧安全管理通过分布式录播系统和紧急预案一键启动功能,增强校园安全预警和事件响应能力。智慧管理系统则利用物联网技术,实现人员和设备的智能管理,提高校园运营效率。 智慧教学部分,方案提供了智慧学习系统和精品录播教室方案,支持专业级学习硬件和智能化网络管理,促进个性化学习和教学资源的高效利用。同时,教学质量评估中心和资源应用平台的建设,旨在提升教学评估的科学性和教育资源的共享性。 智慧环境建设则侧重于基于物联网的设备管理,通过智慧教室管理系统实现教室环境的智能控制和能效管理,打造绿色、节能的校园环境。电子班牌和校园信息发布系统的建设,将作为智慧校园的核心和入口,提供教务、一卡通、图书馆等系统的集成信息。 总体而言,智慧校园整体解决方案通过集成先进技术,不仅提升了校园的信息化水平,而且优化了教学和管理流程,为学生、教师和家长提供了更加便捷、个性化的教育体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值