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

📄 bwchessdlg.cpp

📁 这是我用vc编写的一个黑白棋网络游戏的使用程序
💻 CPP
📖 第 1 页 / 共 5 页
字号:

		}//end 此处无子	   
		
		else//有子
		PlaySounds(IDSOUND_ERROR);

	}//end “if (PointToStonePos(point, pt))”
	else  if (!PointToStonePos(point, pt))//无子
		PlaySounds(IDSOUND_ERROR);
	//此处为非网络模式
	
	
	////模式是网络模式
	if(Sever==0||Sever==1)//已连网
	if (g_nRunMode == MODE_NETWORK&&PointToStonePos(point, pt))
	{
		int nX = pt.x;
		int nY = pt.y;
		if (kernel[nY][nX]==0) //此处无子     
		{			
				if ((g_bUserBlack && !m_byColor) || (!g_bUserBlack && m_byColor)) //数据正确
				{                                    
					m_byColor = !m_byColor;	// 0-Black  1-White//设置当前棋手的颜色,因为初值为黑色棋手,
					                                  //但是m_byColor==0,代表白色,所以要先设成黑色
					duplicate();//保存副本			
					if(BtoW(nY,nX,m_byColor+1))//将棋盘上被夹住的子变色
					{
						m_Mutex.Lock();
						m_HintOnce=0;
						m_PeekOnce=0;
						m_CurPt=pt;
						AddStringToList(nY,nX,m_byColor);//将信息加入列表框
						InvalidateRect(m_Client, FALSE);//刷新窗口
						UpdateWindow();//显示窗口
						PlaySounds(IDSOUND_PUTSTONE);   
						Ring(IsEnd(!m_byColor+1));//根据棋盘的状态处理善后工作
						//正确调用
						if(!m_bGameOver && g_bPeepOften)//m_Skip为1,显示自己的位置,否则显示对方的位置
						OnCanplace();
					     if(m_Skip==1)
						 ready=true;
				        else 
						 ready=false;
						if(m_bGameOver)
						ready=false;
                        if(m_bGameOver)
                        Senddata(nX,nY,CMD_OVER);//发数据给对方, V 操作!!!!!
						if(m_Skip==1)
                        Senddata(nX,nY,CMD_SKIP);//发数据给对方, V 操作!!!!!

                        Senddata(nX,nY,CMD_CLICK);//发数据给对方, V 操作!!!!!
						m_Mutex.Unlock();
                        
					}//end if(BtoW(nY,nX,m_byColor+1))
					else//没有夹住任何棋子,撤消已有的操作
					{
						int temp[NUM*NUM];
						m_UndoPoint.pop(temp);
						m_byColor=!m_byColor;
						PlaySounds(IDSOUND_ERROR);
					}	
				}    //  end if ((g_bUserBlack && !m_byColor) ||(!g_bUserBlack && m_byColor)) 
		}	   		
		
	}//此处为网络模式
    else if (!PointToStonePos(point, pt))//无子
		PlaySounds(IDSOUND_ERROR);//发出错误声音
	//以上为网络模式



	//将其它工作传给基类处理
	CDialog::OnLButtonDown(nFlag, point);
}    //end  OnLButtonDown        
          
int CBWChessDlg::Distance(const CPoint &pt1, const CPoint &pt2)//计算两点间的距离
{
	return (int)sqrt((double)(pt1.x-pt2.x)*(pt1.x-pt2.x) + (double)(pt1.y-pt2.y)*(pt1.y-pt2.y));
}

BOOL CBWChessDlg::IsStonePoint(CPoint& ptStone)//检查是否在棋格内
{
	if (ptStone.x<0 || ptStone.x>=NUM || ptStone.y<0 || ptStone.y>=NUM)
	{//不合法,矫正到最边缘
		if (ptStone.x<0)
			ptStone.x = 0;
		else if (ptStone.x>=NUM)
			ptStone.x = NUM-1;
		if (ptStone.y<0)
			ptStone.y = 0;
		else if (ptStone.y>=NUM)
			ptStone.y = NUM-1;
		return FALSE;
	}
	return TRUE;
}

BOOL CBWChessDlg::PointToStonePos(const CPoint &pt, CPoint& ptStone)//将客户区坐标转化为棋盘坐标
{
	int nPosX = (pt.x - m_wXNull-m_wStoneWidth/2)/m_wStoneWidth;//粗略计算棋盘坐标,有误差
	int nPosY = (pt.y - m_wYNull-m_wStoneWidth/2)/m_wStoneHeight;
	CPoint pt0(nPosX * m_wStoneWidth + m_wXNull+m_wStoneWidth/2, nPosY*m_wStoneHeight+m_wYNull+m_wStoneWidth/2);
	CPoint pt1((nPosX+1)*m_wStoneWidth+m_wXNull+m_wStoneWidth/2, nPosY*m_wStoneHeight+m_wYNull+m_wStoneWidth/2);
	CPoint pt2((nPosX+1)*m_wStoneWidth+m_wXNull+m_wStoneWidth/2, (nPosY+1)*m_wStoneHeight+m_wYNull+m_wStoneWidth/2);
	CPoint pt3(nPosX*m_wStoneWidth+m_wXNull+m_wStoneWidth/2, (nPosY+1)*m_wStoneHeight+m_wYNull+m_wStoneWidth/2);
	//四个参照点,选择误差最小的一点
	int nDis0 = Distance(pt, pt0);
	int nDis1 = Distance(pt, pt1);
	int nDis2 = Distance(pt, pt2);
	int nDis3 = Distance(pt, pt3);
	int nLimit = m_wStoneWidth/2-4;
	if (nDis0 <= nLimit)
		ptStone = CPoint(nPosX, nPosY);
	else if (nDis1 <= nLimit)
		ptStone = CPoint(nPosX+1, nPosY);
	else if (nDis2 <= nLimit)
		ptStone = CPoint(nPosX+1, nPosY+1);
	else if (nDis3 <= nLimit)
		ptStone = CPoint(nPosX, nPosY+1);
	else//不在棋盘内
	{
		int nMin1 = min(nDis0, nDis1);
		int nMin2 = min(nDis2, nDis3);
		int nMin = min(nMin1, nMin2);

		if (nMin == nDis0)
			ptStone = CPoint(nPosX, nPosY);
		else if (nMin == nDis1)
			ptStone = CPoint(nPosX+1, nPosY);
		else if (nMin == nDis2)
			ptStone = CPoint(nPosX+1, nPosY+1);
		else if (nMin == nDis3)
			ptStone = CPoint(nPosX, nPosY+1);

		IsStonePoint(ptStone);//矫正到棋盘上
		return FALSE;
	}
	return IsStonePoint(ptStone);
}

void CBWChessDlg::Ring(int m_nType)//处理走完一步棋之后的善后处理
{
	Calcu_BW();
	ShowNumber();
	m_Skip=0;//only when m_nType==0,then m_Skip==1;
				//other m_Skip==0;
	switch(m_nType)
	{
	case -1://游戏结束
		{
			int win=0;
			int addp=0;
			m_bGameOver = TRUE;
			if(m_TimerOn)
			{
				KillTimer(PASSEDTIME);
				m_TimerOn=0;
			}
			m_pMenu->EnableMenuItem(IDM_HINT,MF_GRAYED);
			m_pMenu->EnableMenuItem(IDM_UNDO,MF_GRAYED);
			m_pMenu->EnableMenuItem(IDM_CANPLACE,MF_GRAYED);
			m_pMenu->EnableMenuItem(IDM_SAVEINFO,MF_ENABLED);
			m_pMenu->EnableMenuItem(IDM_REPLAY,MF_ENABLED);
			CString str1,str2, str3,strPrompt;
			TCHAR str[64];

			str2.LoadString(IDS_TITLE_CHINESE);//“黑白棋”

			if(g_nRunMode == MODE_2PLAYER)//两人对战
			{
				if(num_white<num_black)
				{
					addp=2;
					str1.LoadString(IDS_BLACKWIN_CHINESE);//“本局黑棋胜。”
				}
				else if(num_white>num_black)
				{
					addp=1;
					str1.LoadString(IDS_WHITEWIN_CHINESE);//“本局白棋胜。”
				}
				else
				{
					addp=3;
					str1.LoadString(IDS_TIE_CHINESE);//“本局平手。\n我们的水平不分上下!”
				}
				str3.LoadString(IDS_END_CHINESE);//“黑棋%d子,白棋%d子。\n”
				
				wsprintf(str, str3.GetBuffer(256), num_black,num_white);
				strPrompt = str;
				strPrompt += str1; 
			}
			else//人机对战
			{
				g_nStoneNum=abs(num_black-num_white);
				g_nBestMark=abs((num_white+num_black)*(num_white-num_black));//计算得分,公式是|A*A-B*B|
				if(!(num_black && num_white))//吃光了,再加800
					g_nBestMark+=800;
				if(num_white>num_black)//白 胜
					addp=1;
				if(num_white<num_black)//黑 胜
					addp=2;
				if(num_white==num_black)//平局
				{
					str1.LoadString(IDS_TIE_CHINESE);//“本局平手。\n我们的水平不分上下!”
					win=1;
					addp=3;
				}
				else if((g_bUserBlack && (num_white>num_black)) || ((!g_bUserBlack) && (num_white<num_black)))
				{//人是输家
					if(!num_white || !num_black)
						str1.LoadString(IDS_COMPUTERWIN0_CHINESE);//“你的棋子被我全吃掉了!\n再去研究一下规则吧!”
					else if(g_nStoneNum>=40)//“你真是太差了,我胜了%d你手。\n回去多练几年吧!”
						str1.LoadString(IDS_COMPUTERWIN1_CHINESE);
					else//“我赢了。胜你%d手。\n你还不行,好好锻炼一下吧!”
						str1.LoadString(IDS_COMPUTERWIN2_CHINESE);
				}
				else if((g_bUserBlack && (num_white<num_black)) || ((!g_bUserBlack) && (num_white>num_black)))
				{//人是赢家
					win=1;
					if(!num_white || !num_black)//“你好厉害,居然把我的棋全吃掉了!\n佩服佩服!”
						str1.LoadString(IDS_USERWIN0_CHINESE);
					else if(g_nStoneNum<=6)//“恭喜,你获胜了。胜了我%d手。\n愿意再较量一盘吗?”
						str1.LoadString(IDS_USERWIN2_CHINESE);
					else//“你才胜了我%d手,我不服!\n有种再下一盘!”
						str1.LoadString(IDS_USERWIN1_CHINESE);
				}

				if(num_white!=num_black)
				{
					if(num_white && num_black)
					{
						wsprintf(str, str1.GetBuffer(256), g_nStoneNum);
						strPrompt=str;
					}
					else
						strPrompt=str1;
				}
				else
					strPrompt=str1;//载入胜负信息
			}// end人机对战

			AddStringToList(0,0,0,addp);//载入胜负信息与列表

			if(g_nRunMode == MODE_2PLAYER)//人人对战
				PlaySounds(IDSOUND_USERWIN);
			else//人机对战
				PlaySounds((win==0) ? IDSOUND_COMPUTERWIN : IDSOUND_USERWIN );

			MsgBox(strPrompt,str2);//弹出胜负的对话框

			BOOL bWinner = FALSE;
			if (g_nBestMark>g_nMark1)	    		
	    		bWinner = TRUE;//打破了记录
			
			if (g_nRunMode == MODE_WITH_COMPUTER && bWinner &&
	    		(win==1))//存储记录
			{
	    		CRecordDlg recordDlg;
//    			int result=
				recordDlg.DoModal();
//				if(result==IDOK)
//					OnBest();
			}
		}
		break;


	case 0://表示某一方不能下,m_Skip==1;由另外一方(m_byColor方:1黑,0白)继续下
		{
			CString str3,str2;
			if(g_nRunMode == MODE_WITH_COMPUTER)//人机对战
			{
				if((g_bUserBlack && !m_byColor) || (!g_bUserBlack && m_byColor))
				//m_byColor代表应下棋的颜色,当棋手的颜色与m_byColor不匹配时表示当前棋手不能下
					str3.LoadString(IDS_USER_NOPLACE_CHINESE);//“你无处可走,只能让我走.”
				else if((g_bUserBlack && m_byColor) || (!g_bUserBlack && !m_byColor))
					str3.LoadString(IDS_COMPUTER_NOPLACE_CHINESE);//“我没法走了,只能让你走了.”
			}
			if(g_nRunMode == MODE_2PLAYER)//人人
			{
				if(!m_byColor)//该白色下,则黑色不能下
					str3.LoadString(IDS_BLACK_NOPLACE_CHINESE);//“黑棋无处可走。”
				else//该黑色色下
					str3.LoadString(IDS_WHITE_NOPLACE_CHINESE);//“白棋无处可走”
			}
			str2.LoadString(IDS_TITLE_CHINESE);
			MsgBox(str3,str2);
			//important type
			m_Skip=1;
			//
			m_byColor=!m_byColor;//由于:OnLButtonDown(UINT nFlag, CPoint point)每次在走棋之前,都会反色,
			//因此在此处先反色,确保走棋的正确
		}
		break;
	}
}

void CBWChessDlg::OnNew()//响应 “新棋盘” 菜单命令
{	
	int HaveKilled=0;
	if(m_TimerOn)//停止计时
	{
		HaveKilled=1;
		KillTimer(PASSEDTIME);
		m_TimerOn=0;
	}
    
	//备份数据
	int a=m_bGameOver;
	int b=g_nRunMode;

	CSetupDlg setupDlg;//创建设置对话框
	if (setupDlg.DoModal()==IDCANCEL)//取消了
	{
		if(HaveKilled)//恢复计时
		{			
			SetTimer(PASSEDTIME,1000,NULL);
			m_TimerOn=1;
		}
		return;
	}

     if(!a&&b==MODE_NETWORK)//当前游戏没有结束
	{
        Senddata(0,0,CMD_RESIGN);
        m_bGameOver=TRUE;
	}


       CString str;
	//对相关参数进行初始化
	if(g_nRunMode==MODE_WITH_COMPUTER)//人机0
	{
	     if (g_nRunMode==MODE_WITH_COMPUTER && !g_bUserBlack)
		 {	
	      str.LoadString(IDS_SINGLE_COMPUTER_CHINESE);//IDS_TITLE_CHINESE:“黑白棋”
	       SetWindowText(str);//设置标题
		 }
	    else
		{

	    str.LoadString(IDS_SINGLE_USER_CHINESE);//IDS_TITLE_CHINESE:“黑白棋”
	    SetWindowText(str);//设置标题
		}
		ready=1;
	}

  if(g_nRunMode==MODE_2PLAYER)//人人1
	{
		if(g_nIsNoTimeLimit)
		{
	        str.LoadString(IDS_DOUBLE_NOLIMIT_CHINESE);//IDS_TITLE_CHINESE:“黑白棋”
	        SetWindowText(str);//设置标题
		}
		else
		{
	        str.LoadString(IDS_DOUBLE_LIMIT_CHINESE);//IDS_TITLE_CHINESE:“黑白棋”
	        SetWindowText(str);//设置标题
		}
	    ready=1;
	}
  if(g_nRunMode==MODE_NETWORK)//网络2
	{
		
	  if(Sever==2)//非网络模式
		{
	        str.LoadString(IDS_NONETWORK);//IDS_TITLE_CHINESE:“黑白棋”
	        SetWindowText(str);//设置标题
		    AfxMessageBox("请先连上网络");
			return;
		}
		else if(Sever==1)
		{
	        str.LoadString(IDS_SERVER);//IDS_TITLE_CHINESE:“黑白棋”
	        SetWindowText(str);//设置标题
			g_bUserBlack = TRUE;//先手
			g_nSkill = 1;//棋力
			g_nTimeLimit=60;//允许等待的最大时间 from 60 to 9000,单位秒
            g_nIsNoTimeLimit=1;//限时
		    ready=1;
		}
        else if(Sever==0)
		 {
	        str.LoadString(IDS_CLIENT);//IDS_TITLE_CHINESE:“黑白棋”
	        SetWindowText(str);//设置标题
			g_bUserBlack = FALSE;//先手
			g_nSkill = 1;//棋力
			g_nTimeLimit=60;//允许等待的最大时间 from 60 to 9000,单位秒
            g_nIsNoTimeLimit=0;//限时
			ready=0;
		 }
	     else
		 {
			 AfxMessageBox("未知错误!");
		     return;
		 }
	}
  //以下部分是重新初始化
	InitParams();
	Invalidate();   
	UpdateWindow();   
	ShowNumber(1);
	SetChessTitle();
  //设置菜单
	m_pMenu->EnableMenuItem(IDM_HINT,MF_ENABLED);
	m_pMenu->EnableMenuItem(IDM_UNDO,MF_ENABLED);
	m_pMenu->EnableMenuItem(IDM_CANPLACE,MF_ENABLED);
	m_pMenu->EnableMenuItem(IDM_SAVE,MF_ENABLED);
	m_pMenu->EnableMenuItem(IDM_SAVEINFO,MF_GRAYED);
	m_pMenu->EnableMenuItem(IDM_REPLAY,MF_GRAYED);
	PlaySounds(IDSOUND_NEWGAME);
	UpdateWindow();
	SetWindowText(str);
    if (g_nRunMode==MODE_WITH_COMPUTER && !g_bUserBlack)//人机对站,机先走
	{// Computer first,SO Computer is black!!
		CPoint pt;            			
		m_byColor = !m_byColor;			// 1-Black  0-White,将前一对手的颜色变成当前对手的颜色
		int ptBest_x,ptBest_y;
		IsEnd(m_byColor+1);//是否结束
		Place(&ptBest_x,&ptBest_y,m_byColor+1);
		BtoW(ptBest_x,ptBest_y,m_byColor+1);
		AddStringToList(ptBest_x,ptBest_y,m_byColor);
		pt.x = ptBest_y*m_wStoneWidth + m_wXNull+m_wStoneWidth/2;
		pt.y = ptBest_x*m_wStoneHeight + m_wYNull+m_wStoneWidth/2;
		m_CurPt.x=ptBest_y;
		m_CurPt.y=ptBest_x;
		ClientToScreen(&pt);
		SetCursorPos(pt.x, pt.y);
		InvalidateRect(m_Client, FALSE);
		UpdateWindow();
		PlaySounds(IDSOUND_PUTSTONE);
	}  

	Ring(IsEnd(!m_byColor+1));
	if(!m_bGameOver && g_bPeepOften)
		OnCanplace();//显示位置

	SetTimer(PASSEDTIME,1000,NULL);
	m_TimerOn=1;
	m_nIsContinueReplay=1;
}

void CBWChessDlg::OnAbout()
{
    CAboutDlg aboutDlg(this);
    aboutDlg.DoModal();//响应“关于黑白棋”菜单
}

void CBWChessDlg::OnExit()//关闭程序
{
	if(m_TimerOn)
		KillTimer(PASSEDTIME);
	if(g_nIsDemo)
		::TerminateThread(m_CcThread->m_hThread,0);

	CDialog::EndDialog(0);
}

void CBWChessDlg::PutStone(BYTE byColor, const CPoint &point, CDC *pDC)//填充棋格
{                                      
	int nX = point.x*m_wStoneWidth + m_wXNull;                             
	int nY = point.y*m_wStoneHeight + m_wYNull;
	if (byColor == 0)//  0:  WHITE  1  :BLACK
		DrawBitmap(pDC,nX,nY,IDB_WHITE, SRCCOPY);
	else if (byColor == 1)
		DrawBitmap(pDC,nX,nY,IDB_BLACK, SRCCOPY);
}

BOOL CBWChessDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{//响应光标事件
	CPoint point, pt;
	::GetCursorPos(&point);
   	ScreenToClient(&point);
	if (PointToStonePos(point, pt) && !m_bGameOver && !g_nIsDemo)

⌨️ 快捷键说明

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