(精品)24点游戏的开发和实现(2013年优秀毕业设计)_第1页
(精品)24点游戏的开发和实现(2013年优秀毕业设计)_第2页
(精品)24点游戏的开发和实现(2013年优秀毕业设计)_第3页
(精品)24点游戏的开发和实现(2013年优秀毕业设计)_第4页
(精品)24点游戏的开发和实现(2013年优秀毕业设计)_第5页
已阅读5页,还剩26页未读 继续免费阅读

下载本文档

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

文档简介

24点游戏的开发和实现摘 要:近年来,随着经济的日益发展,人们的生活水平不断提高,生活质量也在渐渐的改善。适当的娱乐游戏对人们的业余生活是不可必缺的。说到娱乐游戏,人们可能会想到网络上许许多多让人迷恋的网络游戏,比如说,传奇,奇迹,cs等等。是的,的确这些游戏给人们的业余生活添加了很多乐趣。借鉴网上的边锋游戏,我用vc+开发设计了24点游戏的实现算法,并在windows图形环境下设计出一个人机交互的游戏系统(类似于纸牌游戏)。关键词:穷举法 栈 递归函数The development and realization of 24 pionts gameAbstract:Recently,with the development of economic ,the peoples life becomes better and better,life condition also is improving more and more.Proper recreation is indispensable in the peoples pasttime life.Mentioned to the game,people may associate many fascinated online games,such as Legend,MU,CS and so on.Certainly,these games enrich peoples life with more and more joys.Using the wing game for reference ,I developed and designed the realization arithmetic of 24 points game.Next I designed a human-computer alternant game system (similar to card game ).Keyword:enumerating method stack recursive function1 24点游戏算法实现1.1 24点游戏简介要开发一个游戏不是那么容易的,哪怕是简单的算术游戏。要是没有一定的专业知识,没有一定的思维能力是不行的。24点游戏是一个传统的算术游戏,其游戏之精髓就是考验人脑的反应能力。所谓24点游戏,就是通过加,减,乘,除4则运算,将给定的4个整数算出24。当然,传统的纸牌游戏其数字是有限定范围的,一般是从1到13。经统计,当算的目标数把24改为2的时候,独立解数更多,就是解的形式趣于集中化,大多数最后一步用减法(如:2*8-3*5)。游戏时会感到单调。由于24的因数多,解的形式就丰富,能充分发掘游戏者数学发散思维能力。要做好一个简单的24点游戏要具备很多知识。其中最主要的思想就是,24点的表达式要怎样行成,这是此游戏的关键。而要做一个完美的24点纸牌游戏,则需要的知识将会更多。现今,网络上的纸牌游戏数不甚数,比较出名的有联众游戏,边锋游戏,qq游戏。当然,他们的开发队伍庞大之极不是我们个人可以比及的。因此要一个人做好一个比较完美的游戏,是需要一定的游戏天分。以下我就开发24点游戏的几个关键算法和分析做详细的剖析。1.2 24点游戏的算法1.2.1 24点算法(1)24点游戏的算法,其中最主要的思想就是穷举法。所谓穷举法就是列出4个数字加减乘除的各种可能性,包括括号的算法。我们可以将表达式分成以下几种:首先我们将4个数设为a,b,c,d,,其中算术符号有+,*,/,(,)。其中有效的表达式有a*(b-c/b),a*b-c*d,等等。列出所有有效的表达式。其中我们用枚举类型将符号定义成数字常量,比如用1表示+,2表示-等。如下是我对穷举法的一种编程语言。在编程的头部要对变量做下定义。其中a,b,c,d的范围是1到13。因为传统的24点游戏是纸牌游戏,而纸牌游戏的数字就是从1到13,其中a是1,K是13,Q是12,J是11,其他的就是牌面的数字。这就需要在定义变量的时候要有限制。在vc+中的MFC编程中,在定义控件的变量范围可以直接填写变量的最大和最小,在此编程中的最大是13,最小是1。这就给编程写语句带来了方便(因为其自动会生成语句)。下面我介绍下穷举法的主要实现,我们知道要实现24点的算法,就是通过4个数字,4个运算符号和2对括号(最多为2对),通过各种组合判断其结果是否为24。我们用a,b,c,d代替4个数字。考虑每种可能,总的算法就有7种可能。分别为:1,没括号的(形如a*b*c*d);2有括号的(形如(a * b) * c * d);3有括号的(形如(a * b * c) * d);4有括号的(形如a * (b * c) * d);5有括号的(形如(a * b) * (c * d));6有括号的(形如(a * b) * c) * d);7有括号的(形如(a * (b * c) * d)。接下来就是对每一种进行分析判断。我们拿2种情况做为例子,一种是没括号的,一种有括号的。先拿没括号的分析。我们知道没括号的式子包括其运算符和数字总共为7个(3个运算符,4个数字),于是我们定义一个数组,用于存放运算符和数字。运算符我们可以用枚举变量来定义,首先我们通过循环语句形成一个表达式子(但这个表达式的运算循序是乱的)。表达式子有很多种情况,利用循环语句我们可以一一将其写出,例如(a+b+c+d,a+b+c-d,a+b+c*d,a+b+c/d.等等)生成表达式子的后,接着就是判别运算顺序。在没有括号存在的情况下,我们令其先运算*,/。这个顺序的选择很轻松,我们可以定义一个bool类型的函数,我们对数组进行扫描,当扫描到/,*,其返回真值,就直接进行运算。依次照样进行扫描,当所有的/,*运算都进行为止,接着将/,*运算生成的结果合并栈(即将运算的结果放在一个变量中),接着就对其与下一个数字进行运算,直到所有的值都计算出来了,最后将最后运算结果放于一个变量中。我们将这个变量的值和24相减,假如其值是在1E-6之外,则说明此运算式能计算出24。接下来我们来做第2种有括号的算法,有括号的算法和没括号的算法就是在判断运算循序的时候有所差别。我们知道,括号就是用来改变运算顺序而添加的。判断括号的先后顺序,我们同样可以用一个bool类型的函数来判别,在生成表达式要判断其运算顺序时,我们首先扫描表达式存放的数组,假如扫描到左括号,则将先对左括号后面的式子进行运算,接着在是对/,*的优先级进行计算。在第2种(形如(a * b) * c * d)的情况下,我们先将a,b先进行运算,生成其值,并将结果存放与另一个变量中,接着将得到的初步结果和c和d进行运算,最后得到总的结果。将其总结果和24相减,若其值小于1E-6则说明此表达式能算出24。接下来几种有括号的算法和第2种情况类似,我们不做详细的说明。以上就是穷举法的基本实现算法。1.2.2 24点游戏算法(2)24点游戏的算法各种各样,各有千秋,现在让我们来讨论另一种24点游戏算法。此算法是在dos下实现的,但其思想明确,语句简短。其主要思想是简化算法,他将24点的算法排序分成如下几种,如下我们用a,b来代替变量。他将其分成如下6种情况,分别是a+b,a-b,b-a,a*b,a/b,b/a这6种情况,我们知道a+b和b+a是一样的,a*b和b*a是一样的。这样就可以省去2种算法。提高系统的使用效率,内存占用量小。还有其第2个思想是在判别24点正确与否的时候,采用了与24点相减绝对直在1E-6之外则判别其为正确,这就给运算带来了精确度,就如5 5 5 1等的数字也可以轻松算出,不会略过了。如下我们通过一段程序来看看其主程序段。bool Search(int n) if (n = 1) if ( fabs(number0 - NUMBER_TO_CAL) PRECISION ) cout expression0 endl; return true; else return false; for (int i = 0; i n; i+) for (int j = i + 1; j n; j+) double a, b; string expa, expb; a = numberi; b = numberj; numberj = numbern - 1; expa = expressioni; expb = expressionj; expressionj = expressionn - 1; expressioni = ( + expa + + + expb + ); numberi = a + b; if ( Search(n - 1) ) return true; expressioni = ( + expa + - + expb + ); numberi = a - b; if ( Search(n - 1) ) return true; expressioni = ( + expb + - + expa + ); numberi = b - a; if ( Search(n - 1) ) return true; expressioni = ( + expa + * + expb + ); numberi = a * b; if ( Search(n - 1) ) return true; if (b != 0) expressioni = ( + expa + / + expb + ); numberi = a / b; if ( Search(n - 1) ) return true; if (a != 0) expressioni = ( + expb + / + expa + ); numberi = b / a; if ( Search(n - 1) ) return true; numberi = a; numberj = b; expressioni = expa; expressionj = expb; return false; 我们简单分析下以上的程序,我们可以清楚看到,SEARCH函数一个递归函数,其返回的是bool类型的值,其中number0为计算结果,假若其值和24相减为1E-6,则说明算法正确。其主要思想如下:首先我们取前面的两个数a,b对其进行相加,接着将两个相加的数结果存放于numberi中,于是第2次循环的运算的时候,令其a= numberi;则a成了原先的a和b之和,接着再将其存放于numberi中,接着我们看到了程序中的递归函数SEARCH(n-1)。当调用递归函数的时候,我们可以看到其实现了所有数的相加,其中的n从原来的最大值4,经过递归达到2,最后生成4个数之和。接着就是递归函数的调用,假如numberi其中i=0时,如果numberi与24相减为零,则可以算出24点。如果,其返回直为否,则说明不能算出24点。则程序往下继续执行,接着是判断其他运算。同样的道理可以得出其返回值的正假,由此判断出24点的生成算法。注意假如我们只是简单的用计算结果和24相减为0则大错特错了,因为其中牵涉了到小数的问题。假如在运算中遇到了小数的式子不算,则此种判别是正确的,但24点游戏是允许中间过程存在有限小数,甚至是无限循环小数。因此要判断结果是否为24只能采用模糊的判别,即相减为1E-6之外,则说明其结果为24。我们可以举个例子如5 5 5 1 ,其中的运算就牵涉到了小数,其算法为(5-1/5)*5。只要我们的判别是如以上程序的,则此算式将轻易的解出。还有一点就是,简化式子的算法。形如a+b和b+a是一样的,可以省略其中的一种。 24点游戏的算法有多种多样,以上我只是简单对2种不同思想的算法做了简短的介绍,当然还有些算法也是大同小异,我们也不逐一列出了。介绍了24点算法后,接下来我们来探讨一下,一个有着纸牌图形界面的24点游戏将怎样完成。1.2.3 24点算法的多样性(即多解的算法和优化算法)的讨论我们拿递归算法来分析其算法的多样性。我们知道递归算法是通过调用一个递归函数,将n值依次减1到最小值为止。并且在此递归的过程中实现了,表达式的4则运算,然而在以上的递归函数中已经考虑到了各种算法的可能性。其主要思想就是对4个数字的运算顺序和运算符号通过递归逐一的算出各种表达式。先重加法算起,依次算到除法(被除数不为零)为止。显然,其中已经包括了24点的所有算法,假如要输出每种可能性进性判别其优化性,那就需要用到编译原理的知识。通过逆波兰式的判定,求出其最优化的算法。我们拿a+b+c+d为例子,我们知道在有括号的情况下,(a+b)+(c+d)以及(a+b+c)+d这3种情况中,很明显前一种是最简洁。那我们在程序中要如何设置其最简单的算法呢。这就需要对两种算法进行逆波兰式的判别,我们将前者写成逆波兰式,则为ab+c+d+,第2种写成逆波兰式为也为ab+c+d+。说明两者运算的结果是一样的。但是很明显,前者简洁。因此,对于逆波兰式相同,但实际程序中不同的程序,就可以判断其优化程度。假如我们将左右括号定义为枚举变量,接着扫描每个字符,假如字符串最短的则为最优化的算法。还有我们假定,在能用中间过程为全整数,而某种表达式中间过程则存在着小数结果,则认为后者算法是不优化的。但有些算式,通过前者是算不出来的,只能通过后者算出,则其也应该算是优化了的算法。因此判断优化与否的关键就是,判断其中间过程是否有小数结果生成,并讨论其用不存在小数中间结果的算法是否可行。如果,存在整数的算法,则要去掉其小数的算法。因为它肯定是没有优化。1.3 24点游戏输入表达式的判别算法讨论了24点游戏的各种算法思想后,接着要考虑的是游戏的关键技术,即是表达式的判别。表达式的判别是除了算法之后的首当其冲也解决的问题。何为表达式判别?所谓表达式的判别就是,你在对话框中输入数字和字符的时候,是不是牌面所显示的值,这是一个非常关键的重点。我们举个例子说明下,假设现在我们已经开始某一个24点纸牌游戏,然后按下开始键。接着游戏截面显示了,红桃A,黑桃5,红桃5和梅花5这4张牌,要求你算出24点。假设现在你要测试这个游戏的表达式判别怎么样。那我们可以轻松的试出其正确与否。我们可输入1*2*3*4这个算式子。如果系统未提示任何错误,反而弹出计算正确的提示。则说明此游戏没有做任何的表达式判别,至少没有对输入数字进行控制。这就是所谓的表达式判别。然而要做到表达式真正的符和要求,其需要对其采取一定的措施。表达式判别有简单有复杂,我们的目的是力争简洁但实用。要进行表达式的判别,我们必须要用编译原理。编译原理是对计算机语言进行文法分析,词法分析的一种学科。特别是对表达式运算顺序和表达式输入正确与否能轻易的做出。我们将在文本中输入的一段字符串,将其进性文法分析和语法判断。我们可以轻松的将其判断出来。对于表达式顺序的问题更是简单,现在我们介绍一种方法叫逆波兰式。逆波兰式的思想是这样的:比如我们现在输入一串运算符号和一些整形类型的变量,他能通过一定的算法顺序进性排列 。例如我们在程序中要得到a+b则逆波兰式为ab+,要得到(a+b)*c则逆波兰式为ab+c*,更复杂的a:=b*c+b*d其逆波兰式为abc*bd*+:=。我们可以看出,逆波兰式可以将有括号的表达式省略括号,那为什么其能省略括号呢,正就是逆波兰式的实现方法。我们拿上面最复杂的例子做分析,得出逆波兰式子的思想。其实,逆波兰的思想是利用了栈的功能。我们看,我们将第一个字符a推入栈顶,接着推入第2字符,接着第3,4一直将推如栈中。假如,中间遇到了运算符号,就如在c后面遇到了*号,则系统将离*号最近的两个变量进行乘运算,得到一个结果。将b,c栈合并用于存放结果。接着在往栈中推入b,d,我们看到在d后又出现了*号,着将离*最近的两个变量进行想乘,并且合并栈,将结果存放于栈中。依着以上的思想进行运算,就可以实现语句a:=b*c+b*d。因此我们在判断输入表达式是否错误的时候就可以利用此种思维方法。我们将每个输入的字符推入栈中,并且对其进行判别,假如遇到的字符是除了如(19,+,-,*,/,(,)等符号外的数据,则说明输入有误,此算法完成了语法错误的判别。接着是判断,输入的数字和系统给的直是否一样,这也非常的简单。我们对每次推入栈的数字和系统的数字进行比较,假如有不同的则报“数字和系统提供的不相同”的错误。在判断括号匹配的时候,我们可以定义一整形数组变量a和2个整形变量count1,count2另其初始值全为0,当遇到左括号字符是另其变量a0+,并且count1+;如过遇到第2个左括号则a1+,并且count1+,其中数组的序号值1有count1控制(即如count1=1则序号为1),同理第3个左括号,第4个左括号都是同样的语句。然而在推入栈的时候碰到的第一个右括号,我们令a0-,count2+,接着和上面的步骤类似。最后,判断括号匹配的时候只要求出数组中所有数字的绝对值之和,如果其值不为0则说明括号没匹配,否则就是匹配的。通过逆波兰式的原理,我们可以轻松完成24点游戏表达式的判别。1.4 纸牌游戏界面的算法1.4.1 获得纸牌界面的函数接下来是纸牌游戏的制作,要做纸牌游戏。首先必须要有纸牌的界面。界面需要通过截图来获得。将一副标准扑克牌的52张牌面截下来,将其加入到vc+的res文件夹中,也就是资源文件夹。并且将其中的52张纸牌牌面进行系统化的命名。比如,用a前缀代替红桃,b前缀代替黑桃,c前缀代替梅花,d前缀代替方块。这样52张牌就对应了52个图形文件。做好了牌面的截图后就是对其进行发牌。发牌算发也是一个直的考虑是关键。我们将其中的52个数设为数组行如:a52 ,这样每张牌就对应了数组中的一个变量。我们先将每个数和数组相连接起来。接着我们用一个随即函数令其随即的产生4个数,函数行如:b1=rand() b2=rand() b3=rand() b4=rand(),其函数的意思就是产生随即数。但是这里产生的随即数都是任意的,可能大于52。这样我们需要对产生的随即数进行处理。在这里我们使用整除求余功能,如:b1=rand()%52+1 这样每次输出随即数就不会大于52了,达到了预期的效果。此程序的关键就是随即搜索牌面的路径,通过牌面的搜索和刷新,形成一组新的数字,根据此4个数字生成24点。其中最主要的函数就是一个随即函数rand(),此函数是c+系统中自带的函数,存放于stblib.h头文件中。此函数在使用之前,必须有个诱导函数srand()。通过调用Rand()函数就可以生成随即数据,但随即函数生成的数字是凌乱无序的,它范围很大,因此必须对它加以限定范围,这时我们用到了一个方法,就是用整除求余的方法。假如将52张牌标记成0到51的数字,那么我们可以通过对随即函数求余的方法,找到每张牌。其函数形式为rand()%52+1;其中形成的0到51个数将代表一副扑克牌中的52张。牌面在程序中将怎样生成?首先我们要做的是截图,所谓截图就是从已有的纸牌游戏中截下相应的52张牌(不包括大,小王)。将其中的52张牌存放为52个图片文件。要注意在文件命名的时候是有讲究的,因为此后要搜索牌的路径。因此给其中的牌面文件命名时要有统一性,又要有区别性。统一性就是我们可以将4种不同花色的牌分别命名以a,b,c,d开头,区分性就是我们用每张牌面的数值来区分其不同行。比如,我们命名黑桃k为a13,桃花k为b13,梅花k为c13,方快k为d13。这样我们就将52张牌和52个有序的文件一一对应了。牌面做好了,接下来就是要怎样在游戏界面中形成牌面。在面向对象的程序编程中,vc+中的图形界面的设计可以在API中来完成。首先我们要指定牌面存放的位置,位置的研究是很重要的。位置包含了很多属性,包括一般的长,高等。其次就是要定义一个矩形空间,此函数的定义在c+中有着现存的函数。可以用以下函数。rectdate0.originrect.top =rectdate0.rect.top =50;rectdate0.originrect.bottom=rectdate0.rect.bottom =rectdate0.rect.top+height;rectdate0.originrect.left =rectdate0.rect.left =50;rectdate0.originrect.right=rectdate0.rect.right =rectdate0.rect.left+width;rectdate0.firstrect =rectdate0.originrect;4张纸牌对应于其中的4个如上的函数,其他三个同理可得。只是大小上有点差别,比如高度,左右位置等都应该有相应的变化。存放位置编好了之后,接着就是在怎样生成图片了。在API中生成图片我们用到了绘制图片的功能和刷新功能。1.4.2不发重复牌的算法我们在完成纸牌游戏界面的设计之后,接着要考虑的一个问题就是:因为你用到的是一副牌,如何实现每次发牌的时候不产生相同的牌面。这是游戏中的一个关键,也是程序成功与否的关键因素。其实,要完成此功能也极为简单。既然我们在做界面的时候已经给52张牌给了命名,则我们只要对52张牌的花色进行分类。就如上面所提到的,用52个有着相同点又有区别的图形文件来区分其花色和大小。接着我们定义一个a52,将52张牌按顺序依次存放于数组中。其中花色一样的牌为一样的顺序,例如红桃花色的牌存放在a0-a12中,黑桃的牌存放在a13-a25中,梅花花色为a26-a38中,方块为a39-a51中。这样做的目的是为了有利于判别其花色。将花色进行了分类后,我们可以对其进行选择判断了。比如我们要拿一张红桃10,则具备两个条件的数组值只有一个。首先我们找出大小为10的值,我们知道有4个,接着我们要找到红桃花色,这只要我们做简单的判断,即数组的下标(这里我们设它为i)0=i=12。通过以上的查找我们可以找到红心10。我们知道一张牌有两个要素组成,一个是大小,一个花色。大小我们可以对其很好的做控制,而花色则没有相映的程序代码。因此只能采用以上方法以区分。1.4.3重新发牌的函数重新开始游戏的算法简介。我们知道游戏中重新开始是肯定要用到的,你不可能让别人只算一次,这就失去了其实际意义,也得不到娱乐和益智的效果。因此,重新发牌也是其中很重要的算法。在API的编程中,我们使用了一个关键技术,那就是刷新函数。刷新函数可以令原有的界面撤消,然后在重新绘制界面。如下让我们看看此24游戏中,重新发牌的关键程序。void CWorkView:OnPaint() /重新绘制牌面的程序int i;CPaintDC dc(this); / device context for paintingfor(i=0;i4;i+)rectdatei.hBitmap=(HBITMAP)LoadImage(AfxGetInstanceHandle(),recGetObject(rectdatei.hBitmap, sizeof BITMAP, &bm1);SelectObject(hSrcDC1, rectdatei.hBitmap);:SetStretchBltMode(hDesDC1,COLORONCOLOR); :StretchBlt(hDesDC1, rectdatei.rect.left, rectdatei.rect.top, width, height, hSrcDC1, 0, 0, bm1.bmWidth, bm1.bmHeight,+SRCCOPY);通过以上的函数,我们就可以得到下一轮游戏的牌面。以上是完成一个简单24点游戏必要的程序设计,接着我介绍下游戏中其他的一些控件。比如时间控制,开始和结束控制等。1.5 其他一些控件的设置1.5.1 时钟的设置时钟是用来控制游戏速度,和提高的人的智力所必需的控件。也是为游戏增添乐趣,提供思索空间所必需的。时钟的设置在vc+钟也是比较简单的,其中用到的函数也非常简介,接着让我们来看看其简单的程序。void CWorkView:OnTimer(UINT nIDEvent) /定时器响应程序CString temp;UpdateData(true);temp=m_edit;timercount-;m_edit4=timercount;UpdateData(FALSE);if(timercountEnableWindow(TRUE);查看如上函数,我们看到的关键函数就只有一个,那就是KillTimer函数。我们从他的拼写可以看到,其意思是消除时间。其中还用到了控制时间秒数的变量timercount,在如上函数中其最大直为30,则说明游戏将在30秒内结束。另外在时间控制下,其他一些控件也要实行相应的变化。在如上程序中,id为IDC-BUTTON5的空件在时间结束的时候要消除灰化。1.5.2 游戏的开始和结束控制每个游戏都有其游戏的开始控制和结束控制,当然24点游戏也不例外。因此要控制游戏的开始结束也是游戏中必要的控件。我们来看下其程序:void CWorkView:OnButton5()if(istimer=false)SetTimer(1,1000,NULL);(CButton*)CWnd:GetDlgItem(IDC_BUTTON5)-EnableWindow(FALSE);(CButton*)CWnd:GetDlgItem(IDC_BUTTON3)-EnableWindow(FALSE);(CButton*)CWnd:GetDlgItem(IDC_BUTTON2)-EnableWindow(FALSE);(CButton*)CWnd:GetDlgItem(IDC_BUTTON4)-EnableWindow(FALSE);其中在控件中我们添加了控件BUTTOM5,用于控制游戏的开始。当按下开始按钮时,我们将控件BUTTTON3,2,4都灰化。这就实现了简单的游戏开始控制。 结束按钮和开始按钮大同小异,这里我们就不详细介绍了。1.6 游戏的实现其具体的函数1.6.1 游戏实现后的主要界面完成了以上4大节工作之后,一个简单的24点游戏程序就基本生成了。接着就是在程序上做简单的修改,查漏补缺。通过游戏的连接,编译并运行。运行没有出错,程序就运行如下。从界面中我们看到了其中的主要功能都具备了。有相应的表达式输入功能,查看结果功能,显示正确答案功能,重新发牌,牌面设置以及定时控制。在菜单中有文件和帮助两个主菜单。其中文件菜单中有开始和结束控制。如下分细节对系统实现进行分析,首先我们来看下按下设置牌面产生的效果。我们看到,在按下了设置牌面的时候,弹出一个牌面设置的窗口。在请输入牌面的输入框中默认了牌面数字全为1,当然我么可以将其改写,比如我们改为3 4 3 5 并按下确定,则弹出如下窗口。我们可以看到按照如上的要求我们实现了牌面的自定义功能。接着我们来看看表达式输时产生的一些错误信息提示,包括语法错误,括号匹配,数字匹配等。我在如下一一都显示出来。 其中的3个错误我们可以清楚的看到,当我们看到在第一个窗口中输入了与纸牌数字不正确的数字之后,提示了“请注意输入的数值是否正确”。在第二个窗口中输入了左括号后直接点击“单机查看结果”键时弹出“括号不匹配”的错误提示。在第三个窗口中输入“方法”俩汉字的时候,我们看到了“输入语法错误”的提示。以上我将所有的错误信息都做了很好的图文说明。以下是输入正确表达式,并得出24点算法后的界面显示。我们在牌面设置的时候输入5 5 5 1 4个数字的时候,显示正确结果的截面如下。 如上我们看到界面中弹出了“计算正确”的消息框,实现了24点游戏表达式的最后判别。1.6.2 24点算法的程序实现/计算24点的答案程序BOOL Calc24(int iNum1, int iNum2, int iNum3, int iNum4, CString& strResult) / /括号的几种情况/无括号/2 (a b) c d同a b (c d), 下省略/3 (a b c) d/4 a (b c)d/5 (a b) (c d)/6 (a b) c) d/7 (a (b c) dint iNumArr4;/定义一维数组 用于存放输入的数值iNumArr0 = iNum1;iNumArr1 = iNum2;NumArr2 = iNum3;iNumArr3 = iNum4;if (CalcArray1(iNumArr, strResult)/调用CalcArray1函数判断其是否能算出24 return TRUE;if (CalcArray2(iNumArr, strResult) /调用CalcArray2函数判断其是否能算出24 return TRUE;if (CalcArray3(iNumArr, strResult) 调用CalcArray3函数判断其是否能算出24return TRUE;if (CalcArray4iNumArr, strResult) 调用CalcArray4函数判断其是否能算出return TRUE;if (CalcArray6(iNumArr, strResult) 调用CalcArray6函数判断其是否能算出return TRUE;if (CalcArray7(iNumArr, strResult) 调用CalcArray7函数判断其是否能算出return TRUE;return FALSE;BOOL CalcArray1(int iNumInput, CString& strResult)/没有括号的一个函/数,类似的函数还有6个,这里不另外写上去了。/ a * b * c * d 7 numberint iNumMaths72;/其中包括数值变量和运算符号有7个字符 for(int i=0;i4;i+)/循环语句判断输入的4个数字 for(int j=0;j4;j+) if(j=i) continue; for(int k=0;k4;k+) if(k=i|k=j) continue; for(int l=0;l4;l+) if(l=i|l=j|l=k) continue; iNumMaths00=iNumInputi;/将数值存入数组中 iNumMaths20=iNumInputj; iNumMaths40=iNumInputk; iNumMaths60=iNumInputl;iNumMaths01=eNumber;/将此字符代表数值还是运算符号的值存入数组iNumMaths21=eNumber;iNumMaths41=eNumber;iNumMaths61=eNumber;for (int oneOP = eAdd; oneOP = eDiv; oneOP+)/通过循环语句实现运算顺序 for (int twoOP=eAdd; twoOP=eDiv; twoOP+)for (int threeOP=eAdd; threeOP=eDiv; threeOP+)iNumMaths10 = oneOP;/通过循环得到第一个字符的运算符号先/,*后+ ,-iNumMaths11 = eOperator;/表明第一个输入的字符为变量还是运算符号iNumMaths30 = twoOP;iNumMaths31 = eOperator;iNumMaths50 = threeOP;iNumMaths51 = eOperator;double dRes = CalcOneExpress(iNumMaths, 7);if(Equal24(dRes)CombineResult(iNumMaths, 7, strResult);/合并结果return TRUE;/end for (int oneOP return FALSE;1.6.3 24点算法表达式的判别程序int temp=0;/用于控制if语句的判断int total;/用于判断输入数字和牌面数字是否匹配rrorNum=3;/3种错误判断和一种正确结果的变量CString s;/用于在输入框中输入字符的变量UpdateData(true);s=m_edit;int length=s.GetLength();int dd;UpdateData(FALSE); int nLength=m_edit.GetLength();har * sz=new charnLength;sz=m_edit.GetBuffer(0);UpdateData(true);dd=eval_exp(sz);m_edit3=dd;if(errorNum=0)/ errorNum有4个值,分别用以判断出错信息和正确消息MessageBox(输入语法错误);else if(errorNum=1) MessageBox(输入括号不匹配)else if(errorNum=2)MessageBox(表达式不存在);else if(errorNum=3)/假如errorNum为3则判断其表达式的长度for(j=0;jlength-1;j+) int getatq=s.GetAt(j); int getath=s.GetAt(j+1);if(getatq=1)&(getath=0)s.SetAt(j,a);s.Delete(j+1,1);length=s.GetLength();if(getatq=1)&(getath=1)s.SetAt(j,b);s.Delete(j+1,1);length=s.GetLength();if(getatq=1)&(getath=2)s.SetAt(j,c);s.Delete(j+1,1);length=s.GetLength();if(getatq=1)&(getath=3)s.SetAt(j,d);s.Delete(j+1,1);length=s.GetLength();for(i=1;i14;i+)/循环语句判断输入值和牌面给定的牌是否匹配temp=0;start=0;while(temp!=(-1)temp=s.Find(di,start);start=temp+1;f(temp!=(-1)ai+;for(i=1;i14;i+)if(ci=m_iNum0)ai-;if(ci=m_iNum1)ai-;if(ci=m_iNum2)ai-;if(ci=m_iNum3)ai-;total=abs(a1)+abs(a2)+abs(a3)+abs(a4)+abs(a5)+abs(a6) +abs(a7)+abs(a8)+abs(a9)+abs(a10)+abs(a11)+abs(a12)+abs(a13); if(total!=0) /利用total变量实现了数字匹配问题,假如total为0则匹配正确 否则错误MessageBox(请注意输入数值是否正确);elseif(dd=24)MessageBox(计算正确);m_edit3=dd;UpdateData(FALSE);else MessageBox(计算错误,请重新输入);1.6.4 24点游戏纸牌发牌算法(不重复)void CWorkView:RandomSelect() /初始化牌面文件的路径,初始化牌面的数值,花色int tempdate4; double number4; int i,j;char realdate480;char temppath80;char pathname5280=resa1.bmp,resa2.bmp,resa3.bmp,resa4.bmp, resa5.bmp,resa6.bmp,resa7.bmp,resa8.bmp, resa9.bmp,resa10.bmp,resa11.bmp,resa12.bmp, resa13.bmp,resb1.bmp,resb2.bmp,resb3.bmp, resb4.bmp,resb5.bmp,resb6.bmp,resb7.bmp, resb8.bmp,resb9.bmp,resb10.bmp,resb11.bmp,resb12.bmp,resb13.bmp,resc1.bmp,resc2.bmp,resc3.bmp,resc4.bmp,resc5.bmp,resc6.bmp,resc7.bmp,resc8.bmp,resc9.bmp,resc10.bmp,resc11.bmp,resc12.bmp,resc13.bmp,resd1.bmp,resd2.bmp,resd3.bmp,resd4.bmp,resd5.bmp, resd6.bmp,resd7.bmp,resd8.bmp,resd9.bmp,resd10.bmp,resd11.bmp,resd12.bmp,resd13.bmp;/将52纸牌文件路径按顺序依次存放于数组中for(i=0;i4;i+)tempdatei =(int)(double)rand()/RAND_MAX*52.

温馨提示

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

评论

0/150

提交评论