1、课程设计成绩考勤成绩( %) 指导老师评语报告及程序成绩( %)总评成绩指导老师签名: windows 程序设计课 程 设 计 报 告学院(系): 计算机科学与技术系 班 级: 计专 2 班 学生姓名: 梁剑 学号 0907045233 指导教师: 时间: 从 2010 年 1 月 18 日 到 2010 年 1 月 22 日摘要1. 能够利用所学的基本知识, 设计一个简单的五子棋序,具有以下功能: 数据结构的设计;五子棋棋盘的绘制。人机下棋时,计算机下棋算法的设计。人机下棋时,判断任一方获胜的算法的设计。关键字: MFC 编程,Windows 程序Windows 程序设计课程设计报告3目录
2、项目一: 五子棋1 设计目的与要求 11.1 设计目的 .11.2 设计内容 .11.3 设计要求 .12 设计环境或器材、原理与说明 32.1 设计环境与器材 .32.2 原理与说明 .33 设计过程及程序代码 .63.1 服务器端设计 63.1.1 界面设计 .63.1.2 人下棋设计 83.1.3 电脑下棋设计 83.1.4 搜索最优下棋点 94 设计结果与分析 214.1 设计结果 .214.2 设计分析 .225 设计体会与建议 23参考文献 24五子棋Windows 程序设计课程设计报告41 设计目的与要求1.1 设计目的1、进一步掌握利用 Visual C+进行程序设计的能力;2
3、、进一步理解和运用面向对象程序设计的思想和方法;3、初步掌握开发一个小型实用系统的基本方法;4、学会调试一个较长程序的基本方法;5、理解 Windows 程序的运行过程;1.2 设计内容能够利用所学的基本知识, 设计一个简单的学生信息管理应用程序,具有以下功能:数据结构的设计;五子棋棋盘的绘制。 人机下棋时,计算机下棋算法的设计。人机下棋时,判断任一方获胜的算法的设计。1.3 设计要求整个程序使用 winsocket 函数做网络数据收发,基于 UDP 协议。可以直接使用Windows API 编程(SDK 编程) ,也可以使用 MFC 编程。本课程设计中我们使用的是MFC 编程。其具体的设计要
4、求如下所述:Windows 程序设计课程设计报告52 设计环境或器材、原理与说明2.1 设计环境与器材因为选择使用 MFC 编程 Windows 环境与 Microsoft Visual C+ 6.0 编译环境;2.2 原理与说明首先利用 mfc 建立单文档窗口,在窗口上画 19*19 的表格,把每个表格点的信息存在二维数组 wzq1919中。白棋为 1,黑棋为-1,这样当要测是否结束时只要查看 4 个方向的绝对值是否等于 5,就可以判定输赢了如图:Windows 程序设计课程设计报告63.1 设计过程及程序代码3.11 界面设计:图 3-2 五子棋界面设计打开应用程序时游戏会自动开始。显示表
5、格代码:CMyDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);/ TODO: add draw code for native data hereCBrush mybrush1;mybrush1.CreateSolidBrush(RGB(192,192,192); CRect myrect1(0,0,1200,800);pDC-FillRect(myrect1,/画棋盘框线CPen mypen;CPen*myoldPen;mypen.CreatePen(PS_SOLID,1,RGB(0,0,0);myoldPen=pDC-SelectObject(fo
6、r(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“);Windows 程序设计课程设计报告7for(int n=0;nBitBlt(n*20+32,m*20+32,160,160, else if(wzqnm=-1)/显示黑棋Dc.SelectObject(m_bmblack);
7、 pDC-BitBlt(n*20+32,m*20+32,160,160, 3.1.2 人下棋设计涉及到 OnLButtonDown(UINT nFlags, CPoint point)和 OnLButtonUp(UINT nFlags, CPoint point)两个函数了。要用哪一个或用两个?用 Down 函数时是在鼠标按下时放下棋子,可是,要是我们按下后意识到按错了怎么办;那就改用 Up 函数,表示当鼠标键松开时放下棋子。这样子当鼠标点下并放开时界面上会显示相应的棋子。并调用 over 函数判断输赢。代码如下:void CMy3_1View:OnLButtonUp(UINT nFlags,
8、 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/表示存在白棋wzqpxpy=1;/检查是否结束over(point);Windows 程序设计课程设计报告8/换黑棋下colorwhite=false;else if(wzqpxpy=0)Dc.SelectObject(
9、m_bmblack);pDC-BitBlt(px*20+32,py*20+32,160,160,wzqpxpy=-1;over(point);colorwhite=true;CView:OnLButtonUp(nFlags, point);3.1.3 电脑下棋:计算机要下棋?就要定位。即搜索棋盘,找出一个最佳点,放下黑棋。实现的方法是:全盘搜索,并把搜索到的位置,保存在变量。由于有多种情况,我们定义变量如下:CPoint bpointcan4, /这个位置空,它旁边有四个黑棋wpointcan4, /这个位置空,它旁边有四个白棋bpointcan3, /这个位置空,它的旁边有三个黑棋wpoin
10、tcan3, /这个位置空,它的旁边有三个白棋bpointcan2, /这个位置空,它的旁边有两个黑棋wpointcan2, /这个位置空,它的旁边有两个白棋bpointcan1; /不是以上情况,这个位置空3.1.4 搜索最优下棋点并在搜索之前都赋值为(-1, -1) ,然后,进行搜索,并把相应的值保存在相应变量里面,而如果前面已经对变量赋值,我们依然赋值,用新值代替旧值。注意:我们只保存最后一个值,这样的一个好处是,避免了每次都从左上角开始,并且它的随机性比随机函数还随机。全盘搜索完之后,由于上面的变量中至少有一个已经被赋值,即不是(-1,-1 ) ,我们可以采用多数优先的方法,让已经有多
11、个同色棋子的位置先下棋。其原理是,如果已经有四个黑棋,计算机再下一个黑棋就赢了;否则,如果人已经有四个白棋,那么计算机就必须放下一个黑棋,阻止白棋下一步赢;如果已经有三个黑棋,再下一个黑棋,变成四个;否则,如果已经有三个白棋,下一个黑棋,破坏它;两个棋子的同理;否则,在刚才白棋下的地方,顺便找一个位置,下棋。computerdown()函数如下:/轮到计算机下棋void CMy3_1View:computerdown()/把各种情形赋值为如下bpointcan4=(-1,-1);wpointcan4=(-1,-1);bpointcan3=(-1,-1);wpointcan3=(-1,-1);b
12、pointcan2=(-1,-1);wpointcan2=(-1,-1);bpointcan1=(-1,-1);/搜索最好的落棋点for(int i=0;iBitBlt(point.x*20+32,point.y*20+32,160,160,wzqpoint.xpoint.y=-1;/由于原来我们检查是否结束时用的是鼠标点下的坐标,而现在/putdown(CPoint point)函数用的是数组棋盘的坐标,所以必须转换CPoint overpoint;overpoint.x=point.x*20+30;overpoint.y=point.y*20+30;over(overpoint);colo
13、rwhite=true;搜索最佳落棋点:现在就剩下 void bestputdown(int i,int j)函数没有定义了(虽然前面的变量函数已经说明了,当时我们这里是用程序扩展的思路进行的,故如此说明) 。它的实现原理是:在四个方向上,各自计算那个方向上棋子的状态,我们的思路是利用原来定义的白棋为 1,黑棋为-1,的思想,让同个方向上的五个棋子的值相加,取绝对值并赋值给为这个方向定义的局部变量 numi。为什么要用五个棋子的值相加呢?因为,如果几个棋子是同色的,无论黑白,它的绝对值必然大,而对于几个棋子中有黑棋和白棋的,其值必然相加而抵消变小。所以我们可以利用这种方法来寻找旁边有多个同色棋
14、子的空位置(前面已经具体说明) 。在每一个棋盘位置,计算以它为起点的四个方向(横、竖、撇、捺) ,再比较这四个方向中哪个值最大,然后在这个方向上寻找落棋点。/检查四个方向,各算出五个棋子的和并赋值void CMy3_1View:bestputdown(int i,int j)/四个方向的值int num4;int a,k;/ num0 a=0;if(i4)point.y=a;elsepoint.x=1;point.y=b;if(cpoint.y)point.x=2;point.y=c;if(dpoint.y)Windows 程序设计课程设计报告12point.x=3;point.y=d;ret
15、urn point; 而另外的四个函数,有其相似性,分别介绍如下:void 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
16、+1j=1)/下面位置可以下棋,已经有四个白棋wpointcan4.x=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;Windows 程序设计课程设计报告13/ num1 “|“if(n=1)for
17、(k=0;k5;k+)if(wzqij=0)if(wzqij+1=1)wpointcan4.x=i;wpointcan4.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;wpointcan
18、4.y=j;break;elsebpointcan4.x=i;bpointcan4.y=j;break;else if(wzqi+kj+k=0) if(wzqij=1)Windows 程序设计课程设计报告14wpointcan4.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;
19、bpointcan4.y=j;break;else if(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;void searchcandown3(int i,int j,int n)函数:如果最大值是三,它有两种情况,一种是三个同色和两个空;一种是四个同色和一个异色。前一种必定能找到一个空位置,赋值;后一种必定找不到空位置,不赋值。所以我们的想法很简单,先找到空位置,证明有三个同色,这对于玩五子棋来说三个同色是很重要的,再判断是
20、哪种颜色,赋相应的值。/最多有三个同色void CMy3_1View:searchcandown3(int i, int j, int n)Windows 程序设计课程设计报告15int k=0;/ 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)fo
21、r(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)bpointcan3.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)
22、for(k=0;k5;k+)if(wzqi-kj+k=0)Windows 程序设计课程设计报告16if(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; void searchcandown2(int i,int j,int n)函数:如果最大值是二,也有两种情况:一种是有两个同色和三个空位置;一种是有三个同色和一个异色和一个空位置,并且只算三个同色不连在一起的情况(因为如果有三个连续的情况,重全盘搜索的角度看,必然会被另外的
23、情况所代替) 。分两种算法:一种是有一个空位置,一种是有三个空位置。前者先找到空位置,再判断它下面两个是否同色,同色则赋值给相应变量,异色则不赋值,因为意义不大;后者只要找到一个空位置就行了。/最多有两个同色void CMy3_1View: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=wzq
24、i+a+1j+wzqi+a+2j;/都是黑棋if(b=-2)/下面位置可以下棋,旁边有两个黑棋bpointcan2.x=i+a;bpointcan2.y=j;/都是白棋if(b=2)wpointcan2.x=i+a;wpointcan2.y=j;/如果有三个空位置,说明另外两个同色if(m=3)Windows 程序设计课程设计报告17for(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
25、/如果两个是白棋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=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(wz
26、qij+a=-1)for(b=0;b5;b+)if(wzqij+b=0)Windows 程序设计课程设计报告18bpointcan2.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.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(
27、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)Windows 程序设计课程设计报告19wpointcan2.x=i+b;wpointcan2.y=j+b; break;/ n
28、um3 “/“m=0;if(n=3)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;
29、break;else if(wzqi-aj+a=1)for(b=0;b5;b+)if(wzqi-bj+b=0)wpointcan2.x=i-b;wpointcan2.y=j+b; break;void searchcandown1(int i,int j,int n)函数:Windows 程序设计课程设计报告20最后的一个函数是 searchcandown1(int i, int j, int n),这是为了预防用的,如果以上情况不发生怎么办,总该下棋吧!而这个函数就是为了它而生的。这里就说明了为什么我们要添加 vspoint 的原因了,它保存了上次白棋下棋的位置,而我们在没有办法的情况下,也
30、只能采取这一步,在白棋旁边随便找个位置算了。/如果五个位置的和是一void CMy3_1View:searchcandown1(int i, int j, int n)/计算刚才白棋落棋点int ii=(vspoint.x-30)/20;int jj=(vspoint.y-30)/20;int a;for(a=0;a5;a+)/如果不到边界if(ii+a19)/向右,如果有空位置if(wzqii+ajj=0)/在这个位置下黑棋bpointcan1.x=ii+a;bpointcan1.y=jj;return;/到了边界else/向左,如果有空位置if(wzqii-1jj=0)bpointcan1
31、.x=ii-a;bpointcan1.y=jj;return;Windows 程序设计课程设计报告214 设计结果与分析4.1 设计结果4.2 设计分析因为该程序是博弈类棋类游戏,其中涉及到了人工智能和搜索最优算法,这对于我现在的水平还不足于设计出足够强大的算法。所以在借鉴和学习的基础上,利用现成的算法加于改进。Windows 程序设计课程设计报告225 设计体会与建议通过本次基 Windows 程序设计,我受益匪浅,并对 Windows 程序设计这一门课程与相关一些技术有了更深一步的认识。在实验中,我们可以把这学期所学的理论知识和实践联系起来,在所要设计的程序中渐渐融会贯通。虽然我们对这些知
32、识还运用得还不是很熟练,但是相信在现在和今后的学习中会得到更加深刻的掌握。本课程设计是设计一个程序,实现 人机和人人之间下棋。通过设计我们进一步掌握利用 Visual C+进行程序设计的能力;进一步理解和运用面向对象程序设计的思想和方法;初步掌握开发一个小型实用系统的基本方法;学会调试一个较长程序的基本方法;理解 Windows 程序的运行过程;掌握 windows 编程方法。总的来说通过本次实验,我学习到了许多东西,增强了一定的实践能力。课程设计过程中我们一边设计一边探索,发现理论和实践要充分地结合,是需要扎实的基本功的,这就表明学好基础知识是理论付诸实践的前提。希望在以后我们能充分利用实习
33、的机会充实自己,并希望有更多的这样的实践机会。Windows 程序设计课程设计报告XXIII参考文献:1Charles Petzold 著,Windows 程序设计北京博彦科技发展有限公司译北京北京大学出版社,19982杨祥金,杨丹等Windows 程序设计教程北京:清华大学出版社,20073Charles PrterzoldProgramming Windows by Charles PrterzoldMicrosoft Press,19984何立起著,陆东晖,杜坚贞改编Borland C+ Windows 程序设计北京:人民邮电出版社,19945Vc+游戏编程 作者:王鹏生 2001.12