总共4个数字a,b,c,d
那么需要三条算式 运算三次 判断结果是否为24
第一步:循环从 a b c d 取两个数做+ - * / 四次运算 剩下新的 a b c 三个数
第二步:循环从 a b c 取两个数做+ - * / 四次运算 剩下新的 a b 两个数
第三步:循环从 a b 取两个数做+ - * / 四次运算 判断结果是否为24
这样出来的解法会有重复的算式,也就是说同一条算式,却出来了不同的解法
举个例子
(a+b)/ (c*d)
我的算法会产生两种同样的解法:
a+b=x
c*d=y
x/y=z
c*d=x
a+b=y
x/y=z
节省我们实际现实看牌的时间
这样的解法很符合我们实际的拍牌解答的过程
如果输出一条含有括号的、复杂一点的算式 我们实际看起来也还得想一想先拍哪两张牌
#include<stdio.h> #include<math.h> #include<string.h> #include<windows.h> char sign[3]; //三条式子的三个符号 int n[3][2]; //三条式子的三对运算数 int cnt=0; //记录第几种解法 int option(int a,int b) // 计算除法 避免小数除以大数 { int c; if(a<b){ //大数排前面 方便后面做除法 c=a; a=b; b=c; } return (a/b) ; } int pd(int a,int b) //是否做除法的判断 { int c; if(a<b){ //大数排前面 方便后面做除法 c=a; a=b; b=c; } if((a*b!=0)&&(a%b==0)){ return 1; } else return 0; } int cal(int a,char x,int b) { if ( x=='+' ) return a+b; if ( x=='-' ) return abs(a-b); if ( x=='*' ) return a*b; if ( x=='/' ) return a/b; } void print() { int i,t; int temp; // int l,j; // for (l=0;l<3;l++){ // printf("第%d条 ",l+1) ; // for(j=0;j<3;j++){ // printf("%c ",sign[l][j]); // if (j==2) printf("\n"); // } // } // for (t=0;t<3;t++){ // printf("第%d条 %d %c %d\n",t+1,n[t][0],sign[t],n[t][1]); // } cnt++; printf("**********************解法%d**********************\n",cnt); for (t=0;t<3;t++){ if(sign[t]=='-'||sign[t]=='/'){ if(n[t][0]<n[t][1]){ int a; a=n[t][0]; n[t][0]=n[t][1]; n[t][1]=a; } } temp=cal(n[t][0],sign[t],n[t][1]); printf("%d%c%d=%d\n",n[t][0],sign[t],n[t][1],temp); } } void step3(int num3[4]) { int i; int temp3[4]; int *u=temp3; int count; for (i=1;i<=4;i++){ // i=3; //******调试******* memcpy(temp3,num3,sizeof(int)*2); //还原为原来的数组 switch (i) //加减乘除四次操作 记录第二条式子 { n[2][0]=*(u+0); n[2][1]=*(u+1); case 1: sign[2]='+'; count=*(u+0) + *(u+1); break; case 2: sign[2]='-'; count=abs(*(u+0) - *(u+1)); break; case 3: sign[2]='*'; count=*(u+0) * *(u+1); break; case 4: if(pd(*(u+0) , *(u+1))){ sign[2]='/'; count=option(*(u+0) , *(u+1)); } break; } if(count==24) { print(); count=0; } } } void step2(int a,int b,int num2[4]) { int i,cf=1; int temp2[4]; int *u=temp2; for (i=1;i<=4;i++){ cf=1; memcpy(temp2,num2,sizeof(int)*3); //还原为原来的数组 switch (i) //加减乘除四次操作 记录第二条式子 { case 1: sign[1]='+'; *(u+a)=*(u+a) + *(u+b); break; case 2: sign[1]='-'; *(u+a)=abs(*(u+a) - *(u+b)); break; case 3: sign[1]='*'; *(u+a)=*(u+a) * *(u+b); break; case 4: if(cf=pd(*(u+a) , *(u+b))){ //记录是否做除法 此步没有做运算 那么不用继续进行下去了 sign[1]='/'; *(u+a)=option(*(u+a),*(u+b)); } break; } if(cf){ int *q; for(q=u+b;q<u+2;q++){ //把后面的数往前移一位 还剩2个数 *q=*(q+1); } n[2][0]=temp2[0]; n[2][1]=temp2[1]; // printf("算第 2 遍后的牌面:%d %d\n",temp2[0],temp2[1]) ; step3(temp2) ; // if (i==4) printf("\n") ; } } } void step1(int a,int b,int num1[4]) //num1为接入数组,temp[]为输出数组 { int i,cf; int temp1[4]; int *u=temp1; for (i=1;i<=4;i++){ cf=1; memcpy(temp1,num1,sizeof(int)*4); //恢复原来的数组进行处理 switch (i) //加减乘除四次操作 记录第一条式子 { case 1: sign[0]='+'; *(u+a)=*(u+a) + *(u+b); break; case 2: sign[0]='-'; *(u+a)=abs(*(u+a) - *(u+b)); break; case 3: sign[0]='*'; *(u+a)=*(u+a) * *(u+b); break; case 4: if(cf=pd(*(u+a) , *(u+b))){ //记录是否做除法 此步没有做运算 那么不用继续进行下去了 sign[0]='/'; *(u+a)=option(*(u+a),*(u+b)); } break; } if (cf){ int *q; for(q=u+b;q<u+3;q++){ //从第b个把后面的数往前移一位 还剩3个数 *q=*(q+1); } int l,j; for(l=0;l<3;l++){ for(j=l+1;j<3;j++){ n[1][0]=temp1[l]; n[1][1]=temp1[j]; // printf("算第 1 遍后的牌面:%d %d %d\n",temp1[0],temp1[1],temp1[2]) ; step2(l,j,temp1) ; } } } } } int main(void){ int num[4]; void step1(int,int,int temp1[]); void step2(int,int,int temp2[]); void step3(int temp3[]); void print(); int cal(int ,char,int ); int pd(int,int); printf("****************************\n") ; printf("* *\n") ; printf("* 这里是24点游戏外挂 *\n") ; printf("* *\n") ; printf("****************************\n") ; loop: printf("请输入四个整数 (退出游戏:输入0 再按回车)\n"); cnt =0; int i; for (i=0;i<4;i++){ //读入四个整数 scanf("%d",&num[i]); if(num[i]==0) goto out; } int l,j; for(l=0;l<4;l++){ for(j=l+1;j<4;j++){ n[0][0]=num[l]; n[0][1]=num[j]; //printf("开始的牌面:%d %d %d %d\n",num[0],num[1],num[2],num[3]) ; step1(l,j,num); } } if(cnt==0) printf("淦!算我半天,这组数没解哇\n") ; printf("\n"); goto loop; out: //程序结束出口 return 0; }
- 海报