天天看点

基于MFC的五子棋应用(一)

基于MFC的五子棋应用(一)

前些日子,参加了学校里一个实验室的面试,面试过程实在糟心,老师提出现场写一个五子棋的算法,然而过于紧张,伪代码都写得并不顺利。
 总而言之,言而总之,面试结果虽然不尽如人意,但最后布置了一道基于MFC的五子棋实现,终是能一展拳脚。
 故以编程日记,记之。
           

1.分析

首先是对整个程序的分析:五子棋,作为最基础的交互型游戏规则简单,游戏的主体主要分为三个部分:1.视图资源 2.规则 3.交互
           

1.1 视图

五子棋的规则很简单:判断当前位置能否落子
                判断当前执子颜色
                判断是否五子连珠
           

1.2 环境

本例采用VC++6.0实现
建立文件 MFC AppWizard[exe]  单文档
           

1.3 资源编辑

黑白位图Bitmap以表示棋盘上面的棋子:
        IDB_BLACK  
        IDB_WHITE
黑白鼠标Cursor以替换当前鼠标:
        IDC_CURSOR1     黑棋子
        IDC_CURSOR2     白棋子

黑白图标Icon以显示在状态栏供以提示:
        IDI_BLACK
        IDI_WHITE

菜单以供操作:
        VS 人:ID_PLAYER
        VS AI:ID_COMPUTER
        保存:ID_SAVE
        载入:ID_OPEN
        退出:ID_APP_EXIT
           
基于MFC的五子棋应用(一)

具体表现为下图:

基于MFC的五子棋应用(一)

1.4 变量函数定义

为了实现状态栏的显示,修改MainFrm.h中 
CStatusBar  m_wndStatusBar 为public访问
在***View.h中添加变量
           
//保存棋谱
    void OnSave();
    //载入棋谱
    void OnOpen();

    //悔棋坐标
    int bprex,bprey;
    int wprex,wprey;
    int Regretpoint;

     //检查是否结束
    void over(CPoint point);

     //两个鼠标
    HCURSOR hcursorwhite;
    HCURSOR hcursorblack;

    //棋盘数组
    int wzq[][];

    // colorwhite TRUE时白棋下,否则黑棋下
    bool colorwhite;

    //棋子位图
    CBitmap m_bmblack;
    //AI
    //保存计算机落子时白棋位置
    CPoint vspoint;
    int vscomputer;     //vscomputer=1 为人机对战  2为人人
           

(AI部分 之后的文章进行介绍 先针对人人对战惊醒解释这一方面比较简单)

protected:
    //{{AFX_MSG(CWuZiQiView)
        // NOTE - the ClassWizard will add and remove member functions here.
        //    DO NOT EDIT what you see in these blocks of generated code !
    afx_msg void OnLButtonUp(UINT nFlags, CPoint point);  //鼠标操作
    afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);  //鼠标图形更换
    afx_msg void OnStart(); //菜单的开始
    afx_msg void OnSave();  //菜单的保存
    afx_msg void OnOpen();  //菜单的打开
    afx_msg void OnPlayer();  //对人
    afx_msg void OnComputer(); //对机器
    afx_msg void Regret();    //悔棋
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
           

1.5 函数实现

**设置棋盘大小:确定棋盘的大小且不能改变,在MainFrm.cpp的CMainFrame::PreCreateWindow 中添加如下语句**:
           
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
    if( !CFrameWnd::PreCreateWindow(cs) )
        return FALSE;
    // TODO: Modify the Window class or styles here by modifying
    //  the CREATESTRUCT cs
    cs.dwExStyle=cs.dwExStyle|WS_EX_TOPMOST;    
    cs.style=WS_SYSMENU|WS_OVERLAPPED|WS_MINIMIZEBOX;

    //设置窗口大小:450*550 
    cs.cx=;
    cs.cy=;   
    return TRUE;
}
           
**在构造函数中载入鼠标的图像和棋子的位图**:
           
CWuZiQiView::CWuZiQiView()
{
    // TODO: add construction code here

    //载入鼠标图像
    hcursorblack=AfxGetApp()->LoadCursor(IDC_CURSOR1);  
    hcursorwhite=AfxGetApp()->LoadCursor(IDC_CURSOR2);

    //载入棋子图像
    m_bmwhite.LoadBitmap(IDB_WHITE);
    m_bmblack.LoadBitmap(IDB_BLACK);
    //重置当前棋盘
    for(int i=;i<;i++)
        for(int j=;j<;j++)
            wzq[i][j]=;
    //约定:白棋先下
    colorwhite=true;

    //默认为人人对战
    vscomputer=;

}
           
**绘制棋谱,本例为绘制19X19的常规棋谱(可以进行修改),在OnDraw(CDC* pDC)函数中画棋盘,由于在游戏过程中可能会重新绘制载入棋盘,此时棋盘上可能会有棋子,所以在OnDraw(CDC* pDC)函数中同时加入绘制棋子的内容.**
           
void CWuZiQiView::OnDraw(CDC* pDC)
{
    CWuZiQiDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    // TODO: add draw code for native data here

    //画背景
    CBrush mybrush1;
    mybrush1.CreateSolidBrush(RGB(,,));    
    CRect myrect1(,,,);
    pDC->FillRect(myrect1,&mybrush1);

    //画格子
    CPen mypen;
    CPen*myoldPen;
    mypen.CreatePen(PS_SOLID,,RGB(,,));
    myoldPen=pDC->SelectObject(&mypen);
    for(int i=;i<;i++)
    {       
        pDC->MoveTo(,+i*20);
        pDC->LineTo(,+i*20);
        pDC->MoveTo(+i*20,);
        pDC->LineTo(+i*20,);
    }
    CDC Dc;
    if(Dc.CreateCompatibleDC(pDC)==FALSE)
        AfxMessageBox("Can't create DC");
    for(int n=;n<;n++)
        for(int m=;m<;m++)
            if(wzq[n][m]==)
            {
                //显示白棋
                Dc.SelectObject(m_bmwhite);
                pDC->BitBlt(n*20+,m*20+,,,&Dc,,,SRCCOPY);   
            }
            else if(wzq[n][m]==-)
                {
                //显示黑棋
                    Dc.SelectObject(m_bmblack);
                    pDC->BitBlt(n*20+,m*20+,,,&Dc,,,SRCCOPY);   
                }
}
           
**设置光标试图资源**
若当前执白子则光标显示为白子,否则光标显示为黑子。具体实现如下:
           
//设置光标
BOOL CWuZiQiView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
{
    if(nHitTest==HTCLIENT)
    {
        //白棋下,显示白棋鼠标
        if(colorwhite)
        {
            CMainFrame*pFrm=(CMainFrame*)AfxGetApp()->m_pMainWnd;
            CStatusBar*pStatus=&pFrm->m_wndStatusBar;       
            if(pStatus)
            {
                pStatus->GetStatusBarCtrl().SetIcon(,AfxGetApp()->LoadIcon(IDI_WHITE));
                pStatus->SetPaneText(,"白棋下");
            }
            SetCursor(hcursorwhite);
        }
        //显示黑棋鼠标
        else
        {
            SetCursor(hcursorblack);
            CMainFrame*pFrm=(CMainFrame*)AfxGetApp()->m_pMainWnd;
            CStatusBar*pStatus=&pFrm->m_wndStatusBar;       
            if(pStatus)
            {
                //显示图像
                pStatus->GetStatusBarCtrl().SetIcon(,AfxGetApp()->LoadIcon(IDI_BLACK));
                //显示文字
                pStatus->SetPaneText(,"黑棋下");
            }
        }
        return ;
    }
    return CView::OnSetCursor(pWnd, nHitTest, message);
}
           

以上即为五子棋MFC窗口及视图资源的绘制。

下一篇,将带来落子及五子棋规则的实现。