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

📄 minedlg.cpp

📁 自己编写的一个简单的扫雷程序,主框架是基于对话框的
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	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 + -