题目:24点游戏是经典的纸牌益智游戏。
常见游戏规则:
从扑克中每次取出4张牌。使用加减乘除,第一个能得出24者为赢。(其中,J代表11,Q代表12,K代表13,A代表1),按照要求编程解决24点游戏。
基本要求: 随机生成4个代表扑克牌牌面的数字字母,程序自动列出所有可能算出24的表达式,用擅长的语言(C/C++/Java或其他均可)实现程序解决问题。
分析:穷举法思想
- 随机产生四个数,将四个数转换成扑克牌面数。
- 从四个数中取出两个数进行运算,然后把运算结果和第三个数进行运算,再把结果与第四个数进行运算。
- 在求表达式的过程中,将括号所在表达式中的所有位置都罗列出来,然后递归调用每种形式,然后又将每种形式中的运算符穷举进行排列运算。
- 最后输出满足结果的所有表达式。如果不能算出结果,输出无解。
流程图:
测试(部分):
测试产生的四个随机纸牌:
测试代码:
#include<stdio.h>
#include <stdlib.h>//产生随机数
#include <time.h>//时间函数,还是用来产生符合要求的随机数
#include <math.h>//数学函数库,进行一些数学运算
void Random(int *num)//产生1-13之间四个随机数函数
{
int i;
srand((unsigned)time(NULL));//时间种子,避免每次出现上次的四个随机数,unsigned表示不含负数
for(i=0;i<4;i++)
{
num[i]=rand()%13+1;//1-13之间取余数,随机数在1-13之间产生
}
return;
}
char pukepai(int x)//将随机数转化成牌面数字(由于10我不会转换成字符形式,因此10用S表示)
{
if(x==1)
return 'A';
else if(x==11)
return 'J';
else if(x==12)
return 'Q';
else if(x==13)
return 'K';
else if(x<10)
return x+'0';
else if(x==10)
return 'S';
}
void printRandom(int *num)//输出产生的四个随机数
{
for(int i=0;i<4;i++)
{
printf("%c ",pukepai(num[i]));
}
printf("\n");
return ;
}
void main()
{
int num[4]; //存放四个随机数的数组
Random(num);
printRandom(num);
}
测试结果:
注:其他部分的测试其实就是运行代码
运行结果:
有扑克牌面的:
源代码:
#include <stdio.h>
#include <stdlib.h>//产生随机数
#include <time.h>//时间函数,还是用来产生符合要求的随机数
#include <math.h>//数学函数库,进行一些数学运算
void Random(int *num)//产生1-13之间四个随机数函数
{
int i;
srand((unsigned)time(NULL));//时间种子,避免每次出现上次的四个随机数,unsigned表示不含负数
for(i=0;i<4;i++)
{
num[i]=rand()%13+1;//1-13之间取余数,随机数在1-13之间产生
}
return;
}
char pukepai(int x)//将随机数转化成牌面数字(由于10我不会转换成字符形式,因此10用S表示)
{
if(x==1)
return 'A';
else if(x==11)
return 'J';
else if(x==12)
return 'Q';
else if(x==13)
return 'K';
else if(x<10)
return x+'0';
else if(x==10)
return 'S';
}
void printRandom(int *num)//输出产生的四个随机数
{
for(int i=0;i<4;i++)
{
printf("%c ",pukepai(num[i]));
}
printf("\n");
return ;
}
void printAnswer(int flag,int *num,char *oper,char *answer)//输出运算结果为24的表达式
{
char a=pukepai(num[0]);
char b=pukepai(num[1]);
char c=pukepai(num[2]);
char d=pukepai(num[3]);//将四个随机数分别赋值给变量a,b,c,d
switch(flag)
{
case 1:
printf("((%c%c%c)%c%c)%c%c\n",a,oper[0],b,oper[1],c,oper[2],d);//((A*B)*C)*D
break;
case 2:
printf("(%c%c(%c%c%c))%c%c\n",a,oper[0],b,oper[1],c,oper[2],d);//(A*(B*C))*D
break;
case 3:
printf("(%c%c%c)%c(%c%c%c)\n",a,oper[0],b,oper[1],c,oper[2],d);//(A*B)*(C*D)
break;
case 4:
printf("%c%c(%c%c(%c%c%c))\n",a,oper[0],b,oper[1],c,oper[2],d);//A*(B*(C*D))
break;
case 5:
printf("%c%c((%c%c%c)%c%c)\n",a,oper[0],b,oper[1],c,oper[2],d);//A*((B*C)*D)
break;
default:
break;
}
return;
}
double getValue(double num1,double num2,char oper)// 两个随机数之间的可能运算形式
{
double result;
switch(oper)
{
case'+':
result=num1+num2;break;//运算符为加号,则直接相加
case'-':
if(num1>=num2)
result=num1-num2;
else
result=num2-num1;
break;//运算符为减号,则需要注意运算的结果
case'*':
result=num1*num2;
break;//运算符为乘号,则直接相乘
case'/':
result=num1/num2;
break;//运算符为除号,直接相除
default:
break;
}
return result;
}
int Result(int *num,char *oper,char *answer)//得到24点表达式的所有可能结果
{
double t;
int a=num[0];
int b=num[1];
int c=num[2];
int d=num[3];
//穷举法进行运算
//((A*B)*C)*D
t=0;
t=getValue(a,b,oper[0]);
t=getValue(t,c,oper[1]);
t=getValue(t,d,oper[2]);
if(t==24)
{
printAnswer(1,num,oper,answer);
return 1;
}
//(A*(B*C))*D
t=0;
t=getValue(b,c,oper[1]);
t=getValue(a,t,oper[0]);
t=getValue(t,d,oper[2]);
if(t==24)
{
printAnswer(2,num,oper,answer);
return 1;
}
//(A*B)*(C*D)
t=0;
t=getValue(getValue(a,b,oper[0]),getValue(c,d,oper[2]),oper[1]);
if(t==24)
{
printAnswer(3,num,oper,answer);
return 1;
}
//A*((B*(C*D))
t=0;
t=getValue(c,d,oper[2]);
t=getValue(b,t,oper[1]);
t=getValue(a,t,oper[0]);
if(t==24)
{
printAnswer(4,num,oper,answer);
return 1;
}
//A*((B*C)*D)
t=0;
t=getValue(b,c,oper[1]);
t=getValue(t,d,oper[2]);
t=getValue(a,t,oper[0]);
if(t==24)
{
printAnswer(5,num,oper,answer);
return 1;
}
return 0;
}
void printResult(int *num,char *answer)//输出算出24的所有表达式
{
char OperKey[4]={'+','-','*','/'};
char oper[3];
int i,j,k;
int count=0;
for(i=0;i<4;i++)
for(j=0;j<4;j++)
for(k=0;k<4;k++)//循环运算符,得到多种表达式
{
oper[0]=OperKey[i];
oper[1]=OperKey[j];
oper[2]=OperKey[k];
if(Result(num,oper,answer))//判断产生的4个随机数是否有解
count++;//解的个数
}
if(count)
{
printf("共%d种解法\n",count);
}
else
{
printf("该种情况无解\n");
}
return ;
}
int main()
{
int num[4]; //存放四个随机数的数组
int k=1;
int number;
char answer[20];
while(k) //循环执行
{
printf("A=1,S=10,J=11,Q=12,K=13\n");
printf("请选择:");
printf("1.运算 2.退出\n");
scanf("%d",&number);
switch(number)
{
case 1:
printf("随机生成的纸牌为:\n");
Random(num);
printRandom(num);
printResult(num,answer);
break;
case 2:
k=0;
printf("你已退出!");
break;
default:
printf("请输入正确的数字!\n");
break;
}
}
return 0;
}