作者:无*
时间:2019-4-10
说明:此代码中的穷举法参考了资料,结合之后采用了一种较为易懂的穷举法
一.题目分析:
24点游戏(经典的纸牌益智游戏)
*基本要求:
- 随机生成4个代表扑克牌牌面的数字字母,程序自动列出所有可能算出24的表达式。
1.利用随机函数产生四个随机数,可利用数组进行存储。
2.利用穷举法列出所有括号的情况共五种
(1). ((A□B)□C)□D (2). (A□(B□C))□D (3). A□(B□(C□D)) (4).
A□((B□C)□D) (5). (A□B)□(C□D)
*
提高要求:
*用户初始生命值为一给定值(比如3),初始分数为0。随机生成4个代表扑克牌牌面的数字或字母,由用户输入包含这4个数字或字母的运算表达式(可包含括号),如果表达式计算结果为24则代表用户赢了此局。
1.此处使用栈进行表达式求值,并设置时间,在规定时间内输入表达式且答对可加分,如果超出时间,需要重新输入并且生命值减一。
2.利用文件的知识,将所得成绩和生命值存入文本文档之中。
二.算法构造:
*****基本要求:*****主要用到了 srand(time(NULL));随机种子产生rand( )%13+1;随机函数;其次就是利用穷举法分别写五个函数列出所有的情况。
提高要求:
1.利用栈的相关知识进行表达式求值
typedef struct //定义结构体 { SElemType *base; SElemType *top;
int stacksize; }SqStack; Status InitStack(SqStack &S){}//初始化 int
In(SElemType e)//判断读入字符是否为运算符
(此处代码比较复杂,参照了相关代码),
2.进行求值后,需要写计算时间的函数 clock_t start,end;并设定一个时间定值作为参照,当用户输入时间超过指定的时间,生命值value减一;否则,用户输入结果正确且在规定时间内,用户得分result++
三.源代码:
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define MAXSIZE 100
typedef int Status;
typedef char SElemType;
int value=3;
int result=0;
char op[5]={' ','+','-','*','/',};
float r1,r2,r3;
float choose(float x,float y,int op)
{ switch(op)
{ case 1: return x+y;
case 2: return x-y;
case 3: return x*y;
case 4: return x/y;
}
}
//穷举法
// ((A+B)-C)×D
float one(float i,float j,float m,float n,int a1,int a2,int a3)
{ r1 = choose(i,j,a1);
r2 = choose(r1,m,a2);
r3 = choose(r2,n,a3);
return r3; }
//(A+(B-C))×D
float two(float i,float j,float m,float n,int a1,int a2,int a3)
{ r1 = choose(j,m,a2);
r2 = choose(i,r1,a1);
r3 = choose(r2,n,a3);
return r3; }
// A+(B-(C×D))
float three(float i,float j,float m,float n,int a1,int a2,int a3)
{
r1 = choose(m,n,a3);
r2 = choose(j,r1,a2);
r3 = choose(i,r2,a1);
return r3; }
//A+((B-C)×D)
float four(float i,float j,float m,float n,int a1,int a2,int a3)
{
r1 = choose(j,m,a2);
r2 = choose(r1,n,a3);
r3 = choose(i,r2,a1);
return r3; }
//(A+B)-(C×D)
float five(float i,float j,float m,float n,int a1,int a2,int a3)
{
r1 = choose(i,j,a1);
r2 = choose(m,n,a3);
r3 = choose(r1,r2,a2);
return r3; }
function(int i,int j,int m,int n)
{
int a1,a2,a3;
for(a1=1;a1<=4;a1++)
for(a2=1;a2<=4;a2++)
for(a3=1;a3<=4;a3++)
{ if(one(i,j,m,n,a1,a2,a3)==24)
{ printf("((%d%c%d)%c%d)%c%d=24\n",i,op[a1],j,op[a2],m,op[a3],n); }
if(two(i,j,m,n,a1,a2,a3)==24)
{ printf("(%d%c(%d%c%d))%c%d=24\n",i,op[a1],j,op[a2],m,op[a3],n); }
if(three(i,j,m,n,a1,a2,a3)==24)
{ printf("%d%c(%d%c(%d%c%d))=24\n",i,op[a1],j,op[a2],m,op[a3],n); }
if(four(i,j,m,n,a1,a2,a3)==24)
{ printf("%d%c((%d%c%d)%c%d)=24\n",i,op[a1],j,op[a2],m,op[a3],n); }
if(five(i,j,m,n,a1,a2,a3)==24)
{ printf("(%d%c%d)%c(%d%c%d)=24\n",i,op[a1],j,op[a2],m,op[a3],n);}
}
}
typedef struct //定义结构体
{
SElemType *base;
SElemType *top;
int stacksize;
}SqStack;
Status InitStack(SqStack &S)//初始化
{
S.base=(SElemType*)malloc(sizeof(SElemType)*MAXSIZE);
if(!S.base)
exit(OVERFLOW);
S.top=S.base;
S.stacksize=MAXSIZE;
return OK;
}
Status Push(SqStack &S,SElemType e)//入栈
{
if(S.top-S.base==S.stacksize)
return ERROR;//栈满
*S.top++=e;//元素e压入栈顶,栈顶指针加1;
return OK;
}
Status Pop(SqStack &S,SElemType &e)//出栈
{
if(S.top==S.base)//栈空
return ERROR;
e=*--S.top;//栈顶指针减一,将栈顶元素赋给e;
return OK;
}
SElemType GetTop(SqStack S)//取栈顶元素
{
if(S.top!=S.base)//栈非空
return *(S.top-1);//返回栈顶元素的值,栈顶指针不变
}
int In(SElemType e)//判断读入字符是否为运算符
{
if(e=='+'||e=='-'||e=='*'||e=='/'||e=='('||e==')'||e=='#')
return 1;//是
else
return 0; //不是
}
SElemType Precede(SElemType a,SElemType b)//比较运算符的优先级
{
SElemType f;
if(a=='+'||a=='-')
{
if(b=='+'||b=='-'||b==')'||b=='#')
f='>';
else if(b=='*'||b=='/'||b=='(')
f='<';
}
else if(a=='*'||a=='/')
{
if(b=='+'||b=='-'||b=='*'||b=='/'||b==')'||b=='#')
f='>';
else if(b=='(')
f='<';
}
else if(a=='(')
{
if(b=='+'||b=='-'||b=='*'||b=='/'||b=='(')
f='<';
else if(b==')')
f='=';
}
else if(a==')')
{
if(b=='+'||b=='-'||b=='*'||b=='/'||b==')'||b=='#')
f='>';
}
else if(a=='#')
{
if(b=='+'||b=='-'||b=='*'||b=='/'||b=='(')
f='<';
else if(b=='#')
f='=';
}
return f;
}
SElemType Operate(SElemType a,SElemType theta,SElemType b)//运算
{
SElemType c;
a=a-'0';
b=b-'0';
if(theta=='+')
c=a+b+'0';
else if(theta=='-')
c=a-b+'0';
else if(theta=='*')
c=a*b+'0';
else if(theta=='/')
c=a/b+'0';
return c;
}
int EvaluateExpression()
{
SqStack OPND,OPTR;
char ch,a,b,theta,x;
InitStack(OPND);//寄存操作数和运算结果
InitStack(OPTR);//寄存运算符
Push(OPTR,'#');
ch=getchar();
while(ch!='#'||GetTop(OPTR)!='#') //输入表达式,以#结束
{
if(!In(ch))
{
Push(OPND,ch);
ch=getchar();
}
else
{
switch(Precede(GetTop(OPTR),ch))
{
case '<':
Push(OPTR,ch);
ch=getchar();
break;
case '>':
Pop(OPTR,theta);
Pop(OPND,b);
Pop(OPND,a);
Push(OPND,Operate(a,theta,b));
break;
case '=':
Pop(OPTR,x);
ch=getchar();
break;
}
}
}
return GetTop(OPND)-'0';
}
void choose1()
{ int num[4]; //数组存储四个随机数
srand(time(NULL)); //随机种子
printf("产生的四个随机数为");
for( int k=0;k<4;k++)
{num[k]=rand( )%13+1; //产生1~13的随机数
printf("%6d",num[k]);
}
printf("\n");
if(function(num[0],num[1],num[2],num[3]));
else
{printf("Sorry\n"); }
}
void choose2()
{ int ending;int sign=1;
clock_t start,end;
double time1;
int number;
int num[4]; //数组存储四个随机数
srand(time(NULL)); //随机种子
printf("产生的四个随机数为");
for( int k=0;k<4;k++)
{num[k]=rand( )%13+1; //产生1~13的随机数
printf("%6d",num[k]);
}
printf("\n");
while(sign){
printf("请输入算术表达式,并以#结束,注意只有30s思考时间\n");
start=clock();
ending=EvaluateExpression();
end=clock();
time1=(double)(end-start)/CLOCKS_PER_SEC;
printf("耗时%fs\n",time1); //计算耗时
if(time1<30)
{sign=0;}
printf("结果是: %d\n",ending);
if(ending==24) //如果结果等于24,得分加一
{result++;
}
else {printf("计算结果不是24\n"); //计算结果不是24,生命值减一
value--;}
printf("*****你当前的生命值为: %d 得分为:%d\n",value,result);
}
FILE *fp;
fp=fopen("TopList.txt","a"); //存储用户信息的文件
if(!fp)
printf("\n打开文件TopList.txt失败!");
fprintf(fp,"生命值为%d 得分为%d \n",value,result); //将用户名和用户的成绩存入TopList文件中
printf("\n");
fclose(fp); //关闭文件
}
int main()
{ int choose;
while(1){printf("*****请选择你要进行的操作*****\n");
printf("*****1.结果显示*****\n");
printf("*****2.开始24点游戏*****\n");
scanf("%d",&choose);
switch(choose)
{ case 1:{choose1();break;} //功能1
case 2:{choose2();break;} //功能2
}
}
if(value==0)
printf("游戏结束");
return 0;
}
四.调试,测试及运行结果
1.调试:
2.测试:
(1)基本要求代码和运行结果:
(2)提高要求代码和运行结果:
(3)写入文件代码
3.运行结果:
(1)选择“结果显示”,产生随机数并列出所有可能等于24的情况
(2)选择“开始24点游戏”,并将成绩写入文本文档中
五.经验归纳及心得:
经验归纳:
此次程序主要是实现一个纸牌益智类游戏—24点游戏,此程序大致可分为两部分,第一部分就是基本要求,基本要求的主要思想就是穷举法,重点就在于考虑括号的优先级和几种情况,经过推算和资料的参考,可以简化为五种。还有就是要注意随机函数的产生,不包括产生0;第二部分就比较复杂,运用了栈来实现表达式求值,此处代码比较复杂,我是进行了多个代码的参考才得出的,最后还需要对表达式结果进行判断,此处应该注意初始值的设定计时器的正确运用。
心得:
此次编写过程中遇到的问题还比较多,栈的编写还参考了资料,前几次的穷举尝试中没有考虑全面,没有注意到括号的优先级等问题,导致程序出错,后来在不断的调试和修改下,基本完成了要求,但是觉得提高要求部分还有待改进。但总体来说,通过这次的编程,对栈和穷举法有了更深的理解,也学会了要巧妙地简化程序,是程序达到更优化,让用户一目了然。