使用C++ MFC编写一个简单的五子棋游戏程序

 更新时间:2020年02月20日 15:08:35   作者:Vac__001  
这篇文章主要介绍了使用C++ MFC编写一个简单的五子棋游戏程序,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下

MFC简介:

  MFC(MicrosoftFoundationClasses)是微软基础类库的简称,是微软公司实现的一个c++类库,主要封装了大部分的windows API函数。 MFC除了是一个类库以外,还是一个框架,在vc++里新建一个MFC的工程,开发环境会自动帮你产生许多文件,同时它使用了mfcxx.dll。xx是版本,它封装了mfc内核,所以你在你的代码看不到原本的SDK编程中的消息循环等等东西,因为MFC框架帮你封装好了,这样你就可以专心的考虑你程序的逻辑,而不是这些每次编程都要重复的东西,但是由于是通用框架,没有最好的针对性,当然也就丧失了一些灵活性和效率。但是MFC的封装很浅,所以效率上损失不大。

开始正文

简述

在学习了C++ MFC编程后,就萌生了编写一个五子棋程序的想法。诚然,用C#来编写的话可能界面会好很多,但是我的主要目标不在界面而是算法,所以利用了VS的MFC来编写程序。

程序特点

  • 鼠标移动过程中有选中框跟随,下棋位置实时自动反馈
  • 选中框位置只会在合法的下棋位置出现(即棋线的交叉处并且没有下过的位子),所以即使你的鼠标不在棋线交叉处,程序也会实时自动反馈鼠标在当前位置将要下棋的位置,这避免了下棋过程中的错下。
  • 提供悔棋功能
  • 为了进一步避免错下,提高程序的可用性,本程序还设计了一个悔棋按钮(程序设置最大悔棋次数为1次)
  • 提供多种棋盘大小
  • 标准的五子棋棋盘为15x15,为了提供更多样的棋盘大小,本程序还设有17x17和19x19两种非常规棋盘。
  • 提供复盘功能
  • 在棋局结束后,程序会给出棋局的复盘结果,可以从中分析出棋局胜败的原因。
  • 解决了MFC绘图窗口移出屏幕图像消失的问题
  • 你可以在完整代码中看到解决刷新问题的解决方案
  • 代码较为基础,只需要掌握基础的MFC编程知识就可以自己实现
  • 因为本人也是编程小白,算法设计比较基础和简单,只掌握基础的C++编程知识就可以看懂代码

程序实现

完整代码可访问我的github: https://github.com/Vaczzy/SimpleGobang

step1:在VS中创建一个MFC对话框程序工程。

(创建好后可以直接将我提供的源码复制到工程中即可运行,如遇问题可以下方留言)

step2:新建一个名为CMainGobang的类,在类中编写主要代码

下面给出了MainGobang.h头文件中的全部代码:

struct Pieces//棋子判断单元
{
 bool bIsPieces;//是否已有棋
 bool bIsBlack;//黑棋或白棋
 int x,y;//棋子所在格
};

struct MyRectangle
{
 int x,y;//选中框核心坐标
};

public:
 CMainGobang(void);
 ~CMainGobang(void);
private:
 /////basic information
 int iSize;//棋盘大小参数
 int xmax,xmin,ymax,ymin;//棋盘大小参数
 int idx;//棋盘每小格长度
 /////pieces information
 int iPieces;//棋子计数//当前棋子计数为iPieces-1
 int iPiecesNum;//棋子总数
 Pieces *pPieces;//棋子
 /////rectangle information
 int iRectangleNum;//选中框个数
 MyRectangle *pmyRectangle;//选中框
 /////for draw rectangle&draw pieces
 bool NoRectangle(int x,int y);//判断该位置上是否有选中框
 bool NoPieces(int x,int y);//判断该位置上是否有棋子
 /////for judge win
 bool IsBlack(int x,int y);//判断该位置上棋子颜色
 bool IsConnect(int iDir,int x,int y);//查找相连的棋子
 int ConnectNum();//返回相连棋子个数
 /////for machine fight
 //void MaConnectNum(int iConnectNum,int iDir);//返回弱相连棋子个数/iDir方向参数
 int ConnectDir();//返回相连棋子方向
public:
 void DrawMainTable(CDC *pDC,CRect rect,int iTableSize);//绘制棋盘函数
 void SetPieces();//设参函数//将初始化代码与绘制棋盘代码分开
 void DrawRectangle(CDC *pDC,CPoint pt);//绘制选中框/返回是否绘制
 void DrawPieces(CDC *pDC,CRect rect,CPoint pt);//绘制棋子函数
 bool ClearPieces(CDC *pDC,bool &bBlack);//清除棋子函数/用于悔棋
 void KeepPieces(CDC *pDC,CRect rect,int iTableSize);//循环绘制棋子 //用以解决刷新问题
 void MachineDraw(CDC *pDC);//机器下棋函数

 bool Success();//判断胜利函数
 void ReplayMark(CDC *pDC);//复盘标记函数

在MainGobang.cpp文件中添加函数实现

限于文章篇幅,这里只给出了绘制棋盘的函数实现以供参考,其他函数实现可访问:https://github.com/Vaczzy/SimpleGobang中MyGobang_DHK文件夹中MainGobang.cpp文件

CMainGobang::CMainGobang(void)
{}
CMainGobang::~CMainGobang(void)
{
 if(pPieces!=NULL)
 {
 delete []pPieces;
 pPieces=NULL;
 }
 if(pmyRectangle!=NULL)
 {
 delete []pmyRectangle;
 pmyRectangle=NULL;
 }
}
//绘制棋盘函数
//后期可添加棋盘大小参数
//控件坐标
void CMainGobang::DrawMainTable(CDC *pDC,CRect rect,int iTableSize)
{
 iSize=iTableSize;
 //先覆盖背景
 CRect Back;
 Back.top=rect.top+1;
 Back.bottom=rect.bottom-1;
 Back.left=rect.left+1;
 Back.right=rect.right-1;
 pDC->FillSolidRect(&Back,RGB(240,240,240));//填充
 //计算每格长度
 idx=(((rect.right-rect.left)/(iTableSize+1))>((rect.bottom-rect.top)/(iTableSize+1)))?
 (rect.bottom-rect.top)/(iTableSize+1):
 (rect.right-rect.left)/(iTableSize+1);
 CBrush brush(RGB(0,0,0));
 CBrush *OldBrush=pDC->SelectObject(&brush);
 int ixp,iyp;//棋盘星坐标
 //绘制天元
 ixp=(rect.right-rect.left)/2;
 iyp=(rect.bottom-rect.top)/2;
 pDC->Ellipse(ixp-3,iyp-3,ixp+3,iyp+3);
 //绘制星
 ixp-=4*idx;
 iyp-=4*idx;//左上角
 pDC->Ellipse(ixp-3,iyp-3,ixp+3,iyp+3);
 iyp+=8*idx;//左下角
 pDC->Ellipse(ixp-3,iyp-3,ixp+3,iyp+3);
 ixp+=8*idx;//右下角
 pDC->Ellipse(ixp-3,iyp-3,ixp+3,iyp+3);
 iyp-=8*idx;//右上角
 pDC->Ellipse(ixp-3,iyp-3,ixp+3,iyp+3);
 pDC->SelectObject(OldBrush);//恢复设备环境中原来的画笔
 brush.DeleteObject();//释放绘图资源
 //计算棋盘大小并放置于窗口中间
 ymin=(rect.bottom-rect.top)/2-(iTableSize-1)/2*idx;
 ymax=ymin+(iTableSize-1)*idx;
 xmin=(rect.right-rect.left)/2-(iTableSize-1)/2*idx;
 xmax=xmin+(iTableSize-1)*idx;
 for(int x=xmin;x<=xmax;x+=idx)
 {
 pDC->MoveTo(x,ymin);
 pDC->LineTo(x,ymax);
 }
 for(int y=ymin;y<=ymax;y+=idx)
 {
 pDC->MoveTo(xmin,y);
 pDC->LineTo(xmax,y);
 }
}

step3:在xxxx(xxxx为你创建的工程名)Dlg.cpp中编写与界面有关的代码
这一步主要是编写一些与界面有关的代码

本程序的位置反馈主要添加在OnMouseMove函数中,如下:

限于文章篇幅,文件所有代码可访问:https://github.com/Vaczzy/SimpleGobang 中 MyGobang_DHK文件夹中MyGobang_DHKDlg.cpp文件

//鼠标移动函数
void CMyGobang_DHKDlg::OnMouseMove(UINT nFlags, CPoint point)
{
 // TODO: 在此添加消息处理程序代码和/或调用默认值
 CPoint pt;
 CRect rect;
 GetDlgItem(IDC_MainTable)->GetWindowRect(&rect);//获取控件屏幕坐标
 GetCursorPos(&pt);//获取鼠标点击坐标(屏幕坐标坐标)
 pt.x-=rect.left;//转化为控件中坐标
 pt.y-=rect.top;
 CDC *pDC=picMain.GetDC();//获取该控件的画布
 if(bIsReady)
 {
 gobang.DrawRectangle(pDC,pt);
 }
 
 CDialogEx::OnMouseMove(nFlags, point);
}

程序界面

打开程序

棋局进行中

棋局结束

最后,如果你对这个程序的算法有任何改进意见可以到我的github地址:https://github.com/Vaczzy/SimpleGobang对代码进行修改和优化。在这个地址中,你将在README.md看到对这个程序更详细的描述,我还在其中贴上了我的邮箱地址,如有任何问题,你可以通过这个地址联系我 :)

总结

以上所述是小编给大家介绍的使用C++ MFC编写一个简单的五子棋游戏程序,希望对大家有所帮助,也非常感谢大家对脚本之家网站的支持!

相关文章

  • C++中的static和const的关键字用法详解

    C++中的static和const的关键字用法详解

    这篇文章主要介绍了C++中的static和const的关键字用法详解,这是一道经常在面试中被问到的知识,本文给大家详细介绍下,需要的朋友可以参考下
    2023-06-06
  • C++实现简单的学生管理系统

    C++实现简单的学生管理系统

    本文给大家分享的是使用C++实现的简单的学生管理系统的代码,主要是通过链表来实现,非常简洁,有需要的小伙伴可以参考下。
    2015-07-07
  • c语言标准库中字符转换函数和数字转换函数

    c语言标准库中字符转换函数和数字转换函数

    这篇文章主要介绍了c标准库中字符转换函数和数字转换函数,需要的朋友可以参考下
    2014-04-04
  • C++实现LeetCode(94.二叉树的中序遍历)

    C++实现LeetCode(94.二叉树的中序遍历)

    这篇文章主要介绍了C++实现LeetCode(94.二叉树的中序遍历),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • c++引用传参和指针传参的区别及说明

    c++引用传参和指针传参的区别及说明

    这篇文章主要介绍了c++引用传参和指针传参的区别及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • C语言的可变参数函数实现详解

    C语言的可变参数函数实现详解

    某些情况下我们希望函数的参数个数可以根据需要确定,因此c语言引入可变参数函数。典型的可变参数函数的例子有printf()、scanf()等,下面我就开始讲解
    2021-08-08
  • VS中scanf函数报错问题的几种解决方法

    VS中scanf函数报错问题的几种解决方法

    本文主要介绍了VS中scanf函数报错问题的几种解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-07-07
  • C++ 反向迭代器模拟实现

    C++ 反向迭代器模拟实现

    反向迭代器reverse_iterator是一种反向遍历容器的迭代器,也就是从最后一个元素到第一个元素遍历容器,本文主要介绍了C++ 反向迭代器模拟实现,感兴趣的可以了解一下
    2024-01-01
  • C++实现地铁自动售票系统程序设计

    C++实现地铁自动售票系统程序设计

    这篇文章主要为大家详细介绍了C++实现地铁自动售票系统程序设计,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • c语言没有try catch的替代方案

    c语言没有try catch的替代方案

    这篇文章主要介绍了c语言没有try catch的替代方案,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-06-06

最新评论