📄 minewnd.cpp
字号:
{
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 + -