分享

24点C语言程序

 _私_房_菜_ 2012-02-10

一、简单介绍

给出4个数字,所给数字均为有理数,用加、减、乘、除(可加括号)把给出的数算成24.每个数必须用一次且只能用一次,先算出结果者获胜。

二、深入讨论

24点游戏能极大限度地调动多种感官的协调活动,对于培养我们快捷的心算能力和反应能力很有帮助.因此我们课后要多加练习,练习方法可以从一副扑克牌中去掉大王小王,剩余52张进行游戏,需要说明的是,经计算机准确计算,一副牌(52张)中,任意抽取4张可有1820种不同组合,其中有458个牌组算不出24点,如1115

三、算24一般掌握以下方法
    1
、最常见的算法是3*84*62*12,所以最先考虑的应该是上述3种算法。一般情况已有其中的一个因子,而用其他3个数去另一个因子。
    2
、先乘后加。常见的有2*7+103*5+92*9+63*7+3
    3
、先乘后减。常见的有3*9-34*7-45*6-6。这种类型里较难的是减数是由两个数相加而得,例如:2579
    4
、消去法。有时候,3个数就可以算出24,多 出来一个数,用消去法,可将多余的数除去。如359103*5+9=24,多一个10,可将10-5=5,将10消去。用乘法的分配律消去,如 2588,(5-2*8=24,多一个8,可以将算式改为5*8-2*8,将多余的8消去。
    5
、会意法。如44444*4表示44,再加24,就是64。又如,27899+728,再乘于2,变成48,再减一个8等于38
    6
、上天法。先将数乘得很大,最后再除于一个数得24,如101044
    7
、入地法。先将数算成分数或小数,最后乘于一个数得24,如3377

8、化除为乘法。用一个数除于一个分数,相当于乘与一个数,最后得24。如3388

 

 

#include "stdafx.h"

#include "conio.h"

#include "stdlib.h"

#include "time.h"

#include "math.h"

#include "string.h"

#include "iostream.h"

/*

  从一副扑克牌中,任取4张。

  2-10 按其点数计算(为了表示方便10T表示)J,Q,K,A 统一按 1 计算

  要求通过加减乘除四则运算得到数字 24

  本程序可以随机抽取纸牌,并用试探法求解。

*/

int s[21][4]={-1};

int sum=0;

void GivePuzzle(char* buf)

{

       char card[] = {'A','2','3','4','5','6','7','8','9','T','J','Q','K'};

       for(int i=0; i<4; i++){

              buf[i] = card[rand() % 13];

       }

}

 

void SetPuzzle(char *buf)

{

       scanf("%c %c %c %c",&buf[0],&buf[1],&buf[2],&buf[3]);

}

 

 

void shuffle(char * buf)

{

       for(int i=0; i<5; i++){

              int k = rand() % 4;

              char t = buf[k];

              buf[k] = buf[0];

              buf[0] = t;

       }

}

 

 

int GetCardValue(int c)                          

{

       if(c=='T')  return 10;

       if(c>='0' && c<='9') return c - '0';

       return 1;

}

 

 

char GetOper(int n)

{

       switch(n)

       {

       case 0:

              return '+';

       case 1:

              return '-';

       case 2:

              return '*';

       case 3:

              return '/';

       }

 

       return ' ';

}

 

double MyCalcu(double op1, double op2, int oper)

{

       switch(oper)

       {

       case 0:

              return op1 + op2;

       case 1:

              return op1 - op2;

       case 2:

              return op1 * op2;

       case 3:

              if(fabs(op2)>0.0001)

                     return op1 / op2;

              else

                     return 100000;

       }

 

       return 0;

}

 

 

void MakeAnswer(char* answer, int type, char* question, int* oper)

{

       char p[4][3];

       for(int i=0; i<4; i++)

       {

              if( question[i] == 'T' )

                     strcpy(p[i], "10");

              else

                     sprintf(p[i], "%c", question[i]);

       }

      

       switch(type)

       {

       case 0:

              sprintf(answer, "%s %c (%s %c (%s %c %s))",

                     p[0], GetOper(oper[0]), p[1], GetOper(oper[1]), p[2], GetOper(oper[2]), p[3]);

              break;

       case 1:

              sprintf(answer, "%s %c ((%s %c %s) %c %s)",

                     p[0], GetOper(oper[0]), p[1], GetOper(oper[1]), p[2], GetOper(oper[2]), p[3]);

              break;

       case 2:

              sprintf(answer, "(%s %c %s) %c (%s %c %s)",

                     p[0], GetOper(oper[0]), p[1], GetOper(oper[1]), p[2], GetOper(oper[2]), p[3]);

              break;

       case 3:

              sprintf(answer, "((%s %c %s) %c %s) %c %s",

                     p[0], GetOper(oper[0]), p[1], GetOper(oper[1]), p[2], GetOper(oper[2]), p[3]);

              break;

       case 4:

              sprintf(answer, "(%s %c (%s %c %s)) %c %s",

                     p[0], GetOper(oper[0]), p[1], GetOper(oper[1]), p[2], GetOper(oper[2]), p[3]);

              break;

       }

}

 

 

bool TestResolve(char* question, int* oper, char* answer)

{

       // 等待考生完成

       int type[5]={0,1,2,3,4};//计算类型

       double p[4];            

       double sum=0;

      

       for(int i=0; i<4; i++)  //循环取得点数

       {

        p[i]=GetCardValue(int(question[i])); 

       }

 

       for(i=0;i<5;i++)

       {

              MakeAnswer(answer,type[i],question,oper);  //获取可能的答案

              //printf("Doing%s\n", answer);

              switch(type[i])

              {

                     case 0:

                            sum=MyCalcu(p[0],MyCalcu( p[1],MyCalcu(p[2], p[3], oper[2]),oper[1]),oper[0]);  //A*(B*(c*D))

                            break;

                     case 1:

                            sum=MyCalcu(p[0],MyCalcu(MyCalcu(p[1], p[2], oper[1]),p[3],oper[2]),oper[0]);   //A*((B*C)*D)

                            break;

                     case 2:

                            sum=MyCalcu(MyCalcu(p[0], p[1], oper[0]),MyCalcu(p[2], p[3], oper[2]),oper[1]); // (A*B)*(C*D)

                            break;

                     case 3:

                            sum=MyCalcu(MyCalcu(MyCalcu(p[0], p[1], oper[0]),p[2],oper[1]),p[3],oper[2]); //((A*B)*C)*D

                            break;

                     case 4:

                            sum=MyCalcu(MyCalcu(p[0],MyCalcu(p[1], p[2], oper[1]),oper[0]),p[3],oper[2]); //(A*(B*C))*D

                            break;

              }

              if(sum==24) return true;   

       }

       return false;

}

 

bool permNum(int* oper, int i,int N,char*question,char*answer)   //递归实现重新排列数字、运算符

{

       int j, k;

       char tmp;

       if(i < N)

       {

              for(j = i; j < N; j++)

              {

                     tmp = question[j];

                     for(k = j; k > i; k--)

                            question[k] = question[k-1];

                     question[i] = tmp;

              if(    permNum(oper, i+1,N,question,answer)) return true;

                     for(k = i; k < j; k++)

                            question[k] = question[k+1];

                     question[j] = tmp;

              }

       }

       else

       {

                     //int type;

                     if( TestResolve(question, oper, answer) ) 

                     {

                            //getch();

                            return true;

                     }

       }

       return false;

}

 

bool perm(int* num, int i,int N,char*question,char*answer)   //递归实现重新排列数字、运算符

{

       int j, k, tmp;

       if(i < N)

       {

              for(j = i; j < N; j++)

              {

                     tmp = num[j];

                     for(k = j; k > i; k--)

                            num[k] = num[k-1];

                     num[i] = tmp;

                     if(perm(num, i+1,N,question,answer)) return true;

                     for(k = i; k < j; k++)

                            num[k] = num[k+1];

                     num[j] = tmp;

              }

       }

       else

       {

              if     (permNum(num,0,4,question,answer))   return true;

       }

       return false;

}

 

int ifcan(int str[4])

{

       for(int i=0;i<sum;i++)

       {

              if(s[i][0]==str[0]&&s[i][1]==str[1]&&s[i][2]==str[2]) {

                    

                     return 1;

              }

       }    

       s[i-1][0]=str[0];

       s[i-1][1]=str[1];

       s[i-1][2]=str[2];

       sum++;

       return 0;

}

 

bool Chooseoper(int *oper,char*question,char*answer)   //递归从四个运算符获取三个运算符

{

      

       int n=3,m=12,i,j;

       int oper1[12];

      

       for (i=0;i<n;i++)

       {

              oper1[i]=i;

       }

      

       for (i=0;i<n;i++)

       {

              oper[i]=oper1[i]/3;

       }

      

       if (!ifcan(oper))

       {

              if(perm(oper,0,n,question,answer)) return true;

       }

      

       j=n-1;

       while (1)

       {

              if (oper1[n-1]==m-1) 

                     j--;

              else j=n-1;

              oper1[j]++;

              for (i=j+1;i<n;i++)

                     oper1[i]=oper1[i-1]+1;

             

              for (i=0;i<n;i++)

              {

                     oper[i]=oper1[i]/3;

              }

              if (!ifcan(oper))

              {

                     if(perm(oper,0,n,question,answer)) return true;

              }

             

              if (oper1[0]>=m-n)

                     break;

       }    

       return false;

}

bool Try(int *oper,char*question,char* answer)

{

       if(Chooseoper(oper,question,answer)) return true;

       return false;

}

 

int main(int argc, char* argv[])

{

       // 初始化随机种子

       srand( (unsigned)time( NULL ) );

       char buf1[4];   // 题目

       char buf2[30];  // 解答

      

       printf("***************************\n");

       printf("计算24\n");

       printf("A J Q K 均按1计算,其它按牌点计算,T 代表 10\n");

       printf("目标是:通过四则运算组合出结果:24\n");

       printf("Mode 1 of Give Puzzle: Rand to give puzzle\n");

       printf("Else Type of Give Puzzle:Give by Youself \n");

       printf("***************************\n\n");

       int mode=1;   //默认为1

       printf("Mode:");

       scanf("%d",&mode);

       getchar();

       printf("***************************\n");

       for(;;)

       {

             

              if (mode==1)

              {

                     GivePuzzle(buf1);  // 出题模式1

              }

              else

              {

                     printf("Num:");

                     SetPuzzle(buf1);  //出题模式2

              }

                     getchar();

              printf("题目:");

              for(int j=0; j<4; j++){

                     if( buf1[j] == 'T' )

                            printf("10 ");

                     else

                            printf("%c ", buf1[j]);

              }

 

              printf("\n按任意键参考答案...\n");

             getch();

 

              int type[4];

              if( Try(type, buf1,buf2) )   //1全局搜索解法,精确解

                     printf("参考:%s\n", buf2);

              else

                     printf("无解...\n");

 

              for (int i=0;i<sum;i++)

              {

                     for(int j=0;j<3;j++)

                     s[i][j]=-1;

              }

              sum=0;

 

              printf("按任意键出下一题目,x 键退出...\n");

              if( getch() == 'x' ) break;

 

       }

 

       return 0;

}

 

 

 

 

Thanks

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多