三子连珠游戏设计VC实现全过程.doc_第1页
三子连珠游戏设计VC实现全过程.doc_第2页
三子连珠游戏设计VC实现全过程.doc_第3页
三子连珠游戏设计VC实现全过程.doc_第4页
三子连珠游戏设计VC实现全过程.doc_第5页
已阅读5页,还剩14页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

三子连珠游戏设计 【摘要】模仿五子棋的形式,编写有一方三子或五子连成一线即获胜的程序,具体要求:1、 玩家可以设置棋盘的大小,即在游戏开始时输入一变量n(n=39),使棋盘的大小为nn。2、 本程序用if-else选择语句来判断获胜者,如果棋盘变大这将非常频繁,现要求将这一功能用循环语句实现,且适用于任意大小的棋盘。3、 加入可以悔棋的功能,要求任意方可以在对方下棋后悔改一步,即将对方当前步和本方上一步删除,本方重新下棋。关键词:三子连珠 小游戏 VC+程序目录程序功能简介3课程设计要求3程序设计思想4原程序各个功能说明4课程设计要求的实现6主要源程序及注释81主函数82.胜负条件的判定10设计过程中的疑难及解答方案和设计的不足11设计过程中的疑难及解答方案11设计的不足12总结12附1:程序运行界面(棋盘4*4的三子连珠游戏)13程序功能简介 该程序是TICTACTOE游戏,棋盘为3*3,3个棋子连起来即为赢。输入参数时,若输入的数字超过边界或在已有棋子的地方再输入,则提示出错,要求重新输入。课程设计要求1.将程序改写成类。2.将棋盘扩充成4*4。3.统计输赢结果并打印输出。4.选做:使游戏更生动。(输赢条件相同)评定难易程度:B程序设计思想 设计一个玩家下棋的操作类,里面封装了棋盘棋子类别和输赢次数等成员数据。 操作类的函数包括有初始化棋盘下棋判断输赢等。定义一个类的对象,在调用类中函数时直接使用对象名加函数名即可。 将两个玩家定义为两个数组用于区分他们的信息,分别用O和X代表两个玩家所用棋子,然后分别对两个玩家通过已定义的类的对象调用类中的函数,完成下棋过程。 进一步改进程序:1. 程序中用if else if格式的语句来判断玩家的输赢,当棋盘增大时,三子连珠的各种可能性成倍增加,使得语句非常繁琐,所以将其改为for语句的循环结构进行判断,当棋盘增大时,只需更改循环条件结束的参数即可,可灵活使用于各种尺寸的棋盘。2. 为防止用户误操作,特别是在姓名的输入时的失误,可以采用cin.getline函数读入在判断确认。3. 在完成第一步的基础上可将三子连珠扩充为标准的五子棋。原程序各个功能说明原程序的结构输出菜单及提示信息输入姓名由“O”先手下棋结束输出最终结果询问是否继续下棋“O”输入棋子所在的行列判断胜负和棋条件输出结果“X”输入棋子所在的行列不符合错误正确错误正确符合 YN1. 类的说明 类是对一组具有相同属性、相同行为的对象的抽象的描述,不占用内存空间。可以把类看作“理论上”的对象,也就是说,它为对象提供蓝图,但在内存中并不存在。从这个蓝图可以创建任何数量的对象。从累创建的所有对象都有相同的成员:属性、行为或方法。这些对象才是具体的独立的个体,占用存储空间,因此,对象又称作类的实例。 下面以具体程序说明。 在头文件之后定义了一个名为CGobang的类:class CGobang char board44;/用数组来定义一个4*4的棋盘public:void Guize();/打印菜单总体情况,说明游戏规则和方法,无返回值 void Dayinqp();/打印棋盘,无返回值void Xiaqi(char*,int &,int &,char);/下棋,无返回值int Huosheng(int,int,char);/判断那个选手赢,返回值为一整形数void Choice(char &);/是否再玩,无返回值void Chongzhi();/重置棋盘,无返回值; 在这个类中,定义了一个未经说明的数组被默认为私有成员,即char board44,用它来存储玩家在下棋的过程中所输入的棋子的坐标,并以此来区分表示不同的两个玩家。另外,这个类中还说明了五个没有返回值的函数以及一个返回值为整形数的函数,对它们的定义将出现在主函数完成之后,所以本着“先定义,后调用”的原则,在类中的说明相当于自定义函数中的函数说明,这样可以使在主函数调用类中的公有函数时变得更加明了清晰。 在这个函数中,对类的对象的定义出现在了主函数第一行,即:CGobang s;/定义类的一个对象s对这个对象的定义的目的是,在下面不同玩家的下其中的不同操作中,可以直接通过这个对象来分别调用类中的任意公有成员函数,这样就避免了通过类名来调用函数时可能出现的冗长。可以说,在这个程序里,这个对象s起到了把主函数与类连接起来的桥梁作用。课程设计要求的实现一、类的封装。 首先,在源程序代码中出现的主要函数程序有:void PrintBoard(); / 打印棋盘void PrintInfo(); /输出游戏提示信息void PrintStats(int, int, int); / 输出统计的胜负信息void IfError(int&, int&); / 判断输入时候有错void ChoiceOfChar(char&); / 询问用户是否在玩一局void PromptTurnO(int&, int&); / 选择“O”的玩家下棋(先走)void PromptTurnX(int&, int&); / 选择“X”的玩家下棋(后走)char board33; / 棋盘在我的程序中的主要函数程序为:void Guize();/打印菜单总体情况,说明游戏规则和方法,无返回值void Dayinqp();/打印棋盘,无返回值void Xiaqi(char*,int &,int &,char);/下棋,无返回值int Huosheng(int,int,char);/判断那个选手赢,返回值为一整形数void Choice(char &);/是否再玩,无返回值void Chongzhi();/重置棋盘,无返回值以此来对比说明。源代码中的关于打印棋盘以及规则提示的说明的函数没有变动。去掉了关于输出统计胜负信息的函数,在主函数体中用三个一组的条件自增变量代替,这样减少了复杂的函数调用,说明以及定义,精简了程序,并且达到了预想的目的。由于对玩家输入是否有错的判断在玩家每次确定下棋之后必须进行,所以如果像源代码一样把玩家下棋的函数和判断是否有误分开定义的话,在没下一步棋之后都要重复调用判断函数,显得十分复杂,所以把源代码中的判断是否有错的函数与玩家下棋合并在 void Xiaqi(char*,int &,int &,char)中,对它们的定义在后面的类的成员函数的定义中一起定义,这样可以减少很多不必要的麻烦,起到了精简程序的作用。源代码中把连个玩家分别定义为两个函数,用以区别先后手,然后在定义一个数组char board33(由于源代码中显示的是3*3的棋盘,所以数组定义为board33)来表示棋盘。在这点我做了比较大的改动,首先是定义了一个类中的私有成员数组,用以记录每位玩家所下棋子的坐标,这样既可以通过用不同的指针变量来指向键盘的方法来区分不同的玩家,亦可以同时用它表示整个棋盘。这样使程序得到了进一步的精简。void CGobang:Xiaqi(char*player1,int & x,int & y,char c)cout该player1下棋了,请输入:endl;coutx;cout y;while(x4|y4|x1|y1| !=boardx-1y-1)/输入数字超过边界或在已有棋子的地方再输入/ !=boardx-1y-1表示已有棋子cout对不起,您的输入有误,请重新输入!endl;coutx;cout y;boardx-1y-1=c;/在x行,y列处下O或X由于需要重复使用空棋盘,我又增加了一个重置棋盘的函数void Chongzhi()来进行每次开始下棋时的棋盘清空重置。void CGobang:Chongzhi()for(int Row=0;Row4;Row+)for(int Column=0;Column4;Column+)boardRowColumn= ;完成对主要函数的改动之后,把它们封装到类CGobang中即可。二、将棋盘扩充为4*4在类的封装中已经详细的将我改动过的棋盘说明了,所以,要把棋盘扩充为n*n只需把定义过的私有成员数组boardnn中的n改为所需数字即可。即,定义board44,就完成了对棋盘4*4的扩充。三、统计输出结果并打印输出。同样,在类的封装中也已说明我对记录胜负结果以及输出的方法,下面给出源代码:记录胜负结果:int FirstWin=0,SecondWin=0,Draws=0,x,y,N;在每次获胜、失败以及和棋的判断完成之后,令FirstWin SecondWin Draws分别依情况自增,达到记录胜负次数的目的。打印输出:/输出游戏输赢次数coutplayer1赢了FirstWin次endl;coutplayer2赢了SecondWin次endl;cout和Draws次endl;cout谢谢使用。endl;cout任意键继续。endl;即在主函数结束时输出已记录的数值即可完成。主要源程序及注释1主函数void main ()/主函数CGobang s;/定义类的一个对象s s.Guize();/通过已定义的类的对象s调用Guize函数,提示玩家如何进行游戏char player120,player220;/定义两个玩家的姓名变量,分别用两个数组储存int FirstWin=0,SecondWin=0,Draws=0,x,y,N;/说明变量,并对部分变量付初值,以待计算输赢结果char choice=Y;cin.ignore(20,n);/输入输出流,前面如果有输入把输入行所有字符 /取空,以便后面的输入从新的一行开始cout请输入第一个玩家姓名:;cin.getline(player1,20);/连续读取数据,实现对玩家一命名cout请输入第二个玩家姓名:;cin.getline(player2,20);/连续读取数据,实现对玩家二命名while(choice=Y|choice=y)/条件成立,开始下棋 s.Chongzhi();/通过对象s调用Chongzhi函数 N=0;/对变量付初值,表示已经下在棋盘上的妻子总数while(N=16)/在棋盘未满的条件下下棋s.Dayinqp();/打印棋盘s.Xiaqi(player1,x,y,O);/调用下棋的运行函数N+;/记录已下棋子数if(s.Huosheng(x-1,y-1,O)/返回值不为0则条件成立coutplayer1赢了。endl;FirstWin+;/记录玩家一所赢局数break;/终止本次循环s.Dayinqp();/交换玩家下棋,下棋方法同上s.Xiaqi(player2,x,y,X);N+;if(s.Huosheng(x-1,y-1,X)coutplayer2赢了。endl;SecondWin+;/记录玩家二所赢局数break;if(N=16)/当棋盘满时,此局结束cout和棋!;Draws+;/记录平局总数break;s.Choice(choice);/让玩家选择是否在玩一次/输出游戏输赢次数coutplayer1赢了FirstWin次endl;coutplayer2赢了SecondWin次endl;cout和Draws次endl;cout谢谢使用。endl;cout任意键继续。=0)&(y-a=0)&(boardx-ay-a=c);a+)if(+count=3) return 1;/从 右斜下 方向判断是否构成胜利条件for(a=1;(x+a4)&(y+a=0)&(boardx-ay=c);a+)if(+count=3) return 1;/从 下向上 方向判断是否构成胜利条件for(a=1;(x+a=0)&(boardxy-a=c);a+)if(+count=3) return 1;/从 右至左 方向判断是否构成胜利条件for(a=1;(y+a=0)&(y+a4)&(boardx-ay+a=c);a+)if(+count=3) return 1;/从 左斜下 方向判断是否构成胜利条件for(a=1;(x+a=0)&(boardx+ay-a=c);a+)if(+count=3) return 1;return 0;设计过程中的疑难及解答方案和设计的不足 设计过程中的疑难及解答方案在这次课程设计的过程中,我遇到了不小的阻力,还有也从中学习到了很多以前没有掌握好或这根本没有掌握的知识。 在定义玩家名字的输入接受的时候我遇到了一个从未见过的函数cin.ignore(),这个函数是我从一个同样是输入存储用户姓名的程序里看到的,上面对它的注释是:“输入输出流,前面如果有输入把输入行所有字符去空,一边后面的输入从新的一行开始。”我对这个想了很长时间,但是一直没有明白。最后解决问题的方法是我通过网络查询找到了这个函数,在其他一些人那里得到了答案:“cin.ignore(a,ch)方法是从输入流(cin)中提取字符,提取的字符被忽略(ignore),不被使用。每抛弃一个字符,它都要计数和比较字符:如果计数值达到a或者被抛弃的字符是ch,则cin.ignore()函数执行终止;否则,它继续等待。它的一个常用功能就是用来清除以回车结束的输入缓冲区的内容,消除上一次输入对下一次输入的影响。比如可以这么用:cin.ignore(1024,n),通常把第一个参数设置得足够大,这样实际上总是只有第二个参数n起作用,所以这一句就是把回车(包括回车)之前的所以字符从输入缓冲(流)中清除出去。”这样我就对这个函数有了很清楚的认识,所以就将它应用到了我的设计中了。 在设计过程中最大的困难就是对胜负判断条件的改写。依据课本中程序设计思想的提示,我需要把源代码中的if else格式的语句改写成for循环语句,以便于后面对任意大棋盘的n子连珠程序的扩展。 起初我只是单单从for循环的简单语句中找答案,但是一直没有结果,我也觉得不应该那么简单,但是却找不到突破口。于是我向另一位同学请教,在我们俩的共同努力下,我们觉得应该把for循环语句与if条件语句结合使用,于是,我便得出了我现在的判断方法。下面举例详细说明:例如从左斜上方向判断 课本中的源代码是else if (board20= O & board11= O & board02= O) cout O player wins the game =0)&(y-a=0)&(boardx-ay-a=c);a+)if(+count=3) return 1; 需要注意的是,源代码只是局限于3*3的棋盘进行三子游戏的从左斜上的获胜判断,不论棋盘变化或者子数变化都会引起代码的非常大的变动,这样显然不利于棋盘以及游戏的扩充。而对于修改后的判断方法,如果棋盘变化,只需修改相应的a的值即可,如果游戏子数变化,那么只要把if(+count=3)中的3改掉就可以了。比如说五子棋可以改为if(+count=5)。 当小错误解决了以后,在重复运行程序的过程中,我测试了各种数据及不同数据类型的输入,发现在玩家输入坐标的时候如果不是int型的,就会导致程序的无效死循环,为了解决这个问题我才又引入了while(!cin) /当输入的行坐标不是int型时char str20;cin.clear();/清空输入缓冲区cin.getline(str,20);/接收原输入数据coutx; /重新输入这一程序,从而解决了这个问题。设计的不足 我的设计已经完成了,但是其中还有很多不足之处,其中最明显的就是我没有完成课程设计要求中的选作项,起初,我是想按照课本程序设计思想中提到的设一个电脑玩家可以与人竞赛的程序的,但是我在思考之后还是决定不添加这个项目,原因是我并没有什么好的办法来完成这个程序段。这个问题也算这次设计过后的一个遗留问题吧,我会在以后的学习中努力掌握这个问题的解决方法的。总结通过这次设计,我还掌握了很多有用但以前不知道

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论