个人项目对方代码分析(随机生成不同难度试卷)
这次的个人项目着实让我知道了为什么程序猿毛发稀疏~(哭),在经历了写代码的血与泪之后,看我搭档的代码不禁感慨,哇塞~她的代码真的好短小精悍,让人心情愉悦~相反,我的代码让人看起来就想扶额(嘤~)。下面我们就来一起欣赏我搭档的代码吧(应老师的要求,还要找找茬😂)~~~~
题目:
1、命令行输入用户名和密码,两者之间用空格隔开(程序预设小学、初中和高中各三个账号,具体见附表),如果用户名和密码都正确,将根据账户类型显示“当前选择为XX出题”,XX为小学、初中和高中三个选项中的一个。否则提示“请输入正确的用户名、密码”,重新输入用户名、密码;
2、登录后,系统提示“准备生成XX数学题目,请输入生成题目数量:”,XX为小学、初中和高中三个选项中的一个,用户输入所需出的卷子的题目数量,系统默认将根据账号类型进行出题。每道题目的操作数在1-5个之间,操作数取值范围为1-100;
3、题目数量的有效输入范围是“10-30”(含10,30),程序根据输入的题目数量生成符合小学、初中和高中难度的题目的卷子(具体要求见附表)。同一个老师的卷子中的题目不能与以前的已生成的卷子中的题目重复(以指定文件夹下存在的文件为准,见5);
4、在登录状态下,如果用户需要切换类型选项,命令行输入“切换为XX”,XX为小学、初中和高中三个选项中的一个,输入项不符合要求时,程序控制台提示“请输入小学、初中和高中三个选项中的一个”;输入正确后,显示“”系统提示“准备生成XX数学题目,请输入生成题目数量”,用户输入所需出的卷子的题目数量,系统新设置的类型进行出题;
5、生成的题目将以“年-月-日-时-分-秒.txt”的形式保存,每个账号一个文件夹。每道题目有题号,每题之间空一行;
该代码流程图:
代码:
代码一共分为三个部分:user.h,generate.h,main.cpp;
1、user.h
1 #ifndef USER_H_ 2 #define USER_H_ 3 4 5 #include <iostream> 6 #include <string> 7 using namespace std; 8 9 extern int g_grade; 10 11 class user 12 { 13 private: 14 string name; 15 string password; 16 int grade; 17 18 public: 19 void users(string username, string userpassword, int usergrade) 20 { 21 name = username; 22 password = userpassword; 23 grade = usergrade; 24 } 25 26 bool IsCorrect(string username, string userpassword) 27 { 28 if (username==name && userpassword==password) return true; 29 else return false; 30 } 31 32 int Getgrade() 33 { 34 return grade; 35 } 36 }; 37 38 void UserData() 39 { 40 user users[9]; 41 users[0].users("张三1", "123", 1); 42 users[1].users("张三2", "123", 1); 43 users[2].users("张三3", "123", 1); 44 users[3].users("李四1", "123", 2); 45 users[4].users("李四2", "123", 2); 46 users[5].users("李四3", "123", 2); 47 users[6].users("王五1", "123", 3); 48 users[7].users("王五2", "123", 3); 49 users[8].users("王五3", "123", 3); 50 51 cout << "请输入用户名和密码" << endl; 52 string name, password; 53 while (1) 54 { 55 cin >> name >> password; 56 int is_correct = 0; 57 for (int i=0; i<9; i++) 58 { 59 if (users[i].IsCorrect(name, password) == true) 60 { 61 is_correct = 1; 62 g_grade = users[i].Getgrade(); 63 break; 64 } 65 } 66 if (is_correct == 1) 67 { 68 cout << "当前选择为"; 69 if (g_grade == 1) cout << "小学出题, "; 70 else if (g_grade == 2) cout << "中学出题, "; 71 else cout << "高中出题, "; 72 break; 73 } 74 else 75 cout << "请输入正确用户名和密码" << endl; 76 } 77 } 78 79 80 81 82 #endif /* USER_H_ */
这个模块主要作用为:有关登陆的一系列提示
优点:该模块代码巧妙运用类,使整个模块思路更加清晰。
2、generate.h
1 #ifndef GENERATE_H_ 2 #define GENERATE_H_ 3 extern int g_num; 4 5 6 #include <iostream> 7 #include <ctime> 8 #include <cstdlib> 9 using namespace std; 10 11 extern ofstream out; 12 13 void Operator(int operatorNo) 14 { 15 switch (operatorNo) 16 { 17 case 1: out << " + "; break; 18 case 2: out << " - "; break; 19 case 3: out << " * "; break; 20 case 4: out << " / "; break; 21 case 5: out << "^2"; break; 22 case 6: out << "√"; break; 23 case 7: out << "sin";break; 24 case 8: out << "cos";break; 25 case 9: out << "tan";break; 26 } 27 28 } 29 30 void GeneratePart(int operandNum, int g_grade) 31 { 32 int is_kuohao, kuohaoNum = 0, tmp1 = 0, tmp2 = 0, tmp3 = 0; 33 int juniorNum = 0, seniorNum = 0; 34 for (int j=0; j<operandNum-1; j++) 35 { 36 int operand = rand()%100 + 1; 37 int tmp4 = 0; 38 39 is_kuohao = rand()%2; 40 if (j != operandNum-2 && is_kuohao == 1 && kuohaoNum <= 3) 41 { 42 out << "("; 43 if (j == 0) tmp2 = 1; //用来排除(5+2)这种情况 44 kuohaoNum ++; 45 tmp1 = 1; //用来排除(5)这种情况 46 } 47 48 int choose = rand()%9 + 1; 49 if (g_grade > 1) 50 { 51 if (g_grade == 2 && choose == 6) 52 { 53 Operator(6); 54 juniorNum ++; 55 tmp4 ++; 56 } 57 else if (g_grade == 3 && choose > 6) 58 { 59 Operator(choose); 60 seniorNum ++; 61 tmp4 ++; 62 } 63 if (j != operandNum-2 && tmp4 != 0) 64 { 65 is_kuohao = rand()%2; 66 if (is_kuohao == 1 && kuohaoNum <= 3) 67 { 68 out << "("; 69 tmp3 = 1; 70 kuohaoNum ++; 71 } 72 } 73 } 74 75 out << operand; 76 77 if (g_grade ==2 && choose == 5) 78 { 79 Operator(5); 80 juniorNum ++; 81 } 82 83 if (tmp1 == 0 && tmp3 == 0 && kuohaoNum >= 1) 84 { 85 for (int k=0; k<kuohaoNum; k++) 86 { 87 int flag = rand()%2; 88 if (flag == 1) 89 { 90 out << ")"; 91 kuohaoNum --; 92 tmp2 = 2; 93 } 94 } 95 } 96 97 if (j==operandNum-2 && tmp2==1 && kuohaoNum>0) 98 { 99 for (int j=0; j<kuohaoNum; j++) 100 out << ")"; 101 kuohaoNum = 0; 102 } 103 104 int operatorNo = rand()%4 + 1; 105 Operator(operatorNo); 106 } 107 108 if ((g_grade==1) || (g_grade==2&&juniorNum!=0) || (g_grade==3&&seniorNum!=0)) out << rand()%100 + 1; 109 else if (g_grade == 2 && juniorNum == 0) 110 { 111 int chooseOper = rand()%2; 112 if (chooseOper == 0) out << "√" << rand()%100 + 1; 113 else out << rand()%100 + 1 << "^2"; 114 } 115 else if (g_grade == 3 && seniorNum == 0) 116 { 117 int chooseOper = rand()%3 + 7; 118 Operator(chooseOper); 119 out << rand()%100 + 1; 120 } 121 122 if (kuohaoNum != 0) 123 { 124 for (int j=0; j<kuohaoNum; j++) 125 out << ")"; 126 kuohaoNum = 0; 127 } 128 out << " = "<< endl; 129 } 130 131 132 133 134 void GenerateAll(int g_num, int g_grade) 135 { 136 for (int i=0; i<g_num; i++) 137 { 138 out << i+1 << ". "; 139 140 if (g_grade == 1) 141 { 142 int operandNum = rand()%4 + 2; 143 GeneratePart(operandNum, g_grade); 144 } 145 146 else if (g_grade == 2) 147 { 148 int operandNum = rand()%5 + 1; 149 if (operandNum == 1) 150 { 151 int chooseOper = rand()%2; 152 if (chooseOper == 0) out << "√" << rand()%100 + 1 << " = " << endl; 153 else out << rand()%100 + 1 << "^2 = " << endl; 154 } 155 else 156 { 157 GeneratePart(operandNum, g_grade); 158 } 159 } 160 161 else if (g_grade == 3) 162 { 163 int operandNum = rand()%5 + 1; 164 if (operandNum == 1) 165 { 166 int chooseOper = rand()%3; 167 if (chooseOper == 0) out << "sin"; 168 else if (chooseOper == 1) out << "cos"; 169 else out << "tan"; 170 out << rand()%100 + 1 << " = " << endl; 171 } 172 else 173 { 174 GeneratePart(operandNum, g_grade); 175 } 176 } 177 out << endl; 178 } 179 } 180 181 182 #endif /* GENERATE_H_ */
这个模块主要作用:按需求文档上的要求生成试卷(选择生成运算符及括号)
优点:括号部分产生条理清晰,对于括号产生的条件限制考虑非常全面,比如(5),()前后需有运算符等。
缺点:一个子函数中变量过多,其中tmp4或许可以删掉。代码中注释较少,一些变量旁可添加一些注释,方便读者阅读代码。
3、main.cpp
1 #include <iostream> 2 #include <fstream> 3 #include <ctime> 4 #include <time.h> 5 #include <stdio.h> 6 #include "generate.h" 7 #include "user.h" 8 9 int g_grade, g_num; 10 ofstream out; 11 12 int main() 13 { 14 UserData(); 15 16 cout << "请输入题目数量(10-30)" << endl; 17 cin >> g_num; 18 while (g_num < 10 || g_num > 30) 19 { 20 cout << "请输入正确数量" << endl; 21 cin >> g_num; 22 } 23 24 srand ((unsigned)time(NULL)); 25 26 time_t t = time(0); 27 char tmp[64]; 28 strftime( tmp, sizeof(tmp), "%Y-%m-%d-%H-%M-%S.txt",localtime(&t) ); 29 //freopen(tmp,"w",stdout); 30 //GenerateAll(g_num, g_grade); 31 //fclose(stdout); 32 //freopen("CON", "w", stdout); 33 //freopen("CON", "r", stdin); 34 out.open(tmp); 35 GenerateAll(g_num, g_grade); 36 out.close(); 37 38 cout << "若需要切换类型, 输入 切换为XX , 为小学、初中和高中三个选项中的一个" << endl; 39 string order; 40 while(1) 41 { 42 cin >> order; 43 int flag = 0; 44 if (order == "切换为小学") g_grade = 1; 45 else if (order == "切换为初中") g_grade = 2; 46 else if (order == "切换为高中") g_grade = 3; 47 else 48 { 49 cout << "请输入小学、初中和高中三个选项中的一个" << endl; 50 flag = 1; 51 } 52 if (flag == 0) 53 { 54 cout << "准备生成"; 55 if (g_grade == 1) cout << "小学题目, 请输入生成题目数量" << endl; 56 else if (g_grade == 2) cout << "中学题目, 请输入生成题目数量" << endl; 57 else cout << "高中题目, 请输入生成题目数量" << endl; 58 cin >> g_num; 59 if (g_num<10 || g_num>30) 60 { 61 cout << "请输入正确数量" << endl; 62 cin >> g_num; 63 } 64 65 time_t t = time(0); 66 strftime( tmp, sizeof(tmp), "%Y-%m-%d-%H-%M-%S.txt",localtime(&t) ); 67 //freopen(tmp,"w",stdout); 68 //GenerateAll(g_num, g_grade); 69 //fclose(stdout); 70 //freopen("CON", "w", stdout); 71 //freopen("CON", "r", stdin); 72 out.open(tmp); 73 GenerateAll(g_num, g_grade); 74 out.close(); 75 } 76 } 77 return 0; 78 }
该模块主要作用:设置出题题数和难度,以及最后文件的输出。
优点:由于各模块已经在头文件中实现,所以主函数中代码简洁短小,条理清晰。
同时,搭档的变量的命名非常规范,严格按照老师给的代码规范命名。
缺点:并不是所有用户都要切换难度,还要考虑不切换难度的情况。同时,为了有更好的用户体验,界面上每次生成完试卷最好提示试卷完成生成。
运行截图:
总结:
优点:代码简短,将各功能模块化,条理清晰,命名及格式规范,每个模块实现条件考虑严谨。
缺点:没有实现向指定文件夹中生成试卷,没有实现查重功能,输入完成后,界面最好有提示,增强用户体验。