代码
/*
软工1604赵昱青
*/
#include<iostream>
#include<time.h>
#include<stdlib.h>
using namespace std;
int division(int p,int q)
//除法运算
{
if(p%q==0)
return p/q;
else
return 111111;
}
int fun(int i,int j,int c)//c(局部变量)选择运算符,i,j为运算数字
{
int s;
switch(c)
{
case 1: s=i+j;break;
case 2: s=i-j;break;
case 3: s=i*j;break;
case 4: s= division(i,j);break;
}
return s;
}
void output(int c)//c(局部变量)选择输出运算符
{
if(c==1)
printf("+");
else if(c==2)
printf("-");
else if(c==3)
printf("*");
else
printf("/");
}
int main()
{
int number[4];//一个数组用来存放4个 1~13之间的数字
int i,j,m,n;
int a,b,c;//符号 1:+ 2:- 3:* 其余:/ (详细可参考output函数)
int d1,d2,d3;//每步的结果
srand(time(NULL));//这里随机生成四个数字(相当于扑克牌)
for(int w=0;w<4;w++)
{
number[w]=rand()%13+1;//通过rand()方法来保证生成的随机数在1~13之间
}
for(int w=0;w<4;w++)
{
printf("%d ",number[w]);
}
printf("\n");
for(i=0;i<4;i++)
for(j=0;j<4;j++)
if(j!=i)
for(m=0;m<4;m++)
if(m!=i&&m!=j)
for(n=0;n<4;n++)
if(n!=i&&n!=j&&n!=m)//四个数字的位置不可重复且多重可能置换位置运算
for(a=1;a<5;a++)
for(b=1;b<5;b++)
for(c=1;c<5;c++)//选择四个数字中间的三个运算符,皆有四种可能
{
//去除括号的相关可能性,转化为二元运算
d1=fun(number[i],number[j],a);
d2=fun(d1,number[m],b);
//用前两个数字的运算结果代替
d3=fun(d2,number[n],c);
//同理,两两运算,递归过程
if(d3==24)
{
cout << number[i];
output(a);
cout << number[j];
output(b);
cout << number[m];
output(c);
printf("%d=24\n",number[n]);
}
}
return 0;
}
- 运行截图
不满足二十四点规则:
满足二十四点规则:
(存在错误输出
设计思路
在二十四点中最难得地方应该是对括号的处理,括号位置不同运算结果也不同。所以该方法没有使用多元运算的情况即全部转化为二元运算,避免了相关括号的运算。首先先生成四个数,从四个随机数中抽取2个数进行相关运算,将运算结果和第三个数再进行相关运算,同理不断进项递归。递归调用之前与之后,现场状态应该保持一致。在上述算法中,需要确保当前递归调用获得下一个正确的排列。 括号 () 的作用只是改变运算符的优先级,也就是运算符的计算顺序。所以在以上算法中,无需考虑括号。括号只是在输出时需加以考虑。
这次的程序还是有一些漏洞,在网上查阅资料了解到了递归的相关算法,但是对括号相关还是掌握不足,算法存在一些漏洞:有时满足二十四点规则后,又是输出会存在多余项,将在后续继续学习了解并改正。