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

📄 minewnd.cpp

📁 Windows 经典游戏-扫雷 源码 VC6.0、VS2005、VS2008均编译通过
💻 CPP
📖 第 1 页 / 共 3 页
字号:
			{
				m_pMines[i][j].uState = STATE_EMPTY;
			}
			else if (m_pMines[i][j].uState == STATE_DICEY)
			{
				m_pMines[i][j].uState = STATE_DICEY_DOWN;
			}
		}
	}
}

void CMineWnd::OnLRBtnUp(UINT row, UINT col)
{
	UINT i, j;
	UINT minRow = (row == 0) ? 0 : row - 1;
	UINT maxRow = row + 2;
	UINT minCol = (col == 0) ? 0 : col - 1;
	UINT maxCol = col + 2;
	
	for (i = minRow; i < maxRow; i++) 
	{
		for (j = minCol; j < maxCol; j++)
		{
			if (!IsInMineArea(i, j)) continue;
			//			if (i == row && j == col) continue;
			if (m_pMines[i][j].uOldState == STATE_NORMAL) 
			{
				m_pMines[i][j].uState = STATE_NORMAL;
			}
			else if (m_pMines[i][j].uOldState == STATE_DICEY) 
			{
				m_pMines[i][j].uState = STATE_DICEY;
			}
		}
	}
	//	Invalidate();
}


//展开拓展周围8个方向
void CMineWnd::OpenAround(UINT row, UINT col)
{
	//如果周围相邻的标志雷数 != 周围相邻的雷数 则返回
	if (GetAroundFlags(row, col) != GetAroundNum(row, col)) return;

	UINT i, j;
	UINT around = 0;
	UINT minRow = (row == 0) ? 0 : row - 1;
	UINT maxRow = row + 2;
	UINT minCol = (col == 0) ? 0 : col - 1;
	UINT maxCol = col + 2;
	
	for (i = minRow; i < maxRow; i++) 
	{
		for (j = minCol; j < maxCol; j++) 
		{
			if (!IsInMineArea(i, j)) continue;
			if (m_pMines[i][j].uState == STATE_NORMAL) 
			{//如果该区域为正常区域

				//拓展该雷区
				ExpandMines(i, j);
				around = GetAroundNum(i, j);
				m_pMines[i][j].uState = 15 - around;
				m_pMines[i][j].uOldState = 15 - around;
			}
		}
	}

	// 判断是否胜利,是则将地图中所有雷标识出来
	if (Victory())
	{
		for (i = 0; i < m_uYNum; i++) 
		{
			for (j = 0; j < m_uXNum; j++)
			{
				if (m_pMines[i][j].uAttrib == ATTRIB_MINE)
				{
					m_pMines[i][j].uState = STATE_FLAG;
					m_pMines[i][j].uOldState = STATE_FLAG;
				}
			}
		}
		m_nLeaveNum = 0;
		Invalidate();
	}
}

BOOL CMineWnd::ErrorAroundFlag(UINT row, UINT col)
{
		//如果周围相邻的标志雷数 != 周围相邻的雷数 则返回
	if (GetAroundFlags(row, col) != GetAroundNum(row, col)) return FALSE;

	UINT i, j;
	UINT minRow = (row == 0) ? 0 : row - 1;
	UINT maxRow = row + 2;
	UINT minCol = (col == 0) ? 0 : col - 1;
	UINT maxCol = col + 2;
	
	for (i = minRow; i < maxRow; i++) 
	{
		for (j = minCol; j < maxCol; j++) 
		{
			if (!IsInMineArea(i, j)) continue;
			if (m_pMines[i][j].uState == STATE_FLAG)
			{
				if (m_pMines[i][j].uAttrib != ATTRIB_MINE)
				{
					Dead(i, j);
					return TRUE;
				}
			}
		}
	}
	
	return FALSE;
}

void CMineWnd::OpenByCheat()
{
	UINT i, j;
	for (i = 0; i < m_uYNum; i++)
	{
		for (j = 0; j < m_uXNum; j++)
		{
			if (m_pMines[i][j].uState == STATE_FLAG) continue;
			OpenAround(i, j);
		}
	}
}

void CMineWnd::FreeMines()
{
	//	if (m_pMines) {
	//		delete[] m_pMines;
	//		m_pMines = NULL;
	//	}
	//	for (UINT row = 0; row<m_uYNum; row++) {
	//		if (m_pMines[row]) {
	//			delete []m_pMines[m_uXNum];
	//			delete m_pMines[row];
	//		}
	//	}
}

void CMineWnd::SizeWindow( void )
{
	UINT uWidth = DEFAULT_FRAME_X + m_uXNum * MINE_WIDTH +
		LINE_WIDTH_0 * 3 + SIDE_WIDTH_0 + SIDE_WIDTH_1; 
	UINT uHeight = DEFAULT_FRAME_Y + m_uYNum * MINE_HEIGHT + 
		LINE_WIDTH_0 * 3 + SIDE_WIDTH_0 * 2 + SIDE_WIDTH_1 + SHELL_S_H;	
	SetWindowPos(&wndTopMost, 0, 0, uWidth, uHeight, 
		SWP_NOZORDER | SWP_NOMOVE | SWP_NOCOPYBITS);	// SWP_NOCOPYBITS does not do function???
	
	GetClientRect(&m_rcClient);
	// Button Position
	m_uBtnRect[0] = m_rcClient.right / 2 - 12;			// the left side of the start(state) button without 3d border
	m_uBtnRect[1] = m_rcClient.right / 2 - 13;			// the left side of the start(state) button with 3d border
	m_uBtnRect[2] = m_rcClient.right / 2 + 12;			// the right side of the start(state) button 
	
	// Number Position
	m_uNumRect[0] = m_rcClient.right - 55;				// the left side of the spend time rect	with 3d border
	m_uNumRect[1] = m_rcClient.right - 15;				// the right side of the spend time rect
	m_uNumRect[2] = m_rcClient.right - 54;				// the left side of the spend time rect without 3d border
	//	m_uNumRect[3] = m_rcClient.right - 41;
	//	m_uNumRect[4] = m_rcClient.right - 28;	
	
	// Shell Position
	m_uShellRcX[0] = m_rcClient.right;					//
	m_uShellRcX[1] = m_rcClient.right - 14;				// the width of the small(big) shell
	
	m_uShellRcY[0] = m_rcClient.bottom;					// 
	m_uShellRcY[1] = m_rcClient.bottom - SHELL_L_START_Y - 5;		// the height of the big shell
}

//
// 绘制笑脸按钮图
//
void CMineWnd::DrawButton(CPaintDC &dc)
{
	CDC cdc;	
	cdc.CreateCompatibleDC(&dc);
	cdc.SelectObject(m_bmpButton);	
	dc.StretchBlt(m_uBtnRect[0], 16, 24, 24, &cdc, 0, 24 * m_uBtnState, 24, 24, SRCCOPY);
	
	dc.Draw3dRect(m_uBtnRect[1], 15, 26, 26, m_clrDark, m_clrDark);
	
}

//
// 绘制数字
//
void CMineWnd::DrawNumber(CPaintDC &dc)
{
	CDC dcMemory;	
	dcMemory.CreateCompatibleDC(&dc);
	dcMemory.SelectObject(m_bmpNumber);
	
	dc.Draw3dRect(16, 15, 41, 25, m_clrDark, COLOR_WHITE);
	dc.Draw3dRect(m_uNumRect[0], 15, 41, 25, m_clrDark, COLOR_WHITE);
	int num;
	
	// draw remaining mine numbers
	num = (m_nLeaveNum<0) ? 11 : m_nLeaveNum/100;
	dc.StretchBlt(17, 16, 13, 23, &dcMemory, 0, 276-23*(num+1), 13, 23, SRCCOPY);
	num = (m_nLeaveNum < 0) ? -(m_nLeaveNum-num*100)/10 : (m_nLeaveNum-num*100)/10;
	dc.StretchBlt(30, 16, 13, 23, &dcMemory, 0, 276-23*(num+1), 13, 23, SRCCOPY);
	num = (m_nLeaveNum<0) ? -m_nLeaveNum%10 : m_nLeaveNum%10;
	dc.StretchBlt(43, 16, 13, 23, &dcMemory, 0, 276-23*(num+1), 13, 23, SRCCOPY);
	
	// draw take seconds
	num = m_uSpendTime / 100;
	dc.StretchBlt(m_uNumRect[0], 16, 13, 23, &dcMemory, 0, 276-23*(num+1), 13, 23, SRCCOPY);
	num = (m_uSpendTime-num*100)/10;
	dc.StretchBlt(m_uNumRect[0] + 13, 16, 13, 23, &dcMemory, 0, 276-23*(num+1), 13, 23, SRCCOPY);
	num = m_uSpendTime%10;
	dc.StretchBlt(m_uNumRect[0]+26, 16, 13, 23, &dcMemory, 0, 276-23*(num+1), 13, 23, SRCCOPY);
}

//
// 绘制外壳
//
void CMineWnd::DrawShell(CPaintDC &dc)
{
	// 绘画2条白条
	dc.FillSolidRect(0, 0, m_uShellRcX[0], LINE_WIDTH_0, COLOR_WHITE);
	dc.FillSolidRect(0, 0, LINE_WIDTH_0, m_uShellRcY[0], COLOR_WHITE);
	
	// 画小的外壳
	dc.Draw3dRect(SHELL_S_START_X, SHELL_S_START_Y, 
		m_uShellRcX[1], SHELL_S_H, m_clrDark, COLOR_WHITE);
	dc.Draw3dRect(SHELL_S_START_X + 1, SHELL_S_START_Y + 1, 
		m_uShellRcX[1] - 2, SHELL_S_H - 2, m_clrDark, COLOR_WHITE);
	
	// 画大的外壳
	dc.Draw3dRect(SHELL_L_START_X, SHELL_L_START_Y,
		m_uShellRcX[1], m_uShellRcY[1], m_clrDark, COLOR_WHITE);
	dc.Draw3dRect(SHELL_L_START_X + 1, SHELL_L_START_Y + 1,
		m_uShellRcX[1] - 2, m_uShellRcY[1] - 2, m_clrDark, COLOR_WHITE);
	dc.Draw3dRect(SHELL_L_START_X + 2, SHELL_L_START_Y + 2, 
		m_uShellRcX[1] - 4, m_uShellRcY[1] - 4, m_clrDark, COLOR_WHITE);
}

//
// 绘制雷区
//
void CMineWnd::DrawMineArea(CPaintDC &dc)
{
	CDC dcMemory; //用作内存设备
	dcMemory.CreateCompatibleDC(&dc); //使得这个设备与dc兼容
	dcMemory.SelectObject(m_bmpMine); //将内存设备与位图资源关联
	
	for (UINT i = 0; i<m_uYNum; i++) 
	{
		for (UINT j = 0; j<m_uXNum; j++) 
		{//根据[i][j]区域的雷方块状态拷贝相应的图像到[i][j]雷区的特定区域
			dc.StretchBlt(MINEAREA_FRAME_X+16*j, MINEAREA_FRAME_Y+16*i, 
				16, 16, &dcMemory, 0, 16*m_pMines[i][j].uState, 16, 16, SRCCOPY);
		}
	}
}

//
// 绘制按下扫雷后的数字
//
void CMineWnd::DrawDownNum(MINEWND* mine, UINT num)
{
	mine->uState = 15 - num;
	mine->uOldState = 15 - num;
	CRect rcMine(mine->uCol * 16, mine->uRow * 16, (mine->uCol+1) *16, (mine->uRow+1) * 16);
	InvalidateRect(rcMine);
}

//重新绘制雷区域的某个方块
void CMineWnd::DrawSpecialMine(UINT row, UINT col)
{
	CRect rcMine(col * 16, row * 16, (col+1) * 16, (row+1) * 16);
	InvalidateRect(rcMine);
}

//
//  获取体图中(x,y)区域的雷信息
//
MINEWND* CMineWnd::GetMine(long x, long y)
{
	//保证参数合格
	if (x < MINEAREA_FRAME_X || y < MINEAREA_FRAME_Y) 
	{
		return NULL;
	}

	//根据坐标值算出该小方块所在地图的行和列
	UINT uCol = (UINT)(x-MINEAREA_FRAME_X) / 16;
	UINT uRow = (UINT)(y-MINEAREA_FRAME_Y) / 16;
	//返回该区域的雷信息
	return &m_pMines[uRow][uCol];
}

void CMineWnd::SetCheckedLevel()
{
	if (m_pSubMenu)
	{
		m_pSubMenu->CheckMenuItem(IDM_PRIMARY, MF_UNCHECKED | MF_BYCOMMAND);
		m_pSubMenu->CheckMenuItem(IDM_SECOND, MF_UNCHECKED | MF_BYCOMMAND);
		m_pSubMenu->CheckMenuItem(IDM_ADVANCE, MF_UNCHECKED | MF_BYCOMMAND);
		m_pSubMenu->CheckMenuItem(IDM_CUSTOM, MF_UNCHECKED | MF_BYCOMMAND);
		switch(m_uLevel)
		{
		case LEVEL_PRIMARY:
			m_pSubMenu->CheckMenuItem(IDM_PRIMARY, MF_CHECKED | MF_BYCOMMAND);
			break;
		case LEVEL_SECONDRY:
			m_pSubMenu->CheckMenuItem(IDM_SECOND, MF_CHECKED | MF_BYCOMMAND);
			break;
		case LEVEL_ADVANCE:
			m_pSubMenu->CheckMenuItem(IDM_ADVANCE, MF_CHECKED | MF_BYCOMMAND);
			break;
		case LEVEL_CUSTOM:
			m_pSubMenu->CheckMenuItem(IDM_CUSTOM, MF_CHECKED | MF_BYCOMMAND);
			break;
		default: 
			break;
		}
	}
}

void CMineWnd::SetCheckedMark()
{
	if (m_pSubMenu) {
		if (m_bMarkful) {
			m_pSubMenu->CheckMenuItem(IDM_MARK, MF_CHECKED | MF_BYCOMMAND);
		}
		else {
			m_pSubMenu->CheckMenuItem(IDM_MARK, MF_UNCHECKED | MF_BYCOMMAND);
		}
	}
}

void CMineWnd::SetCheckedColor()
{
	if (m_pSubMenu)
	{
		if (m_bColorful)
		{
			m_pSubMenu->CheckMenuItem(IDM_COLOR, MF_CHECKED | MF_BYCOMMAND);
		}
		else 
		{
			m_pSubMenu->CheckMenuItem(IDM_COLOR, MF_UNCHECKED | MF_BYCOMMAND);
		}
	}
}

void CMineWnd::SetCheckedSound()
{
	if (m_pSubMenu)
	{
		if (m_bSoundful) 
		{
			m_pSubMenu->CheckMenuItem(IDM_SOUND, MF_CHECKED | MF_BYCOMMAND);
		}
		else 
		{
			m_pSubMenu->CheckMenuItem(IDM_SOUND, MF_UNCHECKED | MF_BYCOMMAND);
		}
	}
}

void CMineWnd::SetCheckedCheat()
{
	if (m_pSubMenu)
	{
//		if (m_bCheat) 
//		{
//			m_pSubMenu->CheckMenuItem(IDM_CHEAT, MF_CHECKED | MF_BYCOMMAND);
//		}
	//	else 
//		{
			m_pSubMenu->CheckMenuItem(IDM_CHEAT, MF_UNCHECKED | MF_BYCOMMAND);
//		}
	}
}

void CMineWnd::LoadWaveSrc()
{
	HMODULE hMdl;
	hMdl = AfxGetResourceHandle();
	HRSRC hSrc;
	
	hSrc = FindResource(hMdl, MAKEINTRESOURCE(IDR_WAVE_DEAD), _T("WAVE"));
	m_pSndDead = LoadResource(hMdl, hSrc);
	hSrc = FindResource(hMdl, MAKEINTRESOURCE(IDR_WAVE_VICTORY), _T("WAVE"));
	m_pSndVictory = LoadResource(hMdl, hSrc);
	hSrc = FindResource(hMdl, MAKEINTRESOURCE(IDR_WAVE_CLOCK), _T("WAVE"));
	m_pSndClock = LoadResource(hMdl, hSrc);
}

void CMineWnd::FreeWaveSrc()
{
	if (m_pSndDead)
	{
		FreeResource(m_pSndDead);
		m_pSndDead = NULL;
	}
	if (m_pSndVictory) 
	{
		FreeResource(m_pSndVictory);
		m_pSndVictory = NULL;
	}
	if (m_pSndClock)
	{
		FreeResource(m_pSndClock);
		m_pSndClock = NULL;
	}
}

void CMineWnd::ResetRecord()
{
	m_uPrimary = DEFAULT_RECORD;
	m_szPrimary = DEFAULT_HOLDER;
	m_uSecond= DEFAULT_RECORD;
	m_szSecond = DEFAULT_HOLDER;
	m_uAdvance = DEFAULT_RECORD;
	m_szAdvance = DEFAULT_HOLDER;
}

void CMineWnd::SetCustom(UINT xNum, UINT yNum, UINT mNum)
{
	m_uXNum = xNum;
	m_uYNum = yNum;
	m_uMineNum = mNum;
}

void CMineWnd::OnPaint() 
{

	CPaintDC dc(this);    // 用以屏幕显示的设备
	CDC dcMemory;  // 内存设备

	CBitmap bitmap;

	if (!dc.IsPrinting()) 
	{

		// 与dc设备兼容
		if (dcMemory.CreateCompatibleDC(&dc))
		{	
			// 使得bitmap与实际显示的设备兼容
			if (bitmap.CreateCompatibleBitmap(&dc, m_rcClient.right, m_rcClient.bottom))
			{
				// 内存设备选择物件-位图
				dcMemory.SelectObject(&bitmap);
				//绘制背景框
				dcMemory.FillRect(&m_rcClient, &m_brsBG);
				
				DrawButton((CPaintDC&) dcMemory);//笑脸按钮绘图
				DrawNumber((CPaintDC&) dcMemory);//文字绘图(计时器文字和剩余雷数文字)
				DrawShell((CPaintDC&) dcMemory);//3D效果外壳绘图
				DrawMineArea((CPaintDC&) dcMemory);//雷区绘图


				// 将内存设备的内容拷贝到实际屏幕显示的设备
				dc.BitBlt(m_rcClient.left, m_rcClient.top, m_rcClient.right, m_rcClient.bottom, &dcMemory, 0, 0, SRCCOPY);
				bitmap.DeleteObject();
			}
		}
	}
}

void CMineWnd::OnShowWindow(BOOL bShow, UINT nStatus) 
{
	SizeWindow();
	CWnd::OnShowWindow(bShow, nStatus);
}

void CMineWnd::OnTimer(UINT nIDEvent) 
{
	if (nIDEvent == ID_TIMER_EVENT)
	{
		if (m_bSoundful) 
		{
			sndPlaySound((LPCTSTR)LockResource(m_pSndClock), SND_MEMORY | SND_ASYNC | SND_NODEFAULT);
		}
		m_uSpendTime++;
		CRect rcNum(m_uNumRect[0], 15, m_uNumRect[1], 39);
	//	InvalidateRect(rcNum);
		Invalidate();
		if (m_uSpendTime >= DEFAULT_RECORD) 
		{
			KillTimer(ID_TIMER_EVENT);
			m_uTimer = 0;
		}
	}
	
	CWnd::OnTimer(nIDEvent);
}

void CMineWnd::OnLButtonDown(UINT nFlags, CPoint point) 
{
	//按钮所在的区域
	CRect rcBtn(m_uBtnRect[1], 15, m_uBtnRect[2], 39);
	//雷区所在的区域
	CRect rcMineArea(MINE_AREA_LEFT, MINE_AREA_TOP, 
		MINE_AREA_LEFT + m_uXNum * MINE_WIDTH, MINE_AREA_TOP + m_uYNum * MINE_HEIGHT);
	
	SetCapture();			// capture the mouse cursor
	m_bClickBtn = FALSE;
	m_bLRBtnDown = FALSE;

	if (rcBtn.PtInRect(point)) 
	{// click in the button area
		m_bClickBtn = TRUE;
		m_uBtnState = BUTTON_DOWN;
		InvalidateRect(rcBtn);
	}
	else if (rcMineArea.PtInRect(point))
	{// click in the mine area
		// change mine state by gamestate
		switch(m_uGameState) 
		{						
		case GS_WAIT: case GS_RUN:
			m_pNewMine = GetMine(point.x, point.y);
			if (!m_pNewMine) return;
			if (m_pNewMine->uState == STATE_NORMAL)
			{
				m_pNewMine->uState = STATE_EMPTY;
			}
			if (m_pNewMine->uState == STATE_DICEY)
			{
				m_pNewMine->uState = STATE_DICEY_DOWN;
			}
			m_pOldMine = m_pNewMine;
			break;
		case GS_DEAD: case GS_VICTORY:
			return;
			break;
		default :
			break;
		}
		m_uBtnState = BUTTON_CLICK;

⌨️ 快捷键说明

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