📄 bwchessdlg.cpp
字号:
}//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 + -