四则运算2:
1、题目避免重复;
2、可定制(数量/打印方式);
3、可以控制下列参数: 是否有乘除法; 是否有括号(最多可以支持十个数参与计算);数值范围;加减有无负数;除法有无余数。
一,设计思想
把一些参数设置成全局变量,方便各个函数使用,避免实参虚参搞丢了参数。在主函数里获取了参数之后将主要功能模块另写在一些函数里。利用时间种子生成随机数,随机数的范围利用全局参数控制,利用string数组来储存生成的每一道题目,生成题目的最后一步应该有一个检验过程,就是遍历之前的字符串数组,如果有一样的就不储存,继续生成。最后输出字符串。
二,程序代码
#include<stdlib.h> #include<conio.h> #include<time.h> #include<iostream> #include<string> #include<cstring> #include<iomanip> using namespace std; //全局参数变量设置 int QstNum,IfIncMD,IfIncBrackets,range,IfNeg,IfRem,IfFraction; //题目数量 是否有乘除 是否有括号 数值范围 是否能有负数 是否能有余数 是否有分数 string a[1000];//用于储存题目 void ParaSet()//参数设置 { cout<<"请输入生成的四则运算题个数(1-1000):"; cin>>QstNum; while(QstNum<0&&QstNum>1000) { cout<<"请重新输入生成的四则运算题个数(1-1000):"; cin>>QstNum; } //是否有乘除法 cout<<"是否有乘除法:(1/0)"; cin>>IfIncMD; while(IfIncMD>1||IfIncMD<0) { cin>>IfIncMD; } //是否支持有括号 cout<<"是否随机生成括号:"; cin>>IfIncBrackets; while(IfIncBrackets!=1&&IfIncBrackets!=0) { cout<<"请输入1或0:(1随机生成括号,0不随机生成括号)"; cin>>IfIncBrackets; } //整数数值范围 cout<<"整数数值范围:(1000以内,100以内,10以内)"; cin>>range; while(range!=10&&range!=100&&range!=1000) { cout<<"请输入10,100,或1000:"; cin>>range; } //加减是否支持负数的存在 cout<<"加减是否允许有负数的存在(输入1则允许,0则不允许):"; cin>>IfNeg; while(IfNeg!=1&&IfNeg!=0) { cout<<"请输入1或0(输入1则允许否则不允许):"<<endl; cin>>IfNeg; } //除法是否允许有余数的存在 cout<<"除法是否允许有余数的存在(输入1则允许,0则不允许):"; cin>>IfRem; while(IfRem!=1&&IfRem!=0) { cout<<"请输入1或0(输入1则允许否则不允许):"<<endl; cin>>IfRem; } //整数除法是否允许有分数的存在 cout<<"整数除法是否允许有分数的存在(输入1则允许,0则不允许):"; cin>>IfFraction; while(IfFraction!=1&&IfFraction!=0) { cout<<"请输入1或0(输入1则允许否则不允许):"<<endl; cin>>IfFraction; } } void Digit(int i,string a[],int Location)//数字转变为字符 { if(i/100!=0) { a[Location]+=(char)(i/100+48); } if(i%100/10!=0) { a[Location]+=(char)(i%100/10+48); } a[Location]+=(char)(i%10+48); } void DealDigit(string a[],int p,int range,int IfNegative,int IfFraction,int x) { int RandomNum1=(int)rand()%100/50;//是否产生负数的随机数 int RandomNum2=(int)rand()%100/50;//是否产生分数的随机数 x=(int)rand()%range;//分子 int z=(int)rand()%range;//分母 if(IfNegative==1)//随机生成数字 { if(RandomNum1==1&&RandomNum2==1)//随机生成负分数 { a[p]+='('; a[p]+='-'; Digit(x,a,p); a[p]+='/'; Digit(z,a,p); a[p]+=')'; } else if(RandomNum1==1&&RandomNum2!=1)//负数 { a[p]+='('; a[p]+='-'; Digit(x,a,p); a[p]+=')'; } else//数字默认为正数 { Digit(x,a,p); } } else//正数 { if(IfFraction==1)//随机生成正分数 { if(RandomNum2==1) { a[p]+='('; Digit(x,a,p); a[p]+='/'; Digit(z,a,p); a[p]+=')'; } } else//默认为正数 { Digit(x,a,p); } } } bool IfRepeated(int CurLocation,string a[])//是否重复 { for(int p=0;p<CurLocation;p++) { for(int q=0;a[p][q]!='=' && a[CurLocation][q]!='=';q++) { if(a[p][q]!=a[CurLocation][q]) p++; if(a[p][q]=='='&&a[CurLocation][q]=='=') return true; } } return false; } void Deal()//生成题目 { for(int p=0;p<QstNum;p++) { int count=0; int FirstNum=0,SecNum=0;//生成的相邻的两个操作数 int RandomNum1,RandomNum2,RandomNum3,RandomNum4; int OperandNum=(int)rand()%10/5+2;//操作数的个数,属于二元或三元运算 int Brackets=(int)rand()%100/50;//随机生成括号 int z;//分母 if(Brackets==1&&count==0&&OperandNum>2&&IfIncBrackets==1)//判断是否生成括号 { a[p]+="("; count++; } DealDigit(a,p,range,IfNeg,IfFraction,FirstNum);//生成第一个数 for(int q=1;q<OperandNum;q++) { int Operator=(int)rand()%100/25;//操作符的范围 if(IfIncMD==0) Operator/=2;//操作符范围设置只有"+-"; switch(Operator) { case 0: a[p]+='+'; DealDigit(a,p,range,IfNeg,IfFraction,SecNum); break; case 1: a[p]+='-'; DealDigit(a,p,range,IfNeg,IfFraction,SecNum); break; case 2: a[p]+='*'; DealDigit(a,p,range,IfNeg,IfFraction,SecNum); break; case 3: a[p]+='/'; RandomNum1=(int)rand()%100/50;//是否产生负数的随机数 RandomNum2=(int)rand()%100/50;//是否产生分数的随机数 SecNum=(int)rand()%range;//分子 z=(int)rand()%range; if(IfNeg==1)//随机生成数字 { if(RandomNum1==1&&RandomNum2==1)//随机生成负分数 { a[p]+='('; a[p]+='-'; Digit(SecNum,a,p); a[p]+='/'; Digit(z,a,p); a[p]+=')'; } else if(RandomNum1==1&&RandomNum2!=1)//负数 { a[p]+='('; a[p]+='-'; Digit(SecNum,a,p); a[p]+=')'; } else//数字默认为正数 { Digit(SecNum,a,p); if(IfRem==0) { if(IfIncBrackets==0)//当不生成括号时 { if(FirstNum%SecNum!=0)//除法有余数 { Digit(SecNum,a,p); } } } } } else//正数 { if(IfFraction==1)//随机生成正分数 { if(RandomNum2==1) { a[p]+='('; Digit(SecNum,a,p); a[p]+='/'; Digit(z,a,p); a[p]+=')'; } } else//默认为正数 { Digit(SecNum,a,p); if(IfRem==0) { if(IfIncBrackets==0)//当不生成括号时 { if(FirstNum%SecNum!=0)//除法有余数 { Digit(SecNum,a,p); } } } } } break; } if(Brackets==1&&count==1&&q==1) { a[p]+=")"; } FirstNum=SecNum;//将运算符左侧数置为FirstNum } a[p]+='='; //判断是否重复,重复则重新生成 if(IfRepeated(p,a)) { p--; } } } void Display()//打印题目 { int count1=0; int p; for(p=0;p<QstNum;p++) { cout<<a[p]; count1++; cout<<endl; } } void main()//主函数 { srand((unsigned)time(NULL)); int p;//程序运行选择器 do { ParaSet();//参数设置 Deal();//核心函数,生成算术题的 Display();//打印题目 //是否继续 cout<<endl<<endl; cout<<"是否继续生成运算题(输入1则生成否则不生成):"<<endl; cin>>p; while(p!=1&&p!=0) { cout<<"请输入1或0(输入1则生成否则不生成):"<<endl; cin>>p; } }while(p==1); cout<<"OVER!"<<endl; }
三,运行截图
四,项目计划日志
日期/任务 | 课堂 | 编程 | 读书 | 博客 | 日总结 |
3.14 | 100min | 30min | 30min | 0 | 130min |
3.15 | 1h | 1h | |||
3.16 | 1h | 1h | |||
3.17 | 1h | 1h | |||
3.18 | 1h | 1h | |||
3.19 | 3h | 3h | |||
周总结 | 100 | 450min | 550m |
五,时间记录日志
日期 | 开始时间 | 结束时间 | 净时间 | 活动 | 备注 |
3.14 | 8:00,19:00 | 10:00,19:30 | 130 | 上课,编程 | |
3.15 | 19:00 | 20:00 | 1h | 编程 | |
3.16 | 19:00 | 20:00 | 1h | 编程 | |
3.17 | 19:00 | 20:00 | 1h | 编程 | |
3.18 | 19:00 | 20:00 | 1h | 编程 | |
3.19 | 14:00 | 17:00 | 3h | 编程 |
六,缺陷记录日志
日期 | 编号 | 类型 | 引入 | 排除 | 修复时间 | 修复 |
3.16 | 1 | 数组溢出 | 编译 | 40min | Y | |
3.19 | 2 | 一些测试例子输入后产生了不正确的结果 | 编译 | 1H | N |
七,仍然存在的问题
一组参数如果输入否就会产生参与计算的数值丢失