24点游戏

题目分析
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文件中。
算法设计
流程图:
在这里插入图片描述

程序源码
基本要求:

//author :lyq
//time :2019-4-9
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<ctime> 
#include<string>
using namespace std;
int n=4;//一共四个数字 
int number[4]={0};//存储4个数字
string s[4];//用于记录运算表达式的字符串数组 
int count=0;//用于记录得到24点的表达式个数 
string c[100];//记录符合的表达式的字符串数组 
int f(int n)
{
 
if(n==1)//完成三次运算
{
	if(number[0]==24)//结果为24 
	{	
		cout<<s[0]<<endl;//输出得到24的表达式 
		c[count]=s[0];
		count++;
		return 1;
	} 
	else
		return 0;
}
//从数组中任意取出两个数的组合 
for(int i=0;i<n;i++)
{
	for(int j=i+1;j<n;j++)
	{
		double a,b;
		string x,y;
		a=number[i];
		b=number[j];
		number[j]=number[n-1];//将最后一位的赋给空出来的j 		
		x=s[i];
		y=s[j];
		s[j]=s[n-1];//最后一位的数字放入第j个 
		//加法 
		number[i]=a+b;//第一个空间保存前两个的运算结果 
		s[i]='('+x+'+'+y+')';//将第一步的运算结果存入数组 
		f(n-1);
		
		//减法;分顺序 
		number[i]=a-b;
		s[i]='('+x+'-'+y+')';
		f(n-1);
		
		number[i]=b-a;
		s[i]='('+y+'-'+x+')';
		f(n-1);
		//乘法 
		number[i]=a*b;
		s[i]='('+x+'*'+y+')';
		f(n-1);
		//除法;分顺序, 注意分母为零的情况 
		if(b!=0)
		{
			number[i]=a/b;
			s[i]='('+x+'/'+y+')';
			f(n-1);
		}
		if(a!=0)
		{
			number[i]=b/a;
			s[i]='('+y+'/'+x+')';
			f(n-1);
		}
		//当以上的运算都无法得到24的结果时,还原数据,进行下一个循环 
		number[i]=a;
		number[j]=b;
		s[i]=x;
		s[j]=y;
	
	}
	 
}
}
int get(int begin, int end )
{
        return rand()%(end-begin+1)+begin;
}
int main()
{
	srand((unsigned int)time(NULL));//根据当前时间产生随机种子 
	cout<<"生成的四个随机数如下:"<<endl;
    for (int i = 0; i < 4; ++i) //生成4个1~13之间的数字
	{ 
        number[i]=get(1,13);
		cout<<number[i]<<" "; 
    }
    cout<<endl;
	for(int i=0;i<4;i++){
		if(number[i]==1)
			s[i]='A';
		else if(number[i]==11) 
			s[i]='J';
		else if(number[i]==12) 
			s[i]='Q';
		else if(number[i]==13) 
			s[i]='K';
		else s[i]='0'+number[i];
	} 
	f(n);
	return 0;
}
提高要求:
//author :lyq
//time :2019-4-9
#include<iostream>
#include<fstream>
#include<cstdlib>
#include<cmath>
#include<ctime> 
#include<string>
using namespace std;
int n=4;//一共四个数字 
int number[4]={0};//存储4个数字
string s[4];//用于记录运算表达式 
int count=0;//用于记录得到24点的表达式个数 
string c[1000];//记录符合的表达式的字符串数组 
int f(int n)
{
	 
	if(n==1)//完成三次运算
	{
		if(number[0]==24)//结果为24 
		{	
//			cout<<s[0]<<endl;//输出得到24的表达式 
			c[count]=s[0];//记录可以得到24的表达式字符串 
			count++;
			return 1;
		} 
		else
			return 0;
	}
	//从数组中任意取出两个数的组合 
	for(int i=0;i<n;i++)
	{
		for(int j=i+1;j<n;j++)
		{
			double a,b;
			string x,y;
			a=number[i];
			b=number[j];
			number[j]=number[n-1];//将最后一位的赋给空出来的j 		
			x=s[i];
			y=s[j];
			s[j]=s[n-1];//最后一位的数字放入第j个 
			//加法 
			number[i]=a+b;//第一个空间保存前两个的运算结果 
			s[i]='('+x+'+'+y+')';//将第一步的运算结果存入数组 
			f(n-1);
			
			//两种减法 
			number[i]=a-b;
			s[i]='('+x+'-'+y+')';
			f(n-1);
			
		number[i]=b-a;
		s[i]='('+y+'-'+x+')';
		f(n-1);
		//乘法 
		number[i]=a*b;
		s[i]='('+x+'*'+y+')';
		f(n-1);
		//两种除法, 注意分母为零的情况 
		if(b!=0)
		{
			number[i]=a/b;
			s[i]='('+x+'/'+y+')';
			f(n-1);
		}
		if(a!=0)
		{
			number[i]=b/a;
			s[i]='('+y+'/'+x+')';
			f(n-1);
		}
		//当以上四则运算的结果都不能满足条件时
		//为了方便进入下一个for循环, 需要将之前的i和j上的值都重新找回 
		number[i]=a;
		number[j]=b;
		s[i]=x;
		s[j]=y;
	
	}
	
	}
}
int get(int begin,int end)//获取随机数 
{
        return rand()%(end-begin+1)+begin;
}
int main()
{
	int life=3;//初始升,生命值为3 
	int score=0;//用户得分,每正确一次加十分 
	string a;//定义输入的字符串 
	srand((unsigned int)time(NULL));
cout<<"生成的四个随机数如下:"<<endl;
	for(int i = 0; i < 4; ++i) //生成4个1~13之间的数字
		{ 
        	number[i]=get(1,13);
			cout<<number[i]<<" "; 
    	}
		
		cout<<endl;
	
for(int i=0;i<4;i++)//将11~13改成相应的扑克牌符号 
{
	if(number[i]==1) 
		s[i]='A';
	else if(number[i]==11) 
		s[i]='J';
	else if(number[i]==12) 
		s[i]='Q';
	else if(number[i]==13) 
		s[i]='K';
	else 
		s[i]='0'+number[i];
} 
f(n);//调用函数 
while(life)//当生命值不为零时循环 
{
	
	cout<<"请输入你的表达式!"<<endl;
	double start=clock();//开始时间 
	cin>>a; 
	double end=clock();//结束时间 
	double time;
	time=(double)(end-start)/CLOCKS_PER_SEC;//输入所花费的总时间 
	if(time>48.0)//当超过48秒时间时,进行下一轮游戏 
	{
		cout<<"你超时了!"<<endl;
		life-=1;
		cout<<"剩余生命值为:"<<life<<endl; 
		continue;
	} 
	int k;
	for(k=0;k<count;k++)
	{
		if(a==c[k])//输入的字符串表达式符合相应的情况
		{
		 	score+=10; 
			cout<<"恭喜!你输入的表达式成功得到了24!,成功加十分!"<<endl;
			break; 
		} 
		
	} 
	if(count==k)//输入表达式无法得到24的结果,进行下一轮的游戏 
	{
		cout<<"sorry!游戏失败!"<<endl;
		life-=1;
		cout<<"剩余生命值为:"<<life<<endl;
		continue;
		cout<<endl;
	}			 
} 
ofstream out;
out.open("E://TopList.txt");//每次的得分记录在文件中 
out<<"此次测试得分为:"<<score<<endl; 
return 0;

}
调试与测试
调试:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
测试:
基本要求:

在这里插入图片描述

在这里插入图片描述
提高:

在这里插入图片描述

在这里插入图片描述
总结:

这次的24点游戏,一开始的想法是进行穷举法,将所有情况都列举出来进行结果判断,如果结果为24,则将其输出,后来发现简单的for循环穷举对于括号的考虑是个问题,对此需要进行多种括号分类的列举与处理。后来一想,为什么不每次取两个数进行加减乘除的运算,将结果又与下一个数重复此过程,直到四个数都已在计算中使用过了,而每次都将运算表达式两侧加上括号,也就不用单独处理括号的问题了。

此次作业还是有些不足之处,自己的能力还是不够,需要继续提升。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值