24点游戏c语言链表做法,常见算法应用实践:24点游戏算法代码实现

24点游戏算法

在现实项目开发应用中,游戏方面的应用程序比较受欢迎,在软件产业中占据了很大的比例。例如24点游戏是一个棋牌类益智游戏,要求结果等于24。在本节中,将详细讲解C语言实现24点游戏的算法。

实例15-2 编程实现24点游戏

问题描述:编写实现24点游戏的C语言程序。

算法分析:其实24点游戏是用4个数字经过数学运行,并得到结果是24的过程。大多数版本应该使用扑克的52张牌(大小王除外),A表示1,K表示13,看任意4张牌是否能够组合得到24。在将4个数进行四则运算时,一般的思维是在4个数中间的3个空放置3个运算符,然后需要在不同的地方加上括号表示优先级的不同。如果仅仅是数字和运算符则很好实现,一旦要添加括号就会变得比较难了。但是后缀表达式可以实现无括号的优先级运算,那么此处使用后缀表达式的这种方法来实现就比较简单了。

在此假设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中可能,4种总计有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。而既然能够得到负数,两个数的位置调换一下就是一个正数了,没有必要在数值前边加上负号来处理。

具体实现:编写实例文件15-2.c,具体实现代码如下所示。

#include

#include

#include

#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 num4n");

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正整数n");

exit(2);

}

}

/*2 pairs of paren, 3 operators, 1 for NULL. */

len += 4 + 3 + 1;

result = (char *)malloc (len);

if (test(nums, result))

printf ("%sn", result);

else

printf ("No Matched.n");

if (result != NULL)

free (result);

getch();

return 0;

}

/* 测试所有可能的情况,找到一种解法*/

int test (const int nums[], char * result)

{

int I, J, M, N;

int r, s, t;

int ret, ret1, ret2;

/*first loop: I J r M N s t ==> (I r J) t (M s N) */

for (I = 0; I < 4; I++)

{

for (J = 0; J < 4; J++)

{

if (J == I)

continue;

for (r = 0; r < 4; r++)

{

ret1 = calculate (nums[I], nums[J], ops[r]);

if (ret1 <= 0)

continue;

for (M = 0; M < 4; M++)

{

if (M == I || M == J)

continue;

for (N = 0; N < 4; N++)

{

if (N == I || N == J || N == M)

continue;

for (s = 0; s < 4; s++)

{

ret2 = calculate (nums[M], nums[N], ops[s]);

if (ret2 <= 0)

continue;

for (t = 0; t < 4; t++)

{

ret = calculate (ret1, ret2, ops[t]);

if (((ret&MASK)==24) && ((ret>>SHIFT)==0))

{

sprintf (result, "(%d%c%d)%c(%d%c%d)",

nums[I], ops[r], nums[J], ops[t],

nums[M], ops[s], nums[N]);

return SUCCESS;

}

}

}

}

/* second loop: I J r M s N t ==> ((I r J) s M) t N */

for (s = 0; s < 4; s++)

{

ret2 = calculate (ret1, nums[M], ops[s]);

if (ret2 <= 0)

continue;

for (N = 0; N < 4; N++)

{

if (N == I || N == J || N == M)

continue;

for (t = 0; t < 4; t++)

{

ret = calculate (ret2, nums[N], ops[t]);

if (((ret&MASK)==24) && ((ret>>SHIFT)==0))

{

sprintf (result, "((%d%c%d)%c%d)%c%d",

nums[I], ops[r], nums[J], ops[s],

nums[M], ops[t], nums[N]);

return SUCCESS;

}

}

}

}

}

}

}

}

/* third loop: I J M r s N t ==> (I s (J r M)) t N */

for (I = 0; I < 4; I++)

{

for (J = 0; J < 4; J++)

{

if (J == I)

continue;

for (M = 0; M < 4; M++)

{

if (M == I || M == J)

continue;

for (r = 0; r < 4; r++)

{

ret1 = calculate (nums[J], nums[M], ops[r]);

if (ret1 <= 0)

continue;

for (s = 0; s < 4; s++)

{

ret2 = calculate (nums[I], ret1, ops[s]);

if (ret2 <= 0)

continue;

for (N = 0; N < 4; N++)

{

if (N == I || N == J || N == M)

continue;

for (t = 0; t < 4; t++)

{

ret = calculate (ret2, nums[N], ops[t]);

if (((ret&MASK)==24) && ((ret>>SHIFT)==0))

{

sprintf (result, "(%d%c(%d%c%d))%c%d",

nums[I], ops[s], nums[J], ops[r],

nums[M], ops[t], nums[N]);

return SUCCESS;

}

}

}

}

}

}

}

}

/* forth loop: I J M N r s t ==> I t (J s (M r N)) */

for (I = 0; I < 4; I++)

{

for (J = 0; J < 4; J++)

{

if (J == I)

continue;

for (M = 0; M < 4; M++)

{

if (M == I || M == J)

continue;

for (N = 0; N < 4; N++)

{

if (N == I || N == J || N == M)

continue;

for (r = 0; r < 4; r++)

{

ret1 = calculate (nums[M], nums[N], ops[r]);

if (ret1 <= 0)

continue;

for (s = 0; s < 4; s++)

{

ret2 = calculate (nums[J], ret1, ops[s]);

if (ret2 <= 0)

continue;

for (t = 0; t < 4; t++)

{

ret = calculate (nums[I], ret2, ops[t]);

if (((ret&MASK)==24) && ((ret>>SHIFT)==0))

{

sprintf (result, "%d%c(%d%c(%d%c%d))",

nums[I], ops[t], nums[J], ops[s],

nums[M], ops[r], nums[N]);

return SUCCESS;

}

}

}

}

}

}

}

}

return FAILURE;

}

/* 计算两个特定的数和操作符的结果*/

int calculate (int num1, int num2, char op)

{

int numerator_num1, numerator_num2;

int denominator_num1, denominator_num2;

int ret = 0;

int denominator, numerator;

denominator_num1 = num1 >> SHIFT; //分母

denominator_num2 = num2 >> SHIFT;

numerator_num1 = num1 & MASK; //分子

numerator_num2 = num2 & MASK;

/* 确定分母,将分子同一化*/

if (denominator_num1 > 0 && denominator_num2 > 0)

{

denominator = denominator_num1 * denominator_num2;

numerator_num1 = denominator_num2 * numerator_num1;

numerator_num2 = denominator_num1 * numerator_num2;

}

else if (denominator_num1 > 0 && denominator_num2 == 0)

{

denominator = denominator_num1;

numerator_num2 = denominator_num1 * numerator_num2;

}

else if (denominator_num1 == 0 && denominator_num2 > 0)

{

denominator = denominator_num2;

numerator_num1 = denominator_num2 * numerator_num1;

}

else

{

denominator = 0;

}

/* 计算*/

if (op == '+')

{

numerator = numerator_num1 + numerator_num2;

}

else if (op == '-')

{

numerator = numerator_num1 - numerator_num2;

}

else if (op == '*')

{

numerator = numerator_num1 * numerator_num2;

denominator *= denominator;

}

else if (op == '/')

{

if (numerator_num2 > 0 && numerator_num1%numerator_num2 == 0)

{

/* 分子可以整除,分母就没有必要了。*/

numerator = numerator_num1 / numerator_num2;

denominator = 0;

}

else

{

numerator = numerator_num1;

denominator = numerator_num2;

}

}

if (denominator>0 && numerator%denominator == 0)

{

numerator = numerator / denominator;

denominator = 0;

}

ret = (numerator<=0)?numerator:((numerator&MASK) | (denominator<

return ret;

}

通过上述算法代码,计算了4个1~13之间的数(包含)是否能够通过加减乘除达到结果为24。执行效果如图15-1所示。

519eb87bc7184474e0ac604511b0ade6.png

24点游戏执行效果

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值