📄 minedlg.cpp
字号:
PaintControlBar();
}
void CMineDlg::OnFileExit()
{
// TODO: Add your command handler code here
m_SetState.RemoveAll();
m_OpenState.RemoveAll();
//m_State.DeleteObject();
delete this;
CDialog::OnClose();
}
void CMineDlg::OnClose()
{
// TODO: Add your message handler code here and/or call default
m_SetState.RemoveAll();
m_OpenState.RemoveAll();
//m_State.DeleteObject();
delete this;
CDialog::OnClose();
}
void CMineDlg::PaintClient()/////////////////////////////////////////雷区显示
{
CDC * pDC=GetDC();
// TODO: add draw code for native data here
int m_width;
int m_height;
int nYSrc; //见MSDN中的解释 //用于确定局部位图在总位图中的位置
CBitmap bitmap;
CDC dc;
bitmap.LoadBitmap(IDB_MYBITMAP);//都在这个总位图中取局部位图,所以先确定
dc.CreateCompatibleDC(pDC);
dc.SelectObject(&bitmap);
for(int i=0; i<m_HighNum; i++)//i for row
for(int j=0; j<m_WideNum; j++)//j for column
{
if(m_OpenState[i*m_WideNum+j] == UNOPENED)//未揭示
{
nYSrc = 0;
}
else if(m_OpenState[i*m_WideNum+j] == OPENED)//已揭示
{
switch(m_SetState[i*m_WideNum+j])
{
case MINE: nYSrc = 5*16; break;
case EMPTY: nYSrc = 15*16; break;
case 1: nYSrc = 14*16; break;
case 2: nYSrc = 13*16; break;
case 3: nYSrc = 12*16; break;
case 4: nYSrc = 11*16; break;
case 5: nYSrc = 10*16; break;
//default: cout<<"error !!!\n";
}
}
else if(m_OpenState[i*m_WideNum+j] == FLAG)
{
nYSrc = 1*16;
}
else if(m_OpenState[i*m_WideNum+j] == QUESTION)
{
nYSrc = 2*16;
}
else if(m_OpenState[i*m_WideNum+j] == WRONG)//出错
{
switch(m_SetState[i*m_WideNum+j])
{
case MINE: nYSrc = 5*16; break;
case EMPTY: nYSrc = 15*16; break;
case 1: nYSrc = 14*16; break;
case 2: nYSrc = 13*16; break;
case 3: nYSrc = 12*16; break;
case 4: nYSrc = 11*16; break;
case 5: nYSrc = 10*16; break;
//default: cout<<"error !!!\n";
}
}
else
{ nYSrc = 0; }
m_width = (16+1)*j;// "+1" 的原因是要把位图间的单象素间隔算上
m_height = m_BarHeight+(16+1)*i;
pDC->BitBlt(m_width,m_height,16,16,&dc,0,nYSrc,SRCCOPY);
} //CPoint(0,nYSrc)为局部位图左上角在总位图中位置
}
void CMineDlg::PaintControlBar()
{
IsGameFinished = AutoFinish();
if((IsGameFinished == TRUE)&(m_OpenState[0] != WRONG)) //如果游戏已经结束
{
m_MainButton->LoadBitmaps(IDB_FINISH,IDB_DOWN);//两个Bitmap分别是up与down的状态
m_MainButton->Invalidate();
}
if((IsGameFinished == TRUE)&(m_OpenState[0] == WRONG))
{
m_MainButton->LoadBitmaps(IDB_DEAD,IDB_DOWN);//两个Bitmap分别是up与down的状态
m_MainButton->Invalidate();
}
CDC* pDC = GetDC();
m_MineCounter->DisplayNumber(pDC);
m_Timer->DisplayNumber(pDC);
}
void CMineDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if(!m_MineRect.PtInRect(point) | (IsGameFinished == TRUE)) //点击在雷区外,或游戏结束
{
return;
}
m_MainButton->LoadBitmaps(IDB_NORMAL,IDB_DOWN);//两个Bitmap分别是up与down的状态
m_MainButton->Invalidate();
//int width = (int)ceil(point.x/(16+1)); // 这里int数相除,因为width从0开始
//int height = (int)ceil((point.y-m_BarHeight)/(16+1));
int width = point.x/(16+1);
int height = (point.y-m_BarHeight)/(16+1);
if(m_OpenState[height*m_WideNum+width] == FLAG)
return;
if(m_SetState[height*m_WideNum+width] == MINE)//出错
{
for (int i=0; i<m_HighNum; i++)// i for row
for(int j=0; j<m_WideNum; j++)// j for column
{
m_OpenState[i*m_WideNum+j] = WRONG; //10:表示出错
}
}
else if(m_SetState[height*m_WideNum+width] == EMPTY) // 此时要继续找出其相邻的空位图
{
ChainReaction(height,width);
}
else
{
m_OpenState[height*m_WideNum+width] = OPENED;
}
PaintClient(); // 此处可直接调用OnPaint()以达到重花功能,不解!!!!!!!
PaintControlBar();
CDialog::OnLButtonUp(nFlags, point);
return;
}
void CMineDlg::ChainReaction(int height,int width)//////////////////巡回揭示空格区
{
m_OpenState[height*m_WideNum+width] = OPENED;
BOOL m_continue = TRUE;
while(m_continue)
{
m_continue = FALSE;
for (int i=0; i<m_HighNum; i++)// i for row
for(int j=0; j<m_WideNum; j++)// j for column
{
if((m_OpenState[i*m_WideNum+j] == OPENED)&(m_SetState[i*m_WideNum+j] == EMPTY))
{
for(int row=i-1; row<=i+1; row++)
for(int col=j-1; col<=j+1; col++)
{
if((row>=0)&(row<m_HighNum)&(col>=0)&(col<m_WideNum))
{
if((m_SetState[row*m_WideNum+col] == EMPTY)&
(m_OpenState[row*m_WideNum+col] == UNOPENED))
{m_continue = TRUE;}
m_OpenState[row*m_WideNum+col] = OPENED;
//凡是空格周围的位图格(按规律不可能是雷)都将其揭示
}
}
}
}
}
}
void CMineDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
if(m_FirstBlick == FALSE)
m_FirstBlick = TRUE;//如果是第一次点击则标识该变量
if(!m_MineRect.PtInRect(point) | (IsGameFinished == TRUE)) //点击在雷区外,或游戏结束
{
return;
}
// TODO: Add your message handler code here and/or call default
//int width = (int)ceil(point.x/(16+1));
//int height = (int)ceil((point.y-m_BarHeight)/(16+1));
int width = point.x/(16+1);
int height = (point.y-m_BarHeight)/(16+1);
m_MainButton->LoadBitmaps(IDB_O,IDB_DOWN);//两个Bitmap分别是up与down的状态
m_MainButton->Invalidate();
if(m_OpenState[height*m_WideNum+width] == UNOPENED)
{
CDC * pDC=GetDC();
// TODO: add draw code for native data here
CBitmap bitmap;
CDC dc;
bitmap.LoadBitmap(IDB_MYBITMAP);
dc.CreateCompatibleDC(pDC);
dc.SelectObject(&bitmap);
int m_width = (16+1)*width;// "+1" 的原因是要把位图间的单象素间隔算上
int m_height = m_BarHeight+(16+1)*height;
int nYSrc = 15*16;
pDC->BitBlt(m_width,m_height,16,16,&dc,0,nYSrc,SRCCOPY);
}
CDialog::OnLButtonDown(nFlags, point);
return;
}
void CMineDlg::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CDialog::OnMouseMove(nFlags, point);
}
void CMineDlg::OnRButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CDialog::OnRButtonDown(nFlags, point);
}
void CMineDlg::OnRButtonUp(UINT nFlags, CPoint point)
{
if(!m_MineRect.PtInRect(point) | (IsGameFinished == TRUE)) //点击在雷区外,或游戏结束
{
return;
}
// TODO: Add your message handler code here and/or call default
//int width = (int)ceil(point.x/(16+1));
//int height = (int)ceil((point.y-m_BarHeight)/(16+1));
int width = point.x/(16+1);
int height = (point.y-m_BarHeight)/(16+1);
if(m_OpenState[height*m_WideNum+width] == UNOPENED)
{
m_OpenState[height*m_WideNum+width] = FLAG;
m_MineLeft = m_MineLeft - 1;
m_MineCounter->SetNumber(m_MineLeft);
}
else if(m_OpenState[height*m_WideNum+width] == FLAG)
{
m_OpenState[height*m_WideNum+width] = QUESTION;
m_MineLeft = m_MineLeft + 1;
m_MineCounter->SetNumber(m_MineLeft);
}
else if(m_OpenState[height*m_WideNum+width] == QUESTION)
{
m_OpenState[height*m_WideNum+width] = UNOPENED;
}
PaintClient();
PaintControlBar();
CDialog::OnRButtonUp(nFlags, point);
return;
}
void CMineDlg::OnLButtonDblClk(UINT nFlags, CPoint point) ////////////////////双击
{
if(!m_MineRect.PtInRect(point) | (IsGameFinished == TRUE)) //点击在雷区外,或游戏结束
{
return;
}
// TODO: Add your message handler code here and/or call default
//int width = (int)ceil(point.x/(16+1));
//int height = (int)ceil((point.y-m_BarHeight)/(16+1));
int width = point.x/(16+1);
int height = (point.y-m_BarHeight)/(16+1);
if(m_OpenState[height*m_WideNum+width] == OPENED)
{
if((m_SetState[height*m_WideNum+width] != MINE)
&(m_SetState[height*m_WideNum+width] != EMPTY))
{
int count = 0;
BOOL error = FALSE;
for(int row=height-1; row<=height+1; row++)
{
for(int col=width-1; col<=width+1; col++)
{
if((row>=0)&(row<m_HighNum)&(col>=0)&(col<m_WideNum))
{
if(m_OpenState[row*m_WideNum+col] == FLAG)
{
count++; //周围红旗数
if(m_SetState[row*m_WideNum+col] != MINE)
error = TRUE; //不是MINE而又标示为FLAG,出错
}
}
}
}
if(error)
{
m_MainButton->LoadBitmaps(IDB_DEAD,IDB_DOWN);//两个Bitmap分别是up与down的状态
m_MainButton->Invalidate();
for (int i=0; i<m_HighNum; i++)// i for row
{
for(int j=0; j<m_WideNum; j++)// j for column
{
m_OpenState[i*m_WideNum+j] = WRONG; //表示出错
}
}
return;
}
else if(m_SetState[height*m_WideNum+width] == count)//初设置数与周围雷数相等
{
for(int i=height-1; i<=height+1; i++)
for(int j=width-1; j<=width+1; j++)
{
if((i>=0)&(i<m_HighNum)&(j>=0)&(j<m_WideNum)&
(m_OpenState[i*m_WideNum+j] == UNOPENED))
{
m_OpenState[i*m_WideNum+j] = OPENED;
if(m_SetState[i*m_WideNum+j] == EMPTY)
ChainReaction(i,j);//双击中揭示空格则要继续揭示
}
}
}
}
}
PaintClient();
PaintControlBar();
CDialog::OnLButtonDblClk(nFlags, point);
return;
}
BOOL CMineDlg::AutoFinish()
{
int counter =0;
for(int i=0;i<m_HighNum;i++)
{
for(int j=0;j<m_WideNum;j++)
{
if(m_OpenState[i*m_WideNum+j] != UNOPENED)
counter++;
}
}
if(counter == m_HighNum*m_WideNum)
return TRUE;
else
return FALSE;
}
void CMineDlg::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
if(IsGameFinished)
KillTimer(1001); //删除时钟
else if((!IsGameFinished) & m_FirstBlick) //要在第一次点击之后才开始计时
{
m_Timer->SetNumber(m_Timer->GetNumber()+1);
PaintControlBar();
}
CDialog::OnTimer(nIDEvent);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -