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

简述

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

程序实现

step1:在VS中创建一个MFC对话框程序(这一步骤可以参考具体教程,本文主要在于给出一个简单的实现)
step2:新建一个名为CMainGobang的类,在类中编写主要代码
(完整代码可访问我的github: https://github.com/Vaczzy/SimpleGobang

  • 在该类的头文件中添加需要用到的函数声明和结构体
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);//复盘标记函数
  • 在该类的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中编写与界面有关的代码
这一步主要是编写一些与界面有关的代码
比如在鼠标移动过程中在其对应的棋格的位置绘制一个矩形框(图见后文)

//鼠标移动函数
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。在这个地址中,你还可以看到对这个程序更详细的描述,我还贴上了我的邮箱地址,如有任何问题,你可以通过这个地址联系我 :)

发布了1 篇原创文章 · 获赞 0 · 访问量 64

猜你喜欢

转载自blog.csdn.net/weixin_44899883/article/details/104379195