24点游戏算法

游戏规则: 一副牌中去掉大小王,在剩下的52张牌中任意取四张。使用四则运算,使其最后结果为24.其中每张牌只能使用一次且A=1,J=11,Q=12,K=13。

     譬如 2,4,6,8  ------>  结果为 6/(4-2)*8=24;

 

算法思考: 首先,从宏观上说,这种问题都是遍历穷举。再看看运算符,其中+,* 都是没有顺序的。即(a*b=b*a), 但是 -、/ 是有顺序的。那么假设都有顺序的。那么就可以统一处理了(最多效率低点,先解决问题。再考虑优化)。那么遍历所有a,b,c,d 以及 三次运算 。即A(4,4) *4*4*4 就是该算法的复杂度。(事实证明我错了。后面会讲到。)

微观上,由于中间有除法,那么不能用int类型来储存数据了。需要用double或者float.每次运算都只有两个数运算。

24点游戏编程具体算法思想可以参考《编程之美》,下面给出自己根据文中算法改写的C语言算法:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

const double Threshold = 1E-6;
#define CardsNumber  4
const int ResultValue = 24;
double NumberCard[CardsNumber];
char *result[CardsNumber];

char *oprate(char *expa,char *expb,char op)
{
	//char *c=r;
	char *c=(char *)malloc(sizeof(char)*50);
	char *b="(";
	char *a=")";
	
	strcpy(c,b);
	strcat(c,expa);
	strcat(c,&op);
	strcat(c,expb);
	strcat(c,a);
	return c;
}
int PointGame(int n)
{
	int i,j,k;
	double a,b;
	char expa[50]={'0'};
	char expb[50]={'0'};
	char op;

	if (n == 1)
	{
		 if (fabs(NumberCard[0]-ResultValue) < Threshold)
		 {
			 printf("%s\n",result[0]);
			 return -1;
		 }
		 else
		 {
			 return 0;
		 }
	}
	else
	{
		for (i = 0;i < n;i++)
		{
			for (j = i+1;j < n;j++)
			{
				
				a = NumberCard[i];
				b = NumberCard[j];
				NumberCard[j] = NumberCard[n-1];
				/* 因为需要删去两个已经进行过运算的数,所以在此利用NumberCard[i]保存运算结果,
				利用NumberCard[j]保存最后一个数
				*/
				for (k=0;k<strlen(result[i]);k++)
				{	
					expa[k]=result[i][k];
				}
				expa[k]='\0';
				for (k=0;k<strlen(result[j]);k++)
				{
					expb[k]=result[j][k];
				}
				expb[k]='\0';
				strcpy(result[j],result[n-1]);
				

				op = '+';
				result[i]=oprate(expa,expb,op);
				NumberCard[i] = a+b;
				if (PointGame(n-1))
					return -1;

				op = '-';
				result[i]=oprate(expa,expb,op);
				NumberCard[i] = a-b;
				if (PointGame(n-1))
					return -1;

				op = '-';
				result[i]=oprate(expb,expa,op);
				NumberCard[i] = b-a;
				if (PointGame(n-1))
					return -1;

				op = '*';
				result[i]=oprate(expa,expb,op);
				NumberCard[i] = a*b;
				if (PointGame(n-1))
					return -1;

				if (b != 0)
				{
					op = '/';
				    result[i]=oprate(expa,expb,op);
				    NumberCard[i] = a/b;
				    if (PointGame(n-1))
					    return -1;
				}

				if (a != 0)
				{
					op = '/';
				    result[i]=oprate(expb,expa,op);
				    NumberCard[i] = b/a;
				    if (PointGame(n-1))
					    return -1;
				}

				NumberCard[i] = a;
				NumberCard[j] = b;
				strcpy(result[i],expa);
				strcpy(result[j],expb);

			}
		}
	}
	return 0;
}

int main()
{
	int x;
	int i;
	char buffer[4][100]={'0'};

	for (i = 0;i < CardsNumber;i++)
	{
		printf("the %d number:\n",i);
		scanf("%d",&x);
		NumberCard[i]=x;
		itoa(x,buffer[i],10);
		result[i]=buffer[i];
	}
	i=PointGame(CardsNumber);
	if (i!=0)
	{
		printf("Success!\n");
	}
	else 
	{
		printf("Fail\n");
	}

	system("pause");
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值