问题描述:
24点游戏是经典的纸牌益智游戏。
常见游戏规则:
从扑克中每次取出4张牌。使用加减乘除,第一个能得出24者为赢。(其中,J代表11,Q代表12,K代表13,A代表1),按照要求编程解决24点游戏。
基本要求: 随机生成4个代表扑克牌牌面的数字字母,程序自动列出所有可能算出24的表达式,用擅长的语言(C/C++/Java或其他均可)实现程序解决问题。
1.程序风格良好(使用自定义注释模板)
2.列出表达式无重复。
提高要求:用户初始生命值为一给定值(比如3),初始分数为0。随机生成4个代表扑克牌牌面的数字或字母,由用户输入包含这4个数字或字母的运算表达式(可包含括号),如果表达式计算结果为24则代表用户赢了此局。
1. 程序风格良好(使用自定义注释模板)
2.使用计时器要求用户在规定时间内输入表达式,如果规定时间内运算正确则加分,超时或运算错误则进入下一题并减少生命值(不扣分)。
3.所有成绩均可记录在TopList.txt文件中。
算法分析
一、采用srand()和rand()配合使用随机生成1~13之间的四个数字,分别为a,b,c,d将4个整数放入数组num[ ]中
二、 在字符数组中存入 +– * / – -/运算符,分别对应flag的0,1,3,4,5。因为除法和减法不存在交换律,所以定义了反除和反减。
三、将用户输入的4个数字与4个运算符进行穷举组合排列,以构成多种不同的表达式,计算每一种表达式的值。
四、若表达式计算结果为24,则输入该表达式,程序运行结果输出所有可能性的排列组合
程序代码
// + - * / -- -/
// 0 1 2 3 4 5
#include <iostream>
#include<stdio.h>
#include<math.h>
#include <cstdlib>
#include <ctime>
using namespace std;
#define random(a,b) (rand() % (b-a+1))+ a //random的宏定义,便于rand()的计算
int calculate(float a,float b,float c,float d); //24点计算函数
float myF(int flag,float m,float n);
void myPrint(int type,int i,int j,int k,float a,float b,float c,float d);
int temp=0;
int main()
{
int i,j,k,t,again,res,flag;
float num[4]; //用于存放四个数字
srand((int)time(0)); // 产生随机种子 把0换成NULL也行
for (int i = 0; i < 4; i++)
{
num[i]= random(1, 13); //生成1-13间四个随机数存入num数组中
cout<<num[i]<<" "<<endl;
}
for (i=0;i<4;i++)
for (j=0;j<4;j++)
if (j!=i)
for (k=0;k<4;k++)
if (k!=j && k!=i)
for (t=0;t<4;t++)
if (t!=i && t!=j && t!=k) //循环对四个数字的计算进行组合
{
res=calculate(num[i],num[j],num[k],num[t]);
}
if (res==0)
printf ("\nNo answer\n");
return 0;
}
int calculate(float a,float b,float c,float d)
{
int i,j,k;
float sum1,sum2,sum3;
for (i=0;i<4;i++)
for (j=0;j<6;j++)
for (k=0;k<6;k++)
{
if ((!(i==3 && b==0)) && (!(j==3 && c==0)) && (!(k==3 && d==0)))
{
sum1=myF(i,a,b); // (((a#b)#c)#d)
sum2=myF(j,sum1,c);
sum3=myF(k,sum2,d);
if (fabs(sum3-24)<0.1)
{
temp++; //type==1
myPrint(1,i,j,k,a,b,c,d); //类型1的输出
}
}
if (k==2)
{
sum1=myF(i,a,b); //(a#b)*(c#d)
sum2=myF(j,c,d);
sum3=sum1*sum2;
if (fabs(sum3-24)<0.1)
{
temp++;
myPrint(2,i,j,k,a,b,c,d);
}
}
if (k==3)
{
sum1=myF(i,a,b); //(a#b)/(c#d)
sum2=myF(j,c,d);
if (sum2!=0)
{
sum3=sum1/sum2;
if (fabs(sum3-24)<0.1)
{
temp++;
myPrint(3,i,j,k,a,b,c,d);
}
}
}
}
if (temp==0) //没有能计算出24点的结果
return 0;
else
return 1;
}
float myF(int flag,float m,float n) //判断运算符功能
{
if (flag==0)
return (m+n);
if (flag==1)
return (m-n);
if (flag==2)
return (m*n);
if (flag==3)
if (n==0)
return 30000;
else
return (m/n);
if (flag==4) //反减
return (n-m);
if (flag==5) //反除
if (m==0)
return 30000;
else
return (n/m);
return 0;
}
void myPrint(int type,int i,int j,int k,float a,float b,float c,float d)
{
char sigle[6];
sigle[0]='+';
sigle[1]='-';
sigle[2]='*';
sigle[3]='/';
sigle[4]='-';
sigle[5]='/';
if (type==1){
if(j==4 || j==5)
{
if (k==4 || k==5)
printf("%2.0f %c (%2.0f %c (%2.0f %c %2.0f)) =24\n",d,sigle[k],c,sigle[j],a,sigle[i],b);
else
printf("(%2.0f %c (%2.0f %c %2.0f)) %c %2.0f =24\n",c,sigle[j],a,sigle[i],b,sigle[k],d);
}
else if (k==4 || k==5)
{
printf("%2.0f %c ((%2.0f %c %2.0f) %c %2.0f) =24\n",d,sigle[k],a,sigle[i],b,sigle[j],c);
}
else
printf("((%2.0f %c %2.0f) %c %2.0f) %c %2.0f =24\n",a,sigle[i],b,sigle[j],c,sigle[k],d);
}
if (type==2 || type==3)
{
printf("(%2.0f %c %2.0f) %c (%2.0f %c %2.0f) =24\n",a,sigle[i],b,sigle[k],c,sigle[j],d);
}
}
概要设计
概要设计
一、主函数程序流程图
二、Calculate函数流程图
calculat函数对四个数字a,b,c,d进行穷举,对每一种的运算结果进行判断,若等于24则该表达式是结果之一。
三、myF函数流程图
myF函数通过形参得到的flag值进行判断,从而进行相应的运算。
调试
测试
一、测试一:随机数产生测试
测试代码:
srand((int)time(0)); // 产生随机种子 把0换成NULL也行
for (int i = 0; i < 4; i++)
{
num[i]= random(1, 13); //生成1-13间四个随机数存入num数组中
}
测试结果:
可以看到,程序成功的生成了四个随机数,并且由于srand函数产生随机种子使得每次都可成功产生完全随机的数字。
二、测试主程序输出结果
测试代码:
int main()
{
int i,j,k,t,again,res,flag;
float num[4]; //用于存放四个数字
srand((int)time(0)); // 产生随机种子 把0换成NULL也行
for (int i = 0; i < 4; i++)
{
num[i]= random(1, 13); //生成1-13间四个随机数存入num数组中
cout<<num[i]<<" "<<endl;
}
for (i=0;i<4;i++)
for (j=0;j<4;j++)
if (j!=i)
for (k=0;k<4;k++)
if (k!=j && k!=i)
for (t=0;t<4;t++)
if (t!=i && t!=j && t!=k) //循环对四个数字的计算进行组合
{
res=calculate(num[i],num[j],num[k],num[t]);
}
if (res==0)
printf ("\nNo answer\n");
return 0;
}
测试结果:
程序成功将系统随机生成的数字1,3,5,13进行了穷举,列出了所有可能的表达式,根据验证,输出结果正确。
三、测试无法组成24点的数据
经过多次运行,对于系统随机生成的8,7,12,10这四个数据,无法组成24点,程序输出No answer运行正确。
心得体会
对于此次程序的编写,考虑到的因素较多,在没有思路的初期在网上借鉴了相关的算法思路,对题目的要求进行了分析,对需要的程序模块进行了分解,细化了问题的解法。使得程序的编写变得更为简单,同时学会了在c++中利用srand以及rand函数生成随机数的方法,更加深刻的认识到了程序设计的标准以及流程方法。对以后的学习打下基础。