经典纸牌益智游戏--24点游戏

作者:无*
时间: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;第二部分就比较复杂,运用了栈来实现表达式求值,此处代码比较复杂,我是进行了多个代码的参考才得出的,最后还需要对表达式结果进行判断,此处应该注意初始值的设定计时器的正确运用。
心得:
此次编写过程中遇到的问题还比较多,栈的编写还参考了资料,前几次的穷举尝试中没有考虑全面,没有注意到括号的优先级等问题,导致程序出错,后来在不断的调试和修改下,基本完成了要求,但是觉得提高要求部分还有待改进。但总体来说,通过这次的编程,对栈和穷举法有了更深的理解,也学会了要巧妙地简化程序,是程序达到更优化,让用户一目了然。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值