zoukankan      html  css  js  c++  java
  • 计算24(随机法)

    程序描述:

    许多人小的时候可能都玩过计算24的游戏。从一副扑克牌中任意取出4张,根据点数用加、减、乘、除计算出24。花色不计,点数:AJQK都算1,其它牌算本身的牌点。

    用计算机搜索算法的解法有很多。一般是用穷举法罗列每一种情况。本程序打算用一种不同寻常的算法:随机地交换牌的位置,随机地产生运算符,看看是符合要求,大量重复这个过程,看看能否碰上运气。实验表明,当试验次数很大的时候,“运气”的概率是很高的。

    请考生参看【原型】的效果,理解程序的目的。先是随机地抽取4张牌,然后用随机试探的方法求解。只要找到一个解就可以了。

    需要考虑计算结果为分数的情况:( 3 + (3 / 7) ) * 7

     

    /*
    *作者:杜红光
    *DATA:2012/3/27
    *描述:利用随机产生扑克牌,随机组合选出的牌,随机产生三个运算符,随机产
    * 生两个括号,来解决24点问题
    */
    #include<iostream>
    #include<ctime>
    #include<cstdlib>
    #include<conio.h>
    using namespace std;
    #define CARDNUMBER 4
    #define RANDTIMES 10000 //随机计算次数
    char card[13]={'A','2','3','4','5','6','7','8','9',10,'J','Q','K'};
    char operators[4]={'+','-','*','/'};
    void cardRand(int *a)
    {
    for(int i=0;i<CARDNUMBER;i++)
    a[i]=rand()%13;
    }

    void printCard(int *a)
    {
    printf("题目:");
    int i;
    for(i=0;i<CARDNUMBER-1;i++)
    {
    if(a[i]==9 )
    printf("10 ");
    else
    printf("%c ",card[a[i]]);
    }
    if(a[i]==9 )
    printf("10\n");
    else
    printf("%c\n",card[a[i]]);
    }

    void changeA(int *a,double *theA)
    {
    for(int i=0;i<CARDNUMBER;++i)
    (a[i]>0 && a[i]<10)?theA[i]=a[i]+1.0:theA[i]=1.0;
    }

    void randNumList(int *theRandA)
    {
    bool flag[CARDNUMBER];
    memset(flag,0,sizeof(flag));
    for(int i=0;i<CARDNUMBER;++i)
    {
    while(1)
    {
    int n=rand()%4;
    if(!flag[n])
    {
    flag[n]=true;
    theRandA[i]=n;
    break;
    }
    }
    }
    //for(int i=0;i<4;i++) cout<<theRandA[i]<<endl;
    //cout<<endl;
    }

    void randOperator(int *theRandOperator)
    {
    for(int i=0;i<CARDNUMBER-1;++i)
    {
    int n=rand()%4;
    theRandOperator[i]=n;
    //cout<<operators[n]<<" ";
    }
    //cout<<" RandOpe"<<endl;
    }

    double computeIt(double t1,double t2,char ch)
    {
    switch(ch)
    {
    case '+':return t1+t2;
    case '-': return t1-t2;
    case '*': return t1*t2;
    case '/':
    if(t2==0) return 10000;
    else return t1/t2;
    }
    return 10000;
    }

    template<class T>
    void removeZero(T *t,int len)
    {
    int i;
    for(i=0;i<len;i++)
    if(t[i]==0) break;
    for(int j=i;j<len-1;j++)
    t[j]=t[j+1];
    }

    double dealM(double *digit,char *operatorRand,int m,int n)
    {
    digit[m]=computeIt(digit[m],digit[m+1],operatorRand[m]);
    digit[m+1]=0; operatorRand[m]=0;
    //计算后把计算过的数据踢除
    removeZero(digit,4-n);removeZero(operatorRand,3-n);
    return digit[m];
    }

    double computeAnswer(double *theA,int *theRandA,int *theRandOperator,int m1,int m2)
    {
    double digit[CARDNUMBER];
    char operatorRand[3];
    int mComputePos[3]={m1,m2,0};
    for(int i=0;i<CARDNUMBER;++i) digit[i]=theA[theRandA[i]];
    for(int j=0;j<3;++j) operatorRand[j]=operators[theRandOperator[j]];
    double sum=0;
    for(int i=0;i<3;i++)
    {
    //计算括号里的数,最后剩余的两个数看成一个新括号里的数据进行运算
    sum=dealM(digit,operatorRand,mComputePos[i],i);
    //如果发现除0的情况直接返回10001,最大的计算数据是10000(即4个10相乘)
    if(sum==10000) return 10001;
    }
    return sum;
    }

    void printExpression(int *a,int *theRandA,int *theRandOperator,int m1,int m2)
    {
    char str[20];
    //memset(str,'\0',sizeof(str));
    switch(m1)
    {
    case 0:
    switch(m2)
    {
    case 0:
    sprintf(str,"((%c%c%c)%c%c)%c%c",card[a[theRandA[0]]],operators[theRandOperator[0]],card[a[theRandA

    [1]]],operators[theRandOperator[1]],card[a[theRandA[2]]],operators[theRandOperator[2]],card[a[theRandA[3]]]);
    break;
    case 1:
    sprintf(str,"(%c%c%c)%c(%c%c%c)",card[a[theRandA[0]]],operators[theRandOperator[0]],card[a[theRandA

    [1]]],operators[theRandOperator[1]],card[a[theRandA[2]]],operators[theRandOperator[2]],card[a[theRandA[3]]]);
    break;
    }
    break;
    case 1:
    switch(m2)
    {
    case 0:
    sprintf(str,"(%c%c(%c%c%c))%c%c",card[a[theRandA[0]]],operators[theRandOperator[0]],card[a[theRandA

    [1]]],operators[theRandOperator[1]],card[a[theRandA[2]]],operators[theRandOperator[2]],card[a[theRandA[3]]]);
    break;
    case 1:
    sprintf(str,"%c%c((%c%c%c)%c%c)",card[a[theRandA[0]]],operators[theRandOperator[0]],card[a[theRandA

    [1]]],operators[theRandOperator[1]],card[a[theRandA[2]]],operators[theRandOperator[2]],card[a[theRandA[3]]]);
    break;
    }
    break;
    case 2:
    switch(m2)
    {
    case 0:
    sprintf(str,"(%c%c%c)%c(%c%c%c)",card[a[theRandA[0]]],operators[theRandOperator[0]],card[a[theRandA

    [1]]],operators[theRandOperator[1]],card[a[theRandA[2]]],operators[theRandOperator[2]],card[a[theRandA[3]]]);
    break;
    case 1:
    sprintf(str,"%c%c(%c%c(%c%c%c))",card[a[theRandA[0]]],operators[theRandOperator[0]],card[a[theRandA

    [1]]],operators[theRandOperator[1]],card[a[theRandA[2]]],operators[theRandOperator[2]],card[a[theRandA[3]]]);
    break;
    }
    break;
    }
    for(unsigned i=0;i<strlen(str);i++)
    str[i]==10?printf("10"):printf("%c",str[i]);
    printf("\n");
    }

    void findAnswer(int *a)
    {
    int randTimes=RANDTIMES;
    double theA[CARDNUMBER];
    int theRandA[CARDNUMBER];
    int theRandOperator[3];
    char ch;
    //改变a中表示的数字和字母
    changeA(a,theA);
    //for(int i=0;i<4;++i) cout<<"$"<<theA[i]<<endl;
    ch=getch();//scanf("%c",&ch);
    while(randTimes--)
    {
    //产生数字的随机顺序
    randNumList(theRandA);
    //随机产生3个运算符
    randOperator(theRandOperator);
    //随机产生两个括号,第一个有3个位置,第二个有2个位置
    int m1=rand()%3;
    int m2=rand()%2;
    //按照产生的结果运算,返回计算结果
    //如果结果是24,则输出,并返回
    double temp=computeAnswer(theA,theRandA,theRandOperator,m1,m2);
    if(fabs(temp-24) < 0.00001)
    {
    //cout<<temp<<endl;
    printExpression(a,theRandA,theRandOperator,m1,m2);
    break;
    }
    }
    if(randTimes==-1)
    printf("可能是无解...\n");
    }

    void printTitle()
    {
    printf("****************************\n");
    printf("计算24\n");
    printf("A J Q K 均按1计算,其他按牌点计算\n");
    printf("目标是:通过四则运算组合出结果:24\n");
    printf("****************************\n\n");
    }
    int main()
    {
    int a[CARDNUMBER];
    char ch;
    srand(time(NULL));
    //输出介绍信息
    printTitle();
    do{
    //随机产生牌点
    cardRand(a);
    //输出选牌
    printCard(a);
    printf("按任意键参考答案...\n");
    //寻找答案
    findAnswer(a);
    printf("按任意键下一题目,x键退出...\n");
    ch=getch();//scanf("%c",&ch);使输入无回显
    }while(ch!='x');
    return 0;
    }


  • 相关阅读:
    从首页问答标题到问答详情页
    首页列表显示全部问答,完成问答详情页布局。
    制作首页的显示列表。
    记此次团队合作
    软件设计规格说明书
    软件工程(2018)第二次团队作业
    团队作业1
    结对作业2
    结对编程1
    第三次作业——题目(1)
  • 原文地址:https://www.cnblogs.com/redlight/p/2419131.html
Copyright © 2011-2022 走看看