《MFC-C++五子棋课程设计报告(共23页).doc》由会员分享,可在线阅读,更多相关《MFC-C++五子棋课程设计报告(共23页).doc(23页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、精选优质文档-倾情为你奉上课程设计成绩考勤成绩( %)指导老师评语报告及程序成绩( %)总评成绩指导老师签名: windows程序设计课 程 设 计 报 告 学院(系): 计算机科学与技术系 班 级: 计专2班 学生姓名: 梁剑 学号 指导教师: 时间: 从 2010 年1 月18 日 到2010 年1 月22 日专心-专注-专业摘要1. 能够利用所学的基本知识, 设计一个简单的五子棋序,具有以下功能:数据结构的设计;五子棋棋盘的绘制。人机下棋时,计算机下棋算法的设计。人机下棋时,判断任一方获胜的算法的设计。关键字: MFC编程,Windows程序目录项目一: 五子棋五子棋1 设计目的与要求1
2、.1 设计目的1、进一步掌握利用Visual C+进行程序设计的能力;2、进一步理解和运用面向对象程序设计的思想和方法;3、初步掌握开发一个小型实用系统的基本方法;4、学会调试一个较长程序的基本方法;5、理解Windows程序的运行过程;1.2 设计内容能够利用所学的基本知识, 设计一个简单的学生信息管理应用程序,具有以下功能:数据结构的设计;五子棋棋盘的绘制。人机下棋时,计算机下棋算法的设计。人机下棋时,判断任一方获胜的算法的设计。1.3 设计要求整个程序使用winsocket 函数做网络数据收发,基于UDP协议。可以直接使用Windows API编程(SDK编程),也可以使用MFC编程。本
3、课程设计中我们使用的是MFC编程。其具体的设计要求如下所述:2 设计环境或器材、原理与说明2.1 设计环境与器材因为选择使用MFC编程Windows环境与Microsoft Visual C+ 6.0 编译环境;2.2 原理与说明首先利用mfc建立单文档窗口,在窗口上画19*19的表格,把每个表格点的信息存在二维数组wzq1919中。白棋为1,黑棋为-1,这样当要测是否结束时只要查看4个方向的绝对值是否等于5,就可以判定输赢了如图:3.1设计过程及程序代码3.11界面设计: 图3-2 五子棋界面设计打开应用程序时游戏会自动开始。显示表格代码:CMyDoc* pDoc = GetDocument
4、();ASSERT_VALID(pDoc);/ TODO: add draw code for native data here CBrush mybrush1; mybrush1.CreateSolidBrush(RGB(192,192,192); CRect myrect1(0,0,1200,800); pDC-FillRect(myrect1,&mybrush1); /画棋盘框线 CPen mypen; CPen*myoldPen; mypen.CreatePen(PS_SOLID,1,RGB(0,0,0); myoldPen=pDC-SelectObject(&mypen); for(
5、int i=0;iMoveTo(40,40+i*20); pDC-LineTo(400,40+i*20); pDC-MoveTo(40+i*20,40); pDC-LineTo(40+i*20,400); /重画时显示存在的棋子 CDC Dc; if(Dc.CreateCompatibleDC(pDC)=FALSE) AfxMessageBox(Cant create DC); for(int n=0;n19;n+) for(int m=0;mBitBlt(n*20+32,m*20+32,160,160,&Dc,0,0,SRCCOPY); else if(wzqnm=-1) /显示黑棋 Dc.
6、SelectObject(m_bmblack); pDC-BitBlt(n*20+32,m*20+32,160,160,&Dc,0,0,SRCCOPY); 3.1.2 人下棋设计涉及到OnLButtonDown(UINT nFlags, CPoint point)和OnLButtonUp(UINT nFlags, CPoint point)两个函数了。要用哪一个或用两个?用Down函数时是在鼠标按下时放下棋子,可是,要是我们按下后意识到按错了怎么办;那就改用Up函数,表示当鼠标键松开时放下棋子。这样子当鼠标点下并放开时界面上会显示相应的棋子。并调用over函数判断输赢。代码如下:void CM
7、y3_1View:OnLButtonUp(UINT nFlags, CPoint point) / TODO: Add your message handler code here and/or call defaultCDC *pDC=GetDC();CDC Dc;if(Dc.CreateCompatibleDC(pDC)=FALSE) AfxMessageBox(Cant create DC); /是否在棋盘内 if(point.x30&point.x30&point.yBitBlt(px*20+32,py*20+32,160,160,&Dc,0,0,SRCCOPY);/表示存在白棋wzq
8、pxpy=1;/检查是否结束over(point);/换黑棋下colorwhite=false;else if(wzqpxpy=0)Dc.SelectObject(m_bmblack); pDC-BitBlt(px*20+32,py*20+32,160,160,&Dc,0,0,SRCCOPY);wzqpxpy=-1;over(point);colorwhite=true;CView:OnLButtonUp(nFlags, point);3.1.3 电脑下棋:计算机要下棋?就要定位。即搜索棋盘,找出一个最佳点,放下黑棋。实现的方法是:全盘搜索,并把搜索到的位置,保存在变量。由于有多种情况,我们定
9、义变量如下:CPoint bpointcan4,/这个位置空,它旁边有四个黑棋wpointcan4,/这个位置空,它旁边有四个白棋bpointcan3,/这个位置空,它的旁边有三个黑棋wpointcan3,/这个位置空,它的旁边有三个白棋bpointcan2,/这个位置空,它的旁边有两个黑棋wpointcan2,/这个位置空,它的旁边有两个白棋bpointcan1;/不是以上情况,这个位置空3.1.4搜索最优下棋点并在搜索之前都赋值为(-1,-1),然后,进行搜索,并把相应的值保存在相应变量里面,而如果前面已经对变量赋值,我们依然赋值,用新值代替旧值。注意:我们只保存最后一个值,这样的一个好处
10、是,避免了每次都从左上角开始,并且它的随机性比随机函数还随机。全盘搜索完之后,由于上面的变量中至少有一个已经被赋值,即不是(-1,-1),我们可以采用多数优先的方法,让已经有多个同色棋子的位置先下棋。其原理是,如果已经有四个黑棋,计算机再下一个黑棋就赢了;否则,如果人已经有四个白棋,那么计算机就必须放下一个黑棋,阻止白棋下一步赢;如果已经有三个黑棋,再下一个黑棋,变成四个;否则,如果已经有三个白棋,下一个黑棋,破坏它;两个棋子的同理;否则,在刚才白棋下的地方,顺便找一个位置,下棋。computerdown()函数如下:/轮到计算机下棋void CMy3_1View:computerdown()
11、/把各种情形赋值为如下bpointcan4=(-1,-1);wpointcan4=(-1,-1);bpointcan3=(-1,-1);wpointcan3=(-1,-1);bpointcan2=(-1,-1);wpointcan2=(-1,-1);bpointcan1=(-1,-1); /搜索最好的落棋点for(int i=0;i19;i+)for(int j=0;jBitBlt(point.x*20+32,point.y*20+32,160,160,&Dc,0,0,SRCCOPY); wzqpoint.xpoint.y=-1;/由于原来我们检查是否结束时用的是鼠标点下的坐标,而现在/put
12、down(CPoint point)函数用的是数组棋盘的坐标,所以必须转换CPoint overpoint;overpoint.x=point.x*20+30;overpoint.y=point.y*20+30;over(overpoint);colorwhite=true; 搜索最佳落棋点:现在就剩下void bestputdown(int i,int j)函数没有定义了(虽然前面的变量函数已经说明了,当时我们这里是用程序扩展的思路进行的,故如此说明)。它的实现原理是:在四个方向上,各自计算那个方向上棋子的状态,我们的思路是利用原来定义的白棋为1,黑棋为-1,的思想,让同个方向上的五个棋子的
13、值相加,取绝对值并赋值给为这个方向定义的局部变量numi。 为什么要用五个棋子的值相加呢?因为,如果几个棋子是同色的,无论黑白,它的绝对值必然大,而对于几个棋子中有黑棋和白棋的,其值必然相加而抵消变小。所以我们可以利用这种方法来寻找旁边有多个同色棋子的空位置(前面已经具体说明)。在每一个棋盘位置,计算以它为起点的四个方向(横、竖、撇、捺),再比较这四个方向中哪个值最大,然后在这个方向上寻找落棋点。/检查四个方向,各算出五个棋子的和并赋值void CMy3_1View:bestputdown(int i,int j) /四个方向的值int num4;int a,k; / num0 -a=0; i
14、f(i15)for(k=0;k5;k+)a=a+wzqi+kj;num0=abs(a); / num1 |a=0;if(j15)for(k=0;k5;k+)a=a+wzqij+k;num1=abs(a);/ num2 a=0;if(i15&j15)for(k=0;k4)&(j15)for(k=0;k=b)point.x=0;point.y=a;elsepoint.x=1;point.y=b;if(cpoint.y)point.x=2;point.y=c;if(dpoint.y)point.x=3;point.y=d;return point; 而另外的四个函数,有其相似性,分别介绍如下:voi
15、d searchcandown4(int i,int j,int n)函数:如果最大值是四,它必然有一个空位置;我们可以这样计算,如果第一个是空,那我们把它赋值给相应变量;否则,先找那个空位置,然后判断第一个棋子的颜色,并赋相应的值。 /由于相似,下面代码只解释第一个方向/有四个同色棋void CMy3_1View:searchcandown4(int i, int j, int n)int k; / num0 -if(n=0)for(k=0;k5;k+)/如果第一个是空if(wzqij=0)/如果下面有白棋if(wzqi+1j=1)/下面位置可以下棋,已经有四个白棋wpointcan4.x=
16、i;wpointcan4.y=j;break;else/下面位置可以下棋,已经有四个黑棋bpointcan4.x=i;bpointcan4.y=j;break;/如果找到下棋位置,一定能找到!else if(wzqi+kj=0) /如果第一个是白棋if(wzqjj=1)wpointcan4.x=i+k;wpointcan4.y=j;break;/否则第一个是黑棋elsebpointcan4.x=i+k;bpointcan4.y=j;break; / num1 |if(n=1)for(k=0;k5;k+)if(wzqij=0)if(wzqij+1=1)wpointcan4.x=i;wpointc
17、an4.y=j;break;elsebpointcan4.x=i;bpointcan4.y=j;break;else if(wzqij+k=0) if(wzqij=1)wpointcan4.x=i;wpointcan4.y=j+k;break;elsebpointcan4.x=i;bpointcan4.y=j+k;break;/ num2 if(n=2)for(k=0;k5;k+)if(wzqij=0)if(wzqi+1j+1=1)wpointcan4.x=i;wpointcan4.y=j;break;elsebpointcan4.x=i;bpointcan4.y=j;break;else i
18、f(wzqi+kj+k=0) if(wzqij=1)wpointcan4.x=i+k;wpointcan4.y=j+k;break;elsebpointcan4.x=i+k;bpointcan4.y=j+k;break;/ num3 / if(n=3)for(k=0;k5;k+)if(wzqij=0)if(wzqi-1j+1=1)wpointcan4.x=i;wpointcan4.y=j;break;elsebpointcan4.x=i;bpointcan4.y=j;break;else if(wzqi-kj+k=0) if(wzqij=1)wpointcan4.x=i-k;wpointcan
19、4.y=j+k;break;elsebpointcan4.x=i-k;bpointcan4.y=j+k;break;void searchcandown3(int i,int j,int n)函数:如果最大值是三,它有两种情况,一种是三个同色和两个空;一种是四个同色和一个异色。前一种必定能找到一个空位置,赋值;后一种必定找不到空位置,不赋值。所以我们的想法很简单,先找到空位置,证明有三个同色,这对于玩五子棋来说三个同色是很重要的,再判断是哪种颜色,赋相应的值。/最多有三个同色void CMy3_1View:searchcandown3(int i, int j, int n)int k=0;
20、/ num0 -if(n=0)for(k=0;k5;k+)/找到位置if(wzqi+kj=0) /下一个是白棋 if(wzqi+k+1j=1)/下面位置可以下棋,已经有三个白棋 wpointcan3.x=i+k;wpointcan3.y=j; /下一个是黑棋else if(wzqi+k+1j=-1) bpointcan3.x=i+k;bpointcan3.y=j; / num1 |if(n=1)for(k=0;k5;k+)if(wzqij+k=0) if(wzqij+k-1=1) wpointcan3.x=i;wpointcan3.y=j+k;else if(wzqij+k+1=-1)bpoi
21、ntcan3.x=i;bpointcan3.y=j+k;/ num2 if(n=2)for(k=0;k5;k+)if(wzqi+kj+k=0) if(wzqi+k+1j+k+1=1)wpointcan3.x=i+k;wpointcan3.y=j+k;else if(wzqi+k+1j+k+1=-1)bpointcan3.x=i+k;bpointcan3.y=j+k;/ num3 / if(n=3)for(k=0;k5;k+)if(wzqi-kj+k=0)if(wzqi-k-1j+k+1=1) wpointcan3.x=i-k;wpointcan3.y=j+k;else if(wzqi-k-1j
22、+k+1=-1)bpointcan3.x=i-k;bpointcan3.y=j+k; void searchcandown2(int i,int j,int n)函数:如果最大值是二,也有两种情况:一种是有两个同色和三个空位置;一种是有三个同色和一个异色和一个空位置,并且只算三个同色不连在一起的情况(因为如果有三个连续的情况,重全盘搜索的角度看,必然会被另外的情况所代替)。分两种算法:一种是有一个空位置,一种是有三个空位置。前者先找到空位置,再判断它下面两个是否同色,同色则赋值给相应变量,异色则不赋值,因为意义不大;后者只要找到一个空位置就行了。 /最多有两个同色void CMy3_1View
23、:searchcandown2(int i, int j, int n)int k=0,m=0,a=0,b=0; / num0 -if(n=0)/判断有多少个空位置for(k=0;k5;k+)if(wzqi+kj=0) m+=1;/如果只有一个空位置if(m=1)for(a=0;a5;a+)/找到空位置if(wzqi+aj=0)/下面两个棋子值的和b=wzqi+a+1j+wzqi+a+2j;/都是黑棋if(b=-2)/下面位置可以下棋,旁边有两个黑棋bpointcan2.x=i+a;bpointcan2.y=j;/都是白棋if(b=2)wpointcan2.x=i+a;wpointcan2.y
24、=j;/如果有三个空位置,说明另外两个同色if(m=3)for(a=0;a5;a+)/如果两个是黑棋if(wzqi+aj=-1)for(b=0;b5;b+)/如果找到空位置if(wzqi+bj=0)/下面位置可以下棋,旁边有两个黑棋bpointcan2.x=i+b;bpointcan2.y=j;break;else /如果两个是白棋if(wzqi+aj=1)for(b=0;b5;b+)if(wzqi+bj=0)wpointcan2.x=i+b;wpointcan2.y=j;break;/ num1 |m=0;if(n=1)for(k=0;k5;k+)if(wzqij+k=0) m+;if(m=
25、1)for(a=0;a5;a+)if(wzqij+a=0)b=wzqij+a+1+wzqij+a+2;if(b=-2)bpointcan2.x=i;bpointcan2.y=j+a;if(b=2)wpointcan2.x=i;wpointcan2.y=j+a;if(m=3)for(a=0;a5;a+)if(wzqij+a=-1)for(b=0;b5;b+)if(wzqij+b=0)bpointcan2.x=i;bpointcan2.y=j+b;break;else if(wzqij+a=1)for(b=0;b5;b+)if(wzqij+b=0)wpointcan2.x=i;wpointcan2
26、.y=j+b;break;/ num2 m=0; if(n=2)for(k=0;k5;k+)if(wzqi+kj+k=0) m+;if(m=1)for(a=0;a5;a+)if(wzqi+aj+a=0)b=wzqi+a+1j+a+1+wzqi+a+2j+a+2;if(b=-2)bpointcan2.x=i+a;bpointcan2.y=j+a;if(b=2)wpointcan2.x=i+a;wpointcan2.y=j+a;if(m=3)for(a=0;a5;a+)if(wzqi+aj+a=-1)for(b=0;b5;b+)if(wzqi+bj+b=0)bpointcan2.x=i+b;bpointcan2.y=j+b;break;else if(wzqi+aj+a=1)for(b=0;b5;b+)if(wzqi+bj+b=0)wpointcan2.x=i+