24点游戏算法及实现(后缀表达式思想)

本文介绍了24点游戏的算法思想,使用后缀表达式解决四则运算优先级问题,避免使用括号。通过4个1到13之间的数,运用加减乘除操作尝试所有组合,寻找得到24的方法。代码实现中,针对计算机无法精确表示某些分数的问题,采用了特殊的整数表示法。最后展示了完整的C语言代码实现。
摘要由CSDN通过智能技术生成

一般而言,我理解的24点游戏是用4个数字经过数学运行,得到24. 一般推广版的应该使用扑克的52张牌(出去大小王),A表示1,K表示13.任意4张牌看是否能够组合得到24.
我这里所设计的就是这样的情况,而不是任意的4个数。(因为这里需要用一个办法表示分数,而我使用了比较简单的一种,能表示范围较小,所以我只处理了1到13这个情况。虽然实现里边可以将13这个范围向上推一段。)
4个数进行四则运算,一般的思维是四个数中间的3个空放置3个运算符,然后可能还需要在不同的地方加上括号,表示优先级的不同。仅仅是数字和运算符好好 做,一旦要添加括号就会有点乱七八糟。前两天看网页突然看到后缀表达式这个东西,我一下想起来了。(网页作者说后缀表达式可以实现无括号的优先级运算)那 我使用后缀表达式的这种方法来做就简单了。反正就只有4个数。
假设I、J、M、N是4个数,r、s、t是3个运算符。那么使用后缀表达式只有如下4种情况:
1)I J r M N s t ==> (I r J) t (M s N)
2)I J r M s N t ==> ((I r J) s M) t N
3)I J M r s N t ==> (I s (J r M)) t N
4)I J M N r s t ==> I t (J s (M r N))
不理会所有的重复,上面4种情况分别有1536中可能,那么总计就是 6144中可能情况。每种情况计算3次,也就20000次计算而已。对计算机来说这个数目是极小的。
在实现中,我没有采用任何取巧的办法,而是每种情况使用了7个for循环进行计算。唯一的取巧是前两种的前边4个for循环是一样,我就将两种拼起来了。
处理整数计算还有一个问题是,计算机无法精确的表示分数,特别是那种无限小数,比如1/3这种。如果不能精确计算,最后就无法判断是否精确等于24,这是计算机的一个弱点,这点不如人啊。
我的方法是,每个数字都用一个int表示,int表示为4字节。由于最大的单个数为13,那么即使是13的连乘也不过28561,不足两个字节能表示的 65536 。因此我使用一个int的低两个字节表示分子或者实际的数值(没有分母的,也就等于整个int表示的数),高两个字节表示分母(不存在分母则表示为0)。 在做计算时将分子统一为等分母的数,然后计算之后与分母作用得到最后的数。这样的话4/5就表示为了0x00050004了。
由于找到一种解法就结束,所以根据输入的数据,得到的可能与通常人们计算得到的结果有出入,比如2 2 6 6 ,人的计算结果一般为2*6+2*6,但是程序结果可能为(2+6)*(6/2),当然结果也是正确的。
另外需要注意的是,对于任何两个数计算得到负数,我都没有继续啊向下计算,因为这个必须得加一个正数或者乘以一个辅助才可能得到24 。而既然能够得到负数,两个数的位置调换一下就是一个正数了,没有必要在数值前边加上负号来处理。
具体实现代码如下,c语言实现:

/* 24.c 计算4个1到13之间的数(包含)是否能够通过加减乘除达到24.*/
#include <stdio.h>

#define MASK  0xFFFF
#define SHIFT 16
enum {FAILURE = 0, SUCCESS};
const char ops[] = "+*-/";

int test (const int nums[], char *result);
int calculate (int num1, int num2, char op);

int main(int argc, char *argv[])
{
    int len = 0;
    int nums[4] = {0};
    int i;
    char *result;
    if (argc != 5)
    {
        printf("Usage: 24.exe num1 num2 num3 num4/n");
        exit(1);
    }
    for (i = 0 ;i < 4 ;i++ )
    {
        len += strlen (argv[i+1]);
        nums[i] = atoi (argv[i+1]);
        if (nums[i] < 1 || nums[i] > 13)
        {
            printf ("所有的数字都应该是1到13正

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
C语言实现中缀表达式转换为后缀表达式算法可以使用栈来实现。具体的步骤如下: 1. 从左到右遍历中缀表达式中的每一个元素(包括数字和运算符)。 2. 如果遇到数字,直接将其输出到后缀表达式中。 3. 如果遇到运算符,则判断其与栈顶运算符的优先级,如果该运算符优先级小于或等于栈顶运算符,则将栈顶运算符弹出并输出到后缀表达式中,直到遇到优先级更低的运算符或者栈为空,然后将该运算符压入栈中。 4. 如果遇到左括号,则直接将其压入栈中。 5. 如果遇到右括号,则依次将栈顶元素弹出并输出到后缀表达式中,直到遇到左括号为止,此时将左括号弹出但不输出。 6. 重复步骤1-5,直到遍历完中缀表达式。 7. 如果栈中还有元素,则依次将其弹出并输出到后缀表达式中。 下面是一个示例中缀表达式转换为后缀表达式的过程: 中缀表达式:2 + 3 * 4 - (5 + 6) 后缀表达式:2 3 4 * + 5 6 + - 具体步骤如下: 1. 遇到数字2,输出到后缀表达式中。 2. 遇到运算符+,压入栈中。 3. 遇到数字3,输出到后缀表达式中。 4. 遇到运算符*,由于*的优先级高于+,所以直接压入栈中。 5. 遇到数字4,输出到后缀表达式中。 6. 遇到运算符-,由于-的优先级低于*,所以将*弹出并输出到后缀表达式中,然后将-压入栈中。 7. 遇到左括号(,直接压入栈中。 8. 遇到数字5,输出到后缀表达式中。 9. 遇到运算符+,由于+的优先级等于(,所以将(弹出但不输出,并将+压入栈中。 10. 遇到数字6,输出到后缀表达式中。 11. 遇到右括号),依次将栈顶元素弹出并输出到后缀表达式中,直到遇到左括号为止。此时将左括号弹出但不输出。 12. 遍历完整个中缀表达式,依次将栈中剩余的元素弹出并输出到后缀表达式中。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值