1、我一定会继续完善、改进算法,重新设计评估函数,争取让机器达到理想的“智能”。一、课题选则1.题目概述利用VC+实现四子棋游戏,要求提供可视化界面以及二人对战、人机对战的功能。四子棋游戏规则如下:四子棋的棋盘共有7行7列,棋盘是垂直摆放,每名玩者只能左右控制落子的位置。两名玩者轮流每次把一只棋子放进棋盘任何未全满的一行中,棋子会佔据一行中最底未被佔据的位置。两名玩者任何一方先以四只棋子在横,竖或斜方向联成一条直线,便可获胜,游戏亦结束。假如棋盘已完全被棋子填满,但仍未有任何一方成功把四只棋子成一直线,则成为和局。2.选题缘由四子棋游戏规则独特,所以其规则的设计将有别于五子棋等通常的棋类游戏。四子
2、棋人机对战功能的实现需要用到博弈树搜索中的核心算法:。与五子棋不同,因为四子棋的独特性网络中根本没有某某“热心”网友的游戏源码,我找了很久也只找到一个二人对战的四子棋,他还是用C语言在dos下实现的,一点也不人性化。综合以上种种我决定挑战一下自己,用VC实现“我的四子棋”游戏。二、需求分析1.功能需求1.1提供合理的人机交互界面1.2提供二人对战功能1.3提供人机对战功能2.数据结构2.1棋盘数据采用一二维数组grid77存储三、模块设计A.整体思路通过对需求的分析,我认为我的设计工作主要可以分为三大块,第一块是主界面的搭建和棋盘的绘制,第二块是落子和输赢判断的实现,第三块就是二人对战和人机对
3、战的实现。对于第一块,因为有图形学和图像处理的上机经验,我将果断的选择单文档作为界面窗口,用绘制的方式搭建棋盘。对于第二块,对于落子其实就是在响应鼠标左键按下的消息后记录下所需放子的坐标,然后改变内部存储数据,调用绘图函数ondraw()进行绘制。输赢判断就是对于每下一颗棋子搜索其横向竖向交叉斜向的棋子,如若有四颗连成一线的就判为赢。对于第三模块,这是整个游戏的核心,二人对战相对好实现。人机对战需要用到博弈树搜索需要用到alphabeta剪枝算法,还需要设定以静态评估函数,这两方面是最困难也是最重要的部分。B.具体设计1.主界面设计1.1单文档窗口大小的限定 我们知道通过VC+工程创建的单文档
4、都有默认的大小,那个大小太大不适合 作为游戏的界面窗口大小。所以我希望自定义其大小,而且在此游戏中不需要用工 具栏,所以我希望通过人为操作去掉工具栏。具体实现:在Frame框架类里面的PreCreateWindow( )创建窗口函数总添加以下代码 cs.style&=WS_MAXIMIZEBOX; /禁止对文档最大化操作=WS_THICKFRAME; cs.cx=700;/ /自定义文档大小 cs.cy=500; cs.y=180; cs.x=300;=FWS_ADDTOTITLE;/将FWS_ADDTOTITLE去掉 cs.lpszName=我的四子棋; /改变文档标题 将OnCreate(
5、LPCREATESTRUCT lpCreateStruct)函数中以下代码屏蔽即可去掉工具栏 /*if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) | !m_wndToolBar.LoadToolBar(IDR_MAINFRAME) TRACE0(Failed to create toolbarn); return -1; / fail to create
6、*/1.2棋盘绘制棋盘绘制在view类里面的ondraw函数里实现,创建画笔蓝色画笔通过MoveTo、LineTo函数画出棋格,创建天蓝色画刷绘制棋格背景色。创建红色、黄色画刷用于绘制双方棋手棋子。具体代码如下:CRect rect; CBrush *brush,*brush1,*brush2,*brush3; brush = new CBrush; brush1 = new CBrush; brush2 = new CBrush; brush3 = new CBrush; brush-CreateSolidBrush(RGB(150, 205 ,205); brush1-CreateSoli
7、dBrush(RGB(255, 0 ,0);/红色画刷 brush2-CreateSolidBrush(RGB(255, 255 ,0);/黄色画刷 brush3-CreateSolidBrush(RGB(128, 128 ,28);/bai色画刷 this-GetClientRect(&rect); pDC-FillRect(&rect,brush); CClientDC dc(this); CPen m_pen(PS_SOLID,1,RGB(0,0,255); /将画笔选入设备列表 CPen *pOldPen = dc.SelectObject(&m_pen); int i; for(i=
8、0;i8;i+) dc.MoveTo(bx,by+width*i); dc.LineTo(bx+width*7,by+width*i); dc.MoveTo(bx+width*i,by); dc.LineTo(bx+width*i,by+width*7); for (i=0;7; for (int j=0;jSelectObject(brush1); pDC-Ellipse(bx+width*(i+0.5)-r,by+width*(j+0.5) -r,bx+width*(i+0.5)+r,by+width*(j+0.5)+r); break; case 2: /pDC-SelectStockO
9、bject(WHITE_PEN); pDC-SelectObject(brush2);Ellipse(bx+width*(i+0.5)-r,by+width*(j+0.5)-r,bx+width*(i+0.5)+r,by+width*(j+0.5)+r);SelectStockObject(BLACK_PEN); case 3:SelectObject(brush3);Ellipse(bx+width*(i+0.5)-(r+5),by+width*(j+0.5)-(r+5),bx+width*(i+0.5)+(r+5),by+width*(j+0.5)+(r+5); default: 2.模式
10、选择设计2.1更改菜单按钮 在菜单栏中添加模式按钮“二人对战”和“人机对战”2.2响应选择按钮消息通过MFC类向导在View类中响应“二人对战”和“人机对战”的按钮消息,实现方式如下:void CMYSIZIQIView:OnPvsp() / TODO: Add your command handler code here reset(); pvsp=true; Invalidate();/是当前窗口无效,需要重绘OnPvsc() pvsc=true; RorY=true; pvsp=false;3.Onleftbuttondown()函数设计3.1根据鼠标坐标转换出在存储数组中对应的下标in
11、t px=(point.x-bx)/width; int py=(point.y-by)/width;3.2限定落子只可以在该列最下面一个空格 for(int j=6;j=0;j-) if(gridpxj=0) py=j; break;3.3二人对战、人机对战程序响应 if(0=px&px7&0=py&pyi-)/&棋子左边 /MessageBox(红赢 if(gridiy=color) HWIN+; if(gridiy!=color) break; if(HWIN=4&color=1)/左边可能已经三个棋子 for ( i=x-1;i-)/一方赢了则改变其颜色 if(gridiy=color
12、) gridiy=3; gridxy=3; MessageBox( reset(); Invalidate(); return true; else if (HWINcolor=2) if(gridiy=color) gridiy=3; 黄赢 t0=HWIN; for (i=x+1;=6;i+)/&棋子右边color=1) for ( i=x+1;i+)/一方赢了则改变其颜色 if(HWIN-t0=2) gridx-1y=3; if(HWIN-t0=1) gridx-1y=3;gridx-2y=3;具体判断细节见注释4.2竖向判断是否四子连线/*竖向判断*/ int SWIN=1; for (
13、 j=y+1;j+)/&棋子下边 /MessageBox( if(gridxj=color) SWIN+; if(gridxj! if(SWINcolor=1)/下边可能已经三个棋子 for (j=y+1;j+)/一方赢了则改变其颜色 if(gridxj=color&j-y4.3左上右下方向判断是否四子连线 /*左上右下方向*/ int LRWIN=1; for (i=x-1,j=y-1;=0&i-,j-)/&棋子左上方 if(gridij=color) LRWIN+; if(gridij! if(LRWINcolor=1)/左上可能已经三个棋子 for (i=x-1,j=y-1;i-,j-) /一方赢了则改变其颜色 if(gridij=color&(y-j t0=LRWIN; for (i=x+1,j=y+1;=6&i+,j+)/&棋子右下边 for (i=x+1,j=y+1;i+,j+) /一方赢了则改变其颜色(j-y)color=1)/可能已经三个棋子 for (i=x+1,j=y-1;i+,j-) /一方赢了则改变其颜色 else if (RLWIN t0=RLWIN; for (i=x-1,j=y+1;i-,j+)/&棋子左下边
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1