24点小游戏(C语言实现)

一、题目分析

题目要求:

24点小游戏是经典的纸牌益智游戏。

常见游戏规则如下:

从扑克牌中任意取出四张牌,对牌面上的四个数字使用任意的加减乘除(每张牌牌面上的数字都只能使用一次),第一个能得到24者为胜。(其中,J代表11、Q代表12、K代表13、A代表1),请按要求编写程序实现24点小游戏。

基本要求:随机生成四个代表扑克牌牌面的数字,程序自动列出所有可能算出24点的表达式,用擅长的语言(C/C++/Java或其他均可)实现程序解决问题。

  1. 程序风格良好(使用自定义的注释模板)
  2. 程序自动列出的表达式无重复

提高要求:用户初始生命值为一给定值,初始分数为0。随机生成四个代表扑克牌牌面的数字,由用户输入包含这四个数字的运算表达式(可包含括号),如果表达式计算结果为24,则代表用户赢了此局。

  1. 程序风格良好(使用自定义的注释模板)
  2. 使用计时器,要求用户在规定时间内输入表达式,如果规定时间内运算正确则加分,超时或运算错误则进入下一题并减少生命值(不扣分)
  3. 所有成绩均可记录在TopList.txt文件中

分析:

1.可以通过rand()函数生成四个1-13的随机数

2.通过分析,表达式可分为以下三类:

  1. )不含括号的表达式
  2. )含有一个括号的表达式
  3. )含有两个括号的表达式

这三类表达式可具体概括为以下五种:

● ((A_B)_C)_D

● (A_(B_C))_D

● A_((B_C)_D)

● A_(B_(C_D))

● (A_B)_(C_D)

我们可以通过3个for循环的嵌套根据五种表达式类型穷举出四个随机数可能组成的所有表达式,并利用if条件判断输出所有能够得到24点的表达式。

二、算法构造(流程图)

● 通过num()函数生成四个1-13的随机数

void num()
{
	int i;
	srand(time(NULL));

	for(i=0; i<4; i++)
	{
		a[i] = rand()%13+1;
	}
	for(i=0; i<4; i++)
	{
		printf("第%d张牌:%d\n", i+1, a[i]);
	}
}

● 通过cal()函数对两个操作数进行计算

int cal(int x, int y, char ope)
{
	int z;
	if(ope=='+')
		z = x+y;
	else if(ope=='-')
		z = x-y;
	else if(ope=='*')
		z = x*y;
	else if(ope=='/')
		z = x/y;

	return z;
}

● 通过express_1()函数计算表达式((A_B)_C)_D

int express_1(int i, int j, int k, int t, char ope1, char ope2, char ope3)
{
	int x1, x2, x3;
	x1 = cal(i, j, ope1);
	x2 = cal(x1, k, ope2);
	x3 = cal(x2, t, ope3);

	return x3;
}

● 通过express_2()函数计算表达式(A_(B_C))_D

int express_2(int i, int j, int k, int t, char ope1, char ope2, char ope3)
{
	int x1, x2, x3;
	x1 = cal(j, k, ope2);
	x2 = cal(i, x1, ope1);
	x3 = cal(x2, t, ope3);

	return x3;
}

● 通过express_3()函数计算表达式A_((B_C)_D)

int express_3(int i, int j, int k, int t, char ope1, char ope2, char ope3)
{
	int x1, x2, x3;
	x1 = cal(j, k, ope2);
	x2 = cal(x1, t, ope3);
	x3 = cal(i, x2, ope1);

	return x3;
}

● 通过express_4()函数计算表达式A_(B_(C_D))

int express_4(int i, int j, int k, int t, char ope1, char ope2, char ope3)
{
	int x1, x2, x3;
	x1 = cal(k, t, ope3);
	x2 = cal(j, x1, ope2);
	x3 = cal(i, x2, ope1);

	return x3;
}

● 通过express_5()函数计算表达式(A_B)_(C_D)

int express_5(int i, int j, int k, int t, char ope1, char ope2, char ope3)
{
	int x1, x2, x3;
	x1 = cal(i, j, ope1);
	x2 = cal(k, t, ope3);
	x3 = cal(x1, x2, ope2);

	return x3;
}

● 通过3个for循环穷举出四个随机数所能组成的所有表达式,并利用if条件判断输出所有能够得到24点的表达式

	for(x=0; x<4; x++)
	{
		p = ope[x];
		for(y=0; y<4; y++)
		{
			q = ope[y];
			for(z=0; z<4; z++)
			{
				r = ope[z];
				if(express_1(i, j, k, t, p, q, r)==24)
					printf("((%d %c %d) %c %d) %c %d = 24\n", i, p, j, q, k, r, t);
				if(express_2(i, j, k, t, p, q, r)==24)
					printf("(%d %c (%d %c %d)) %c %d = 24\n", i, p, j, q, k, r, t);
				if(express_3(i, j, k, t, p, q, r)==24)
					printf("%d %c ((%d %c %d) %c %d) = 24\n", i, p, j, q, k, r, t);
				if(express_4(i, j, k, t, p, q, r)==24)
					printf("%d %c (%d %c (%d %c %d)) = 24\n", i, p, j, q, k, r, t);
				if(express_5(i, j, k, t, p, q, r)==24)
					printf("(%d %c %d) %c (%d %c %d) = 24\n", i, p, j, q, k, r, t);
			}
		}
	}

三、算法实现(源代码)

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int a[4];    // 数组a[]用于存放随机产生的四个操作数
char ope[4] = {'+','-','*','/'};    // 数组ope[]用于存放四类运算符

// 通过num()函数生成四个1-13的随机数
void num()
{
	int i;
	srand(time(NULL));

	for(i=0; i<4; i++)
	{
		a[i] = rand()%13+1;
	}
	for(i=0; i<4; i++)
	{
		printf("第%d张牌:%d\n", i+1, a[i]);
	}
}

// 通过cal()函数对两个操作数进行计算
int cal(int x, int y, char ope)
{
	int z;
	if(ope=='+')
		z = x+y;
	else if(ope=='-')
		z = x-y;
	else if(ope=='*')
		z = x*y;
	else if(ope=='/')
		z = x/y;

	return z;
}

// 通过express_1()函数计算表达式((A_B)_C)_D
int express_1(int i, int j, int k, int t, char ope1, char ope2, char ope3)
{
	int x1, x2, x3;
	x1 = cal(i, j, ope1);
	x2 = cal(x1, k, ope2);
	x3 = cal(x2, t, ope3);

	return x3;
}

// 通过express_2()函数计算表达式(A_(B_C))_D
int express_2(int i, int j, int k, int t, char ope1, char ope2, char ope3)
{
	int x1, x2, x3;
	x1 = cal(j, k, ope2);
	x2 = cal(i, x1, ope1);
	x3 = cal(x2, t, ope3);

	return x3;
}

// 通过express_3()函数计算表达式A_((B_C)_D)
int express_3(int i, int j, int k, int t, char ope1, char ope2, char ope3)
{
	int x1, x2, x3;
	x1 = cal(j, k, ope2);
	x2 = cal(x1, t, ope3);
	x3 = cal(i, x2, ope1);

	return x3;
}

// 通过express_4()函数计算表达式A_(B_(C_D))
int express_4(int i, int j, int k, int t, char ope1, char ope2, char ope3)
{
	int x1, x2, x3;
	x1 = cal(k, t, ope3);
	x2 = cal(j, x1, ope2);
	x3 = cal(i, x2, ope1);

	return x3;
}

// 通过express_5()函数计算表达式(A_B)_(C_D)
int express_5(int i, int j, int k, int t, char ope1, char ope2, char ope3)
{
	int x1, x2, x3;
	x1 = cal(i, j, ope1);
	x2 = cal(k, t, ope3);
	x3 = cal(x1, x2, ope2);

	return x3;
}

void main()
{
	printf("#**************************************#\n");
	printf("#                                      #\n");
	printf("#              欢迎来到                #\n");
	printf("#                                      #\n");
	printf("#             24点小游戏               #\n");
	printf("#                                      #\n");
	printf("#**************************************#\n");

	printf("请按任意键开始游戏:\n");
	getchar();

	num();

	int i, j, k, t;
	i = a[0];
	j = a[1];
	k = a[2];
	t = a[3];

	int x, y, z;
	char p, q, r;

	printf("\n");
	printf("所有能够出现24点的表达式有:\n");

	/* 通过三个for循环的嵌套,穷举出四个随机数所能组成的所有表达式;
	   通过与最里层for循环嵌套的五个if判断输出所有能够得到24点的表达式。*/
	for(x=0; x<4; x++)
	{
		p = ope[x];
		for(y=0; y<4; y++)
		{
			q = ope[y];
			for(z=0; z<4; z++)
			{
				r = ope[z];
				if(express_1(i, j, k, t, p, q, r)==24)
					printf("((%d %c %d) %c %d) %c %d = 24\n", i, p, j, q, k, r, t);
				if(express_2(i, j, k, t, p, q, r)==24)
					printf("(%d %c (%d %c %d)) %c %d = 24\n", i, p, j, q, k, r, t);
				if(express_3(i, j, k, t, p, q, r)==24)
					printf("%d %c ((%d %c %d) %c %d) = 24\n", i, p, j, q, k, r, t);
				if(express_4(i, j, k, t, p, q, r)==24)
					printf("%d %c (%d %c (%d %c %d)) = 24\n", i, p, j, q, k, r, t);
				if(express_5(i, j, k, t, p, q, r)==24)
					printf("(%d %c %d) %c (%d %c %d) = 24\n", i, p, j, q, k, r, t);
			}
		}
	}
}

四、调试、测试与运行结果

调试:

对最外层for循环打断点,查看其中变量值变化是否正确

 

通过调试发现,main()函数在调用express_5()函数时 x3 = x1+x2;语句中x3的值有问题,

该语句应改为x3 = cal(x1, x2, ope2);

 

对变量Z加断点,查看其值在cal()函数中的变化

测试:

添加测试代码(验证是否能生成四个1-13的随机数):
void main()
{
	int i;
	srand(time(NULL));
	for(i=0; i<4; i++)
		a[i] = rand()%13+1;
	for(i=0; i<4; i++)
		printf("%d", a[i]);
}

运行结果:

五、总结

本次作业利用C语言编程设计实现了24点小游戏的基本要求。在程序设计实现的过程中遇到了许多问题,就比如说通常我们要得到四个随机数都会利用rand()函数随机生成,可是用这种方法产生的随机数每次都是一样的,为了解决这一问题,我上网搜索到在使用rand()函数前都必须要利用srand()函数设置随机数种子,采用在随机数生成前加入srand(time(NULL));的方式解决了问题。除此之外,由于自身算法能力不强,找不到一个合理实现24点小游戏的算法,最后还是通过查阅大量资料找到了解决方法,通过3个for循环的嵌套根据五种运算表达式类型,穷举出四个随机数能够组成的所有表达式,再利用最内层循环嵌套的5个if判断输出所有能够得到24点的表达式。由于自身能力的原因,我只完成了基本要求(OS.我也是垃圾的可以。。。)。通过这次作业,我的算法能力有了进一步的提升,在今后的作业中我会尽量通过自己的努力解决问题。ps.由于自身能力原因,实现代码可能存在一些问题,还请各位大佬们不吝赐教啊!

 

 

 

 

 

  • 46
    点赞
  • 226
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
以下是C语言实现24点游戏的代码和解释: ```c #include <stdio.h> #include <stdlib.h> #define TARGET 24 #define EPSILON 1e-6 int dfs(double *nums, int len) { if (len == 1) { if (fabs(nums[0] - TARGET) < EPSILON) { return 1; } else { return 0; } } int i, j; double tmp[5]; for (i = 0; i < len; i++) { for (j = i + 1; j < len; j++) { int k, idx = 0; for (k = 0; k < len; k++) { if (k != i && k != j) { tmp[idx++] = nums[k]; } } tmp[idx] = nums[i] + nums[j]; if (dfs(tmp, len - 1)) { printf("%.0lf+%.0lf\n", nums[i], nums[j]); return 1; } tmp[idx] = nums[i] - nums[j]; if (dfs(tmp, len - 1)) { printf("%.0lf-%.0lf\n", nums[i], nums[j]); return 1; } tmp[idx] = nums[j] - nums[i]; if (dfs(tmp, len - 1)) { printf("%.0lf-%.0lf\n", nums[j], nums[i]); return 1; } tmp[idx] = nums[i] * nums[j]; if (dfs(tmp, len - 1)) { printf("%.0lf*%.0lf\n", nums[i], nums[j]); return 1; } if (nums[j] != 0) { tmp[idx] = nums[i] / nums[j]; if (dfs(tmp, len - 1)) { printf("%.0lf/%.0lf\n", nums[i], nums[j]); return 1; } } if (nums[i] != 0) { tmp[idx] = nums[j] / nums[i]; if (dfs(tmp, len - 1)) { printf("%.0lf/%.0lf\n", nums[j], nums[i]); return 1; } } } } return 0; } int main() { double nums[5]; int i; for (i = 0; i < 4; i++) { scanf("%lf", &nums[i]); } if (dfs(nums, 4)) { printf("Yes\n"); } else { printf("No\n"); } return 0; } ``` 代码解释: 1. 定义了目标值TARGET和一个极小值EPSILON,用于判断计算结果是否等于目标值。 2. dfs函数是本程序的核心,用于递归计算所有可能的表达式,直到只剩下一个数,判断是否等于目标值。 3. 在dfs函数中,首先判断是否只剩下一个数,如果是,则判断该数是否等于目标值,如果是,则返回1,否则返回0。 4. 如果不止一个数,则枚举所有可能的两个数的组合,计算它们的和、差、积、商,并将结果存入一个临时数组tmp中,然后递归调用dfs函数,计算剩下的数。 5. 如果递归调用的结果为1,则说明找到了一种表达式,输出该表达式,并返回1。 6. 如果所有的组合都尝试过了,仍然没有找到符合要求的表达式,则返回0。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值