基于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
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiQ3chVEa0V3bT9CX5RXa2Fmcn9CXwczLcVmds92czlGZvwVP9EUTDZ0aRJkSwk0LcxGbpZ2LcBDM08CXlpXazRnbvZ2LcRlMMVDT2EWNvwFdu9mZvwFNrRlT3FFROVTT6hVdsdUZwZlMkZXUYpVd1kmYr50MZV3YyI2cKJDT29GRjBjUIF2LcRHelR3LcJzLctmch1mclRXY39DM3IzMwMDN0EzMykDM3EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
具体表现为下图:
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窗口及视图资源的绘制。
下一篇,将带来落子及五子棋规则的实现。