您好,欢迎访问三七文档
当前位置:首页 > IT计算机/网络 > C/C++资料 > 五子棋MFC源码及注释
五子棋五子棋是一种很受人们喜爱的游戏,它的规则简单,但玩法变化多端,富有趣味性,适合人们消遣。这里我们就来设计一个五子棋游戏。(一)(一)人对人游戏1.1.游戏实现人对人游戏,其实只是对游戏规则的实现,我们只是利用五子棋游戏的规则来编程,至于真正的游戏实现——计算机的“智能”算法,我们将在后面讲述。五子棋的规则很简单:1,判断是否能放下棋子(是否已经有了棋子);2,判断是哪种颜色下棋;3,判断是否已经结束(是谁赢?)。这些规则,我们将用相应的函数来实现。其它,我们还将介绍其它一些功能的实现。如鼠标的更换,工具栏和状态栏的编辑,类与类之间的相互调用。新建工程3_1,选择单文档,在Step4of6中先中WindowsSockets复选框。如下图:图3-1-12.2.资源编辑由于我们这个程序出现的关于资源编辑的内容太多,我们具体介绍如下:见下图3-1-2,我们需要添加的有:图3-1-2黑白位图Bitmap以表示棋盘上面的棋子:IDB_BLACKIDB_WHITE黑白鼠标Cursor以替换当前鼠标:IDC_CURSOR1黑棋子IDC_CURSOR2白棋子说明:由于下棋时我们必须把鼠标热点设置在中间,点击下图(图3-1-3)最右边按扭,然后把鼠标移动到图像中你想设置为热点的地方,按下鼠标左键。图3-1-3黑白图标Icon以显示在状态栏供以提示:IDI_BLACKIDI_WHITE说明:由于我们的图标支持256色,按下下图(图3-1-4)最右边按扭,选择Device里面显示的选项。图3-1-4菜单以供操作:开始:ID_START保存:ID_SAVE打开:ID_OPEN工具栏:如上图所示。说明:工具栏一般都是根据菜单选项而产生的,它的ID一般都能从菜单的ID中找到。3.3.变量函数首先,为了实现状态栏的应用,我们必须更改它的变量:在MainFrm.h文件里面,把CStatusBarm_wndStatusBar为public接着是在3_1View.h文件里面添加变量函数://两个鼠标HCURSORhcursorwhite;HCURSORhcursorblack;//棋盘数组intwzq[19][19];//colorwhiteTRUE时白棋下,否则黑棋下boolcolorwhite;//棋子位图CBitmapm_bmblack;CBitmapm_bmwhite;//保存文件voidSave();//检查是否结束voidover(CPointpoint);//鼠标操作afx_msgvoidOnLButtonUp(UINTnFlags,CPointpoint);//鼠标图形更换afx_msgBOOLOnSetCursor(CWnd*pWnd,UINTnHitTest,UINTmessage);//菜单的开始afx_msgvoidOnStart();//菜单的保存afx_msgvoidOnSave();//菜单的打开afx_msgvoidOnOpen();4.4.具体实现棋盘大小设置:由于我们的游戏的棋盘大小是一定的,不能改变大小的,是应该符合要求的。在如下函数添加设置窗口大小的语句:BOOLCMainFrame::PreCreateWindow(CREATESTRUCT&cs){if(!CFrameWnd::PreCreateWindow(cs))returnFALSE;//TODO:ModifytheWindowclassorstylesherebymodifying//theCREATESTRUCTcscs.dwExStyle=cs.dwExStyle|WS_EX_TOPMOST;//cs.style=WS_SYSMENU|WS_OVERLAPPED|WS_MINIMIZEBOX;//;//设置窗口大小:400*340cs.cx=450;cs.cy=500;returnTRUE;}初始化变量:在构造函数里添加初始代码:CMy3_1View::CMy3_1View(){//TODO:addconstructioncodehere//Load鼠标图像和棋子位图hcursorblack=AfxGetApp()-LoadCursor(IDC_CURSOR1);hcursorwhite=AfxGetApp()-LoadCursor(IDC_CURSOR2);m_bmwhite.LoadBitmap(IDB_WHITE);m_bmblack.LoadBitmap(IDB_BLACK);//清理棋盘//数组值为0表示没有棋子for(inti=0;i19;i++)for(intj=0;j19;j++)wzq[i][j]=0;//白棋先下colorwhite=true;}画棋盘:在OnDraw(CDC*pDC)函数中画棋盘,由于在游戏过程中有可能重画棋盘,而那时棋盘上面有棋子,所以,我们在这个函数里面必须有画棋子的语句。我们用数组的做为1表示白棋,-1表示黑棋。voidCMy3_1View::OnDraw(CDC*pDC){CMy3_1Doc*pDoc=GetDocument();ASSERT_VALID(pDoc);//TODO:adddrawcodefornativedatahere//画背景CBrushmybrush1;mybrush1.CreateSolidBrush(RGB(192,192,192));CRectmyrect1(0,0,1200,800);pDC-FillRect(myrect1,&mybrush1);//画棋盘框线CPenmypen;CPen*myoldPen;mypen.CreatePen(PS_SOLID,1,RGB(0,0,0));myoldPen=pDC-SelectObject(&mypen);for(inti=0;i19;i++){pDC-MoveTo(40,40+i*20);pDC-LineTo(400,40+i*20);pDC-MoveTo(40+i*20,40);pDC-LineTo(40+i*20,400);}//重画时显示存在的棋子CDCDc;if(Dc.CreateCompatibleDC(pDC)==FALSE)AfxMessageBox(Can'tcreateDC);for(intn=0;n19;n++)for(intm=0;m19;m++)if(wzq[n][m]==1){//显示白棋Dc.SelectObject(m_bmwhite);pDC-BitBlt(n*20+32,m*20+32,160,160,&Dc,0,0,SRCCOPY);}elseif(wzq[n][m]==-1){//显示黑棋Dc.SelectObject(m_bmblack);pDC-BitBlt(n*20+32,m*20+32,160,160,&Dc,0,0,SRCCOPY);}}设置鼠标:棋盘画好了,接下来就是下棋了。但鼠标并没有像我们上面说的那样变成白棋,加函数如下:BOOLCMy3_1View::OnSetCursor(CWnd*pWnd,UINTnHitTest,UINTmessage){//TODO:Addyourmessagehandlercodehereand/orcalldefaultif(nHitTest==HTCLIENT){//白棋下,显示白棋鼠标if(colorwhite){//调用主框架里面的状态栏CMainFrame*pFrm=(CMainFrame*)AfxGetApp()-m_pMainWnd;CStatusBar*pStatus=&pFrm-m_wndStatusBar;if(pStatus){pStatus-GetStatusBarCtrl().SetIcon(0,AfxGetApp()-LoadIcon(IDI_WHITE));pStatus-SetPaneText(0,白棋下);}SetCursor(hcursorwhite);}//显示黑棋鼠标else{SetCursor(hcursorblack);CMainFrame*pFrm=(CMainFrame*)AfxGetApp()-m_pMainWnd;CStatusBar*pStatus=&pFrm-m_wndStatusBar;if(pStatus){//显示图像pStatus-GetStatusBarCtrl().SetIcon(0,AfxGetApp()-LoadIcon(IDI_BLACK));//显示文字pStatus-SetPaneText(0,黑棋下);}}return1;}returnCView::OnSetCursor(pWnd,nHitTest,message);}现在运行程序,怎样,鼠标变成白棋了,而且下面的状态栏也能够显示鼠标状态了,真是一举两得。可是,又该怎样把棋子放在棋盘上呢?下棋操作:这就涉及到OnLButtonDown(UINTnFlags,CPointpoint)和OnLButtonUp(UINTnFlags,CPointpoint)两个函数了。要用哪一个或用两个?用Down函数时是在鼠标按下时放下棋子,可是,要是我们按下后意识到按错了怎么办;那就改用Up函数,表示当鼠标键松开时放下棋子。OK!添加函数如下:voidCMy3_1View::OnLButtonUp(UINTnFlags,CPointpoint){//TODO:Addyourmessagehandlercodehereand/orcalldefaultCDC*pDC=GetDC();CDCDc;if(Dc.CreateCompatibleDC(pDC)==FALSE)AfxMessageBox(Can'tcreateDC);//是否在棋盘内if(point.x30&&point.x410&&point.y30&&point.y410){intpx=(point.x-30)/20;intpy=(point.y-30)/20;//是否已经有棋子if(colorwhite&&wzq[px][py]==0){Dc.SelectObject(m_bmwhite);pDC-BitBlt(px*20+32,py*20+32,160,160,&Dc,0,0,SRCCOPY);//表示存在白棋wzq[px][py]=1;//检查是否结束over(point);//换黑棋下colorwhite=false;}elseif(wzq[px][py]==0){Dc.SelectObject(m_bmblack);pDC-BitBlt(px*20+32,py*20+32,160,160,&Dc,0,0,SRCCOPY);wzq[px][py]=-1;over(point);colorwhite=true;}}CView::OnLButtonUp(nFlags,point);}由上面可以看出,当鼠标键松开时判断,如果那个位置没有棋子,则放下,并把棋盘数组赋相应的值:1或-1。是否结束:接着是用一个over()函数判断是否结束,是则结束并重新开始;否则,接着把鼠标变成对方棋子,表示对方下棋。那over()函数又是怎样的呢?此函数是利用刚下棋的位置为中心,检查它各个方向上的连续五个棋子是否同色,是则结束并重新开始。然而,我们又是怎样判断一个方向上的五个棋子的同色的?这就涉及地为什么我要把五子棋数组赋值为1和-1的问题。因为这样有一个好处:利用连续五个棋子的值相加,如果它们的值的绝对值等于5,则说明是同色。当然,这只是这样赋值的一点作用,真正的作用将在后面介绍。添加如下:voidCMy3_1View::over(CPointpoint){//获取鼠标指向数组位置,即中心位置intx=(point.x-30)/20;inty=(point.y-30)/20;//计算开始判断的坐标xx,yyintxx,yy;if(x4)xx=0;elsexx=x-4;if(y4)yy=0;elseyy=y-4;i
本文标题:五子棋MFC源码及注释
链接地址:https://www.777doc.com/doc-4924349 .html