递归实现四则混合运算随机出题

大一大作业出题中有一个小学生随机出题系统,刚好学习了随机函数,就选择这个,结果上手后才发现不是这么简单,最终耗时挺久终于完成了最难的出题模块,分享给大家

#include <bits/stdc++.h>
using namespace std;
void numcraet(double t);
void title(char s1,char s2,int t1,int t2,int t3,int t4);
char pcreat();
void numscreat(double t);

int p=0;
int m;
int main()
{
	int z,M,N;
	char a;
	srand(time(0));
	printf("请输入页数\n");
	cin>>M;
	printf("请输入每页题目数\n");
	cin>>N;
	int t;
	for(int i=1;i<=M;i++)
	{
		for(int j=1;j<=N;j++)
		{   
		    z=1+rand()%2;//z==1or2 
			t=rand()%2;//t==0or1 
			if(t==1)//t 用来随机决定生成哪种类型 
	        title('(',a,z,z,0,0);//
	        else if(t==0)//
	        title(a,a,z,z,1,0);//
	        cout<<'='<<' '<<' '<<' '<<' ';//
		}
		cout<<endl;
	}
	return 0;
}
void titlecreat() 
{
	char a;
	int z,t;
	z=1+rand()%3;//决定生成几个括号 
	t=rand()%2;//决定首先是否生成括号 
	if(t==1) title('(',a,z,z,0,0);
	else if(t==0) title(a,a,z,z,1,0);//z是括号个数 
	cout<<'=';
} 


int numcreat()//生成数字
{
    return 1+rand()%100;
}


char pcreat()//生成运算符
{
	int t;
	t=rand()%4;
	if(t==0) return '+';
	if(t==1) return '-';
	if(t==2) return '*';
	if(t==3) return '/';
}


void numscreat()//生成单个运算
{
	int num;
	char s;
	num=numcreat();
	cout<<num;
	s=pcreat();
	cout<<s;
	num=numcreat();
	cout<<num;
}


void title(char s1,char s2,int t1,int t2,int t3,int t4) //t3,t4是现存左右括号 
{
    int m;
    m=0;
	int num;
	char s;
	int ta=rand()%2;//[0,1] 
    int tb=rand()%2;//随机 
    int tc=rand()%2;
    int td=rand()%2;
	char a;
	if(s1=='('&&t1>0)//如果s1==(,输出(,t1--。进入下一个函数 
	{
		p++;
		cout<<'(';
		t1--;
		title(a,a,t1,t2,1,0);
	}
	else if(s1==a)//s1不为(有两种情况. 
	{
		if(t3==1)//t3==1
		{
			numscreat();//生成一对运算 
			if(tb==1&&p>0)//决定 是否生成右括号 
			{
		    p--;
			title(a,')',t1,t2,0,0);
		    }
			else title(a,a,t1,t2,0,1);
		}
		else if(t4==1)//t4==1
		{
		    s=pcreat();
		    cout<<s;
		    if(s=='/') m=1;
		    if(tc==0&&t1>0&&m==0) title('(',a,t1,t2,0,0);//决定是否生成左括号 
		    else title(a,a,t1,t2,1,0);
		}
	}
	if(s2==')')
	{
		t2--;
		cout<<')';
		if(t2==0)
		{
			s=pcreat();
			cout<<s;
    	    num=numcreat();
    	    cout<<num;
    	    return;
		}
		else
		{
			s=pcreat();
			cout<<s;
			if(s=='/') m=1;
			if(td==0&&t1>0&&m==0) title('(',a,t1,t2,0,0);//决定是否生成左括号 
		    else title(a,a,t1,t2,1,0);
		}
	}
}             

输出结果如下:

 

如上图,逻辑有点复杂,下面是解析:

首先要知道,一个混合四则运算包括什么:数字,运算符,括号。按照顺序将他们拼接在一起就能得到一个运算。

再进一步,我们将数字和运算符组合成单个运算,即代码中的numscreate模块(代码中的单词拼错了)(狗头),numscreate模块由pcreate和numcreate组成。

再进一步,如果我们将单个运算组合起来,其中穿插括号,就能得到一个四则混合运算了。

可是困难的是如何将他们组合起来,并让其中穿插括号。一番思考之后,自然地想到了递归,简直和递归完美契合(哈哈)。

我们设置一个值,假如是p1,我们给他赋一个随机值,代表递归层数,每次递归减一,到零为止。可以表示运算的长短。

假设一个t1,判断是否生成括号,设置一个t2,判断生成括号是否合法(可以参考力扣20题,有效的括号)。

这样就可以将括号和单个运算组合起来了。

最后是细节处理,一个是除法不能除零,有时候括号也不允许(括号内可能为零),可以加入一个判断,如果随机生成了除法就不能在后面生成括号,零懒得搞了,就规定随机数不生成零(聪明)。还有一个是可能生成类似与  (3+5)=  这样的运算,为了美观决定再最后加一个运算符和数字(所以最后生成的都是奇数个数字)

优化点:无法实现去重

代码就是按照这个思路写的,如果想深入了解,可读一下代码

大一萌新,如有错误,敬请指正,如果觉得对你有帮助,请点一个赞哦(⊙o⊙)?

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值