24点游戏-穷举破解

来源:互联网 发布:sass for mac中文版 编辑:程序博客网 时间:2024/05/21 22:24

24点游戏,由1~13任意选取四个数字,利用加减乘除的方法使结果变为24,任意抽取四张,有1820种组合可以构成24点
1820来源:

按相同点数牌的张数分成五种情况讨论,分别为 4、3+1、2+1+1、2+2、1+1+1+1
需要注意每一种情况之中,只有相同张数的部分才能用组合数C来算,而不同张数之间需要用排列数算 所以是
13+A132+13*C122+CC132+C134
=13+156+858+78+715=1820

有458个牌组算不出24点

458这个数字真的不会算,求看客见过的留言,感谢:D

完成24点游戏程序的算法比较简单,将用户输入的4个数字与4个运算符进行穷举组合排列,已构成多种不同的表达式,计算每一种表达式的值。
在四则运算中,乘加法是有交换律的,除减法是没有的,在计算机中特别增加两个运算符:反向(除减)号——结果中一律以大(除以/减)小。
根据以上分析,代码如下:

#include<stdio.h>int iCount = 0; //求解计数 //输出解 void Output(int type, int o1,             int o2, int o3,             float data1, float data2,            float data3, float data4)   {    //保存6种运算符    char operator[6];        operator[0] = '+';    operator[1] = '-';    operator[2] = '*';    operator[3] = '/';    operator[4] = '-';    operator[5] = '/';    printf("解%d:", iCount);    if (type == 1)    {        //第2个运算符为反减或反除运算符        if (o2 == 4 || o2 == 5)          {            //第3个运算符为反减或反除运算符            if (o3 == 4 || o3 == 5)              {                printf("%2.0f %c (%2.0f %c (%2.0f %c %2.0f)) =24\n", data4,                    operator[o3], data3, operator[o2], data1, operator[o1], data2);            }            else            {                printf("(%2.0f %c (%2.0f %c %2.0f)) %c %2.0f =24\n", data3,                    operator[o2], data1, operator[o1], data2, operator[o3], data4);            }        }         //第3个运算符为反减或反除运算符        else if (o3 == 4 || o3 == 5)             {            printf("%2.0f %c ((%2.0f %c %2.0f) %c %2.0f) =24\n", data4,                operator[o3], data1, operator[o1], data2, operator[o2], data3);        }         else        {            printf("((%2.0f %c %2.0f) %c %2.0f) %c %2.0f =24\n", data1,                operator[o1], data2, operator[o2], data3, operator[o3], data4);        }    }    if (type == 2)    {        printf("(%2.0f %c %2.0f) %c (%2.0f %c %2.0f) =24\n", data1,            operator[o1], data2, operator[o3], data3, operator[o2], data4);    }}//根据运算符计算结果 float Calc(int oper, float data1, float data2)  {    if (oper == 0)  //加法     {        return (data1 + data2);    }    if (oper == 1)  //减法     {        return (data1 - data2);    }    if (oper == 2)  //乘法     {        return (data1 * data2);    }    if (oper == 3)  //除法     {        if (data2 == 0) //除数为0         {            //返回一个极大值            return 32767;            }        else        {            return (data1 / data2); //返回商         }    }    if (oper == 4)  //若是反减运算符     {        return (data2 - data1);    }    if (oper == 5)  //若是反除运算符     {        if (data1 == 0) //若除数为0         {            return 32767;   //返回一个极大值         }        else        {            return (data2 / data1);        }    }    return 0;}//对4个数进行试算 int Trial(float data1, float data2, float data3, float data4)   {    int o1, o2, o3;    float temp1, temp2, temp3;    for (o1 = 0; o1 < 4; o1++)  //4个运算符     {        for (o2 = 0; o2 < 6; o2++)  //6种运算符         {            for (o3 = 0; o3 < 6; o3++)  //6种运算符             {                //处理第1种表达式                 if ((!(o1 == 3 && data2 == 0)) && (!(o2 == 3 && data3 == 0))                    && (!(o3 == 3 && data4 == 0)))                      //若运算符为除法,且除数为0,不执行下面的语句                 {                    //返回a、b两数的运算结果                     temp1 = Calc(o1, data1, data2);                    //返回temp1,c两数的计算结果                    temp2 = Calc(o2, temp1, data3);                     //返回temp2,d两数的计算结果                     temp3 = Calc(o3, temp2, data4);                    //判断若temp3与24相等                    if (fabs(temp3 - 24) < 0.1)                      {                        //累加次数                        iCount++;                            //输出第1种算式的解                         Output(1, o1, o2, o3, data1, data2, data3, data4);                      }                }                //将乘法作为中间的运算符                 if (o3 == 2)                    {                    //计算a、b的运算结果                     temp1 = Calc(o1, data1, data2);                     //计算c、d的运算结果                     temp2 = Calc(o2, data3, data4);                     //计算相乘的结果                    temp3 = temp1 * temp2;                      //若结果等于24                    if (fabs(temp3 - 24) < 0.1)                    {                        iCount++;                        //输出第2种算式的解                         Output(2, o1, o2, o3, data1, data2, data3, data4);                      }                }                //将除法作为中间的运算符                 if (o3 == 3)                    {                    //计算a、b的结果                     temp1 = Calc(o1, data1, data2);                     //计算c、d的结果                     temp2 = Calc(o2, data3, data4);                     if (temp2)                    {                        //计算相除的结果                         temp2 = temp1 / temp2;                          //若结果等于24                        if (fabs(temp3 - 24) < 0.1)                         {                            iCount++;                            //输出第2种算式的解                             Output(2, o1, o2, o3, data1, data1, data3, data4);                          }                    }                }            }        }    }    return iCount;}int main(){    int i, j, k, t, result, flag;    float num[4]; //保存输入的4个数     char again = 'y';    while (again == 'y' || again == 'Y')    {        iCount = 0;        printf("\n输入4个数(1~13):");        i = 0;        flag = 0;        while (flag == 0)        {            i++;            for (i = 0; i < 4; i++) //输入4个数             {                scanf("%f", &num[i]);                //判断输入数据是否有效                if (num[i] < 1 || num[i] > 13 || num[i] != (int) (num[i]))                       flag++;            }            if (flag != 0)  //有数据输入错误             {                printf("数据输入错误,重新输入。\n", i);                flag = 0;            }            else            {                flag = 1;            }        }        //循环将4个数代入表达式进行计算         for (i = 0; i < 4; i++)         {            for (j = 0; j < 4; j++)            {                //该数组元素已用                 if (j == i)                {                    //继续下一个                     continue;                   }                for (k = 0; k < 4; k++)                {                    //该数组元素已用                    if (k == i || k == j)                       {                        continue;   //继续下一个                     }                    for (t = 0; t < 4; t++)                    {                        //该数组元素已用                        if (t == i || t == j || t == k)                         {                            continue;   //继续下一个                         }                        else                        {                            result = Trial(num[i], num[j], num[k], num[t]);                        }                    }                }            }        }        if (result == 0)            printf("\n这4个数无解!\n");        printf("\n继续(y/n)?");        again = getch();    }    return 0;}

运行演示:
这里写图片描述
这里写图片描述
这里写图片描述
最后一张图片中,箭头所指的7-8或者5-8就是反向符号。

代码下载地址:

http://pan.baidu.com/s/1skWasLB
http://download.csdn.net/download/u013553804/9501252


欢迎关注我的微信个人订阅号
这里写图片描述
每天多学一点0.0

0 0
原创粉丝点击