C++实现24点游戏

来源:互联网 发布:mac airplay显示关闭 编辑:程序博客网 时间:2024/05/17 23:53

1.   算法思路

(1)首先穷举的可行性问题。我把表达式如下分成三类
1
、 无括号的简单表达式。
2、 有一个括号的简单表达式。
3、 有两个括号的较复4,杂表达式。
穷举的开始我对给出的四个数进行排列,其可能的种数为4*3*2*1=24。我利用一个嵌套函数实现四个数的排列

     (2)那么作为栈的著名应用,表达式的计算可以有两种方法。

第一种方法: 
  首先建立两个栈,操作数栈OVS和运算符栈OPS。其中,操作数栈用来记忆表达式中的操作数,其栈顶指针为topv,初始时为空,即topv=0;运算符栈用来记忆表达式中的运算符,其栈顶指针为topp,初始时,栈中只有一个表达式结束符,即topp=1,且OPS1=‘。此处的即表达式结束符。
  然后自左至右的扫描待处理的表达式,并假设当前扫描到的符号为W,根据不同的符号W做如下不同的处理:
1W为操作数
2则将W压入操作数栈OVS 
3且继续扫描下一个字符
4W为运算符
5则根据运算符的性质做相应的处理:
(1)、若运算符为左括号或者运算符的优先级大于运算符栈栈顶的运算符(OPS(top)),则将运算符W压入运算符栈OPS,并继续扫描下一个字符。
(2)、若运算符W为表达式结束符且运算符栈栈顶的运算符也为表达式结束符(即OPS(topp)=’;’),则处理过程结束,此时,操作数栈栈顶元素(即OVStopv))即为表达式的值。
(3)、若运算符W为右括号且运算符栈栈顶的运算符为左括号(即OPStopp=’(‘),则将左括号从运算符栈谈出,且继续扫描下一个符号。
(4)、若运算符的右不大于运算符栈栈顶的运算符(即OPS(topp)),则从操作数栈OVS中弹出两个操作数,设先后弹出的操作数为ab,再从运算符栈OPS中弹出一个运算符,设为+,然后作运算a+b,并将运算结果压入操作数栈OVS。本次的运算符下次将重新考虑。
第二种方法—— 
  首先对表达式进行线性化,然后将线性表达式转换成机器指令序列以便进行求值。
  那么什么是表达式的线性化呢?人们所习惯的表达式的表达方法称为中缀表示。中缀表示的特点是运算符位于运算对象的中间。但这种表示方式,有时必须借助括号才能将运算顺序表达清楚,而且处理也比较复杂。
   1929年,波兰逻辑学家Lukasiewicz提出一种不用括号的逻辑符号体系,后来人们称之为波兰表示法(Polish notation)。波兰表达式的特点是运算符位于运算对象的后面,因此称为后缀表示。在对波兰表达式进行运算,严格按照自左至右的顺序进行。下面给出一些表达式及其相应的波兰表达式。
表达式波兰表达式
A-B AB- 
A-B*C+D AB-C*D+ 
A*B+C/D-E*F ABCD/+*EF*- 
B+C/A-D BC+AD-/ 

  OK,所谓表达式的线性化是指将中缀表达的表达式转化为波兰表达式。对于每一个表达式,利用栈可以把表达式变换成波兰表达式,也可以利用栈来计算波兰表达式的值

下面是代码

//西安科技大学-计算机科学与技术学院#include <iostream>  #include <string>  #include <cmath>     using namespace std;     const  double  PRECISION = 1E-6;  const  int  COUNT_OF_NUMBER  = 4;  const  int  NUMBER_TO_BE_CAL = 24;  double  number[COUNT_OF_NUMBER];  string  expression[COUNT_OF_NUMBER];  bool Judgement = false;                    //判断是否有解。int count = 0;      void  Search(int   n)  {     if (n   ==   1)   {       if ( fabs(number[0] - NUMBER_TO_BE_CAL) <= PRECISION   )  //对于除法,要小心小数的精确位数 {       cout << expression[0] << "\t\t";      Judgement = true;     count ++;     if((count % 3)==0)     cout<<endl;     }     else    { }      }        for(int i=0;  i < n; i++)    {      for (int j = i + 1; j < n; j++)    {         double   a,   b;         string   expa,   expb;     a   =   number[i];         b   =   number[j];         number[j]  =  number[n - 1];   //递归之后,n比以前小一位,所以可以不停向前赋值    expa   =   expression[i];         expb   =   expression[j];         expression[j]  =  expression[n - 1];   //递归之后,n比以前小一位,所以可以不停向前赋值   expression[i]   =   '('   +   expa   +   '+'   +   expb   +   ')';   //加法不需要分顺序       number[i]   =   a   +   b;         Search(n-1);       expression[i]   =   '('   +   expa   +   '-'   +   expb   +   ')';   //减法应该分顺序,减数以及被减数       number[i]   =   a   -   b;         Search(n-1);    expression[i]   =   '('   +   expb   +   '-'   +   expa   +   ')';   //减法应该分顺序,减数以及被减数       number[i]   =   b   -   a;         Search(n-1);    expression[i]   =   '('   +   expa   +   '*'   +   expb   +   ')';   //乘法不需要分顺序       number[i]   =   a   *   b;         Search(n-1);    if (b != 0)      {           expression[i]   =   '('   +   expa   +   '/'   +   expb   +   ')';   //除法应该分顺序,除数以及被除数         number[i] = a / b;           Search(n-1);        }           if (a != 0)      {           expression[i]   =   '('   +   expb   +   '/'   +   expa   +   ')';   //除法应该分顺序,除数以及被除数         number[i]   =   b  /  a;           Search(n-1);        }              number[i]   =   a;                  //这4句语句是为了防止如果上面几种可能都失败了的话,         number[j]   =   b;                  //就把原来的赋值撤消回去,以无干扰的正确的进入到下一次         expression[i]   =   expa;           //for循环队列中。         expression[j]   =   expb;           //      }      }}     int  main()  {    cout<<"请依次输入4个数字:\n";  for (int i = 0; i < COUNT_OF_NUMBER; i++)   {      char   buffer[20];       cout<<"第"<<i+1<<"个卡片:";    cin   >>   number[i];                      itoa(number[i],   buffer,   10);   //itoa()函数的作用是把第一个参数(数值)传送到第二个参数(字符串)中去,第三个               //参数(int型)是该数值在字符串里以什么进制存放。    expression[i]   =   buffer;    }  cout<<endl;  Search(COUNT_OF_NUMBER) ;  if(Judgement==true)  {      cout   <<   "\n成功"   <<   endl;    cout<<"所以可以计算的次数总和 = "<<count<<endl;  }    else  {      cout   <<   "失败"   <<   endl;    }         system("pause");  return 0;}

2 0
原创粉丝点击