中小学数学卷子自动生成程序——结对编程队友互评

一、题目介绍

本博客是对结对编程队友严同学编写的个人项目的分析评价,编写语言为C++。项目要求实现生成小学、初中和高中难度的题目,题目数量范围在10~30,每次生成的题目数量可自行选择并产生在相应的文件夹中。

二、代码分析

整个项目由一个cpp文件组成,定义了一个User类,通过该类实现项目的功能调用:

User类

class User {
	public:
		void Sign_In();			//登录 
		void Create_Exam();		//生成试卷 
		void Create_File();		//生成文件 
		void Change_Type();		//转换试卷类型 
		bool Check_Topic(); 	//检查是否题目重复 
		
	private:
		string name;		//用户名 
		string passward;	//密码 
		string type;		//用户年级类型 
		string folder_path; //文件夹路径 
		string path;        //.txt文件路径 
		int num; 			//题目数目 
		bool state;		    //登录状态 
		stringstream topic; //临时保存题目 
		string all_topic;   //题目合集 
};

用户登录

void User::Sign_In() { //用户登录 
	while(1) {
		cout<<"请输入用户名和密码,两者之间用空格隔开:"<<endl;
		cin>>name>>passward;
		if(passward=="123") {
			state=1;
			if(name=="张三1" || name=="张三2" || name=="张三3")
				type="小学";
			else if(name=="李四1" || name=="李四2" || name=="李四3")
				type="初中";
			else if(name=="王五1" || name=="王五2" || name=="王五3")
				type="高中"; 
			
			cout<<"登录成功!"<<endl; 
			Change_Type(); 
		} 
		else
			cout<<"请输入正确的用户名、密码"<<endl;
	}
}

生成文件

void User::Create_File() { //生成文件
	folder_path="./"+name; //文件夹路径 
	if(access(folder_path.c_str(),0)!=0)
        mkdir(folder_path.c_str());
	
	char filename[30];
	struct tm *ptr;
	time_t t=time(NULL);
	ptr=localtime(&t);
	strftime(filename,30,"%y-%m-%d-%H-%M-%S.txt",ptr); //将文件以"年-月-日-时-分-秒.txt"的形式保存
	path=name+"\\"+filename; //生成.txt文件的路径
}

生成试卷

void User::Create_Exam() { //生成试卷 
	cout<<"准备生成"<<type<<"数学题目,请输入生成题目数量(范围10~30,-1退出当前用户):"<<endl;
	cin>>num;
	if(num==-1){
		system("cls");
		cout<<"退出登录成功"<<endl;
		state=0; 
		return;
	}
	while(num<10 || num>30) {
		cout<<"生成失败,题目数量范围10~30,请重新输入:"<<endl;
		cin>>num;
	}
	ofstream write;
	write.open(path.c_str()); //创建文件打开 
	write<<type<<"数学,共"<<num<<"题"<<endl<<endl;
	int N=num;
	while(N!=0) {
		N--;
		int operand; //操作数个数 
		if(type=="小学")
			operand=rand()%4+2; 
		else
			operand=rand()%5+1;
		if(operand==1) //减少仅有一个操作数的几率 
			operand+=rand()%5;
		int op=operand;
		int bracket_left=0;	//括号开始位置 
		int bracket_size=0;	//括号内操作数个数 
		
		if(operand>2 && rand()%2==1) { //1/2几率生成有括号题目
			if(operand==3){ //操作数个数为3时两种括号生成情况 
				bracket_left=rand()%2+1;
				bracket_size=2;
			} 
			else if(operand==4) { //操作数个数为4时 
				bracket_left=rand()%3+1;
				if(bracket_left==3) //左括号在第3个操作数前时 
					bracket_size=2; //左括号在第1或第2个操作数前时
				else
					bracket_size=rand()%2+2;
			}
			else if(operand==5) { //操作数个数为5时 
				bracket_left=rand()%4+1;
				if(bracket_left==4) //左括号在第4个操作数前时 
					bracket_size=2;
				else if(bracket_left==3) //左括号在第3个操作数前时			
					bracket_size=rand()%2+2;
				else //左括号在第1或第2个操作数前时
					bracket_size=rand()%3+2;	
				}			
		}
		bool flag=0; //初中题目是否有平方/根号,高中题目是否有三角函数
		while(op!=0) {
			int value=rand()%100+1; //随机生成操作数的值 
			op--;
			if(op==operand-bracket_left)
				topic<<"(";
				int choose; //运算符选择,1、2为平方根号,3、4、5为sin,cos,tan 
				if(type=="小学")
					choose=0;
				else if(type=="初中") {
					choose=rand()%4;
					if(choose!=0) //至少有一个平方或根号了
						flag>1;
					if(op==0 && flag==0) //到最后一个操作数都没有平方或根号 
						choose=rand()%2+2;
				} 
				else if(type=="高中") {
					choose=rand()%7;
					if(choose>3) //至少有一个三角函数 
						flag=1;
					if(op==0 && flag==0)
						choose=rand()%3+4; //到最后一个操作数都没有三角函数 
				}
			
			if(choose==0 || choose==1) //操作数加上初中高中运算符 
			 	topic<<value;
			else if(choose==2)
				topic<<"√"<<value;
			else if(choose==3)
				topic<<value<<"^2";
			else if(choose==4)
				topic<<"sin"<<value;
			else if(choose==5)
				topic<<"cos"<<value;
			else if(choose==6)
				topic<<"tan"<<value;
			
			if(op==operand-bracket_left-bracket_size+1) //加右括号 
				topic<<")"; 
			
			if(op!=0) {
				choose=rand()%4; //choose为1、2、3、4对应加减乘除 
				if(choose==0)
					topic<<"+";
				else if(choose==1)
					topic<<"-";
				else if(choose==2)
					topic<<"×";
				else if(choose==3)
					topic<<"÷";
			} 
			else
				topic<<"=";
		}
		if(Check_Topic()) {
			write<<num-N<<"、"<<topic.str()<<endl<<endl;
			topic.str(""); //清空topic 
		}
		else
			N++;
	}
	write.close(); 
	cout<<"已成功生成"<<type<<"数学试卷!"<<endl<<endl; 
}

切换题目类型

void User::Change_Type() { //切换题目类型
	string change;
	char flag;
	
	while(state) {
		cout<<"-----------当前选择为"<<type<<"出题-----------"<<endl;
		cout<<"-----------是否切换出题类型?(y/n)----------"<<endl;
		cin>>flag;
		if(flag=='y') {
			cout<<"请输入要转换的类型:";
			while(1) {
				cin>>change;
				if(change!="小学" && change!="初中" && change!="高中")
					cout<<"转换失败!请输入正确的类型:";
				else {
					type=change;
					break;
				}
			}
		}
		Create_File();
		Create_Exam();	
	}
}

查重

bool User::Check_Topic() {
	string check_path=name+"\\Check_Topic.txt";  
	fstream check;
	check.open(check_path.c_str(),ios::in|ios::app); //生成Check_Topic.txt文件 
	stringstream ss;
	ss<<check.rdbuf();
	all_topic=ss.str();	//将Check_Topic.txt文件的题目读到all_topic中用来判断是否有题重复 
	if(all_topic.find(topic.str())==string::npos) {	//没有重复 
		check<<topic.str();	//更新Check_Topic文件 
		return 1;
	}
	return 0;
} 

main

int main() {
	User user;
	srand((unsigned)time(NULL)); // 产生随机数种子 
	
	user.Sign_In();
	return 0;
}

代码观看感受:

1、整个项目结构清晰,函数功能简洁实用,必要地方使用注释,极好地缩短分析时间,缩进和变量名的命名都按照了Google的编码规范执行;
2、文件输出部分使用相对路径,保证能正常输出结果且方便后期查看输出的题目;
3、在终端运行的界面也较为人性化,合理的操作提示,让使用者用的很舒服。

三、代码运行测试

用户登录,生成初始难度题目

切换难度,生成高中难度题目

程序使用感受:

具体使用下来,除了每次操作都会询问是否切换难度,会导致使用时有点糟心,其他的都是完成的非常好的。

posted @   monster_t  阅读(218)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示