【HNU个人项目互评】

发布时间 2023-09-20 13:54:57作者: --啊吧啊吧

 

  • 代码:软件2101拜赫赫
  • 评价:软件2102廖星宇

一、题目介绍

用户

小学、初中和高中数学老师。

功能

1、命令行输入用户名和密码,两者之间用空格隔开(程序预设小学、初中和高中各三个账号,具体见附表),如果用户名和密码都正确,将根据账户类型显示“当前选择为XX出题”,XX为小学、初中和高中三个选项中的一个。否则提示“请输入正确的用户名、密码”,重新输入用户名、密码;

2、登录后,系统提示“准备生成XX数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录):”,XX为小学、初中和高中三个选项中的一个,用户输入所需出的卷子的题目数量,系统默认将根据账号类型进行出题。每道题目的操作数在1-5个之间,操作数取值范围为1-100;

3、题目数量的有效输入范围是“10-30”(含10,30,或-1退出登录),程序根据输入的题目数量生成符合小学、初中和高中难度的题目的卷子(具体要求见附表)。同一个老师的卷子中的题目不能与以前的已生成的卷子中的题目重复(以指定文件夹下存在的文件为准,见5);

4、在登录状态下,如果用户需要切换类型选项,命令行输入“切换为XX”,XX为小学、初中和高中三个选项中的一个,输入项不符合要求时,程序控制台提示“请输入小学、初中和高中三个选项中的一个”;输入正确后,显示“”系统提示“准备生成XX数学题目,请输入生成题目数量”,用户输入所需出的卷子的题目数量,系统新设置的类型进行出题;

5、生成的题目将以“年-月-日-时-分-秒.txt”的形式保存,每个账号一个文件夹。每道题目有题号,每题之间空一行;

附表-1:账户、密码

账户类型账户密码
小学 张三1 123
小学 张三1 123
小学 张三1 123
初中 李四1 123
初中 李四1 123
初中 李四1 123
高中 王五1 123
高中 王五1 123
高中 王五1 123

附表-2:小学、初中、高中题目难度要求

 小学初中高中
难度要求 +,-,*./ 平方,开根号 sin,cos,tan
备注 只能有+,-,*./和() 题目中至少有一个平方或开根号的运算符 题目中至少有一个sin,cos或tan的运算符

二、代码分析

1. QuizPaper

public class QuizPaper {
public static void main(String[] args) {
Login log=new Login();//创建用户
log.logUser();//登录用户
//System.out.println(log.grade);
//int grade=Login.grade;//记录当前年级
while(true) {
InPut in=new InPut();
int out= in.waitInPut();
if (out==-1) {
log.logUser();//登录用户
//grade=Login.grade;
} else if (out==1) {
Login.grade=1;
} else if (out==2) {
Login.grade=2;
} else if (out==3) {
Login.grade=3;
} else {
OutPut problem=new OutPut();
problem.writeFile(Login.grade,out); // 输出题目
System.out.println("卷子生成完毕");
}
}
}
}
功能
  • 主要负责程序的启动和用户的登录。
  • 根据用户的输入和当前的年级级别来决定题目的生成。
优点
  • 有一个清晰的主入口,通过main方法来启动程序。
  • 利用循环结构来实现用户的多次输入和题目的多次生成。
缺点
  • 代码中存在大量的硬编码,如年级级别的判断和设置。

2. OutPut

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;

public class OutPut {
public String[] symbol=new String[] {"+","-","*","/","²","√","sin","cos","tan"};
public int number; // 产生的数字
String problem=new String ();
Random r = new Random();
public int bracket=r.nextInt(3); // 随机创建总的括号个数
public int num=0; // 指示操作数数量
public int leftbracket=0; // 多余的左括号个数
public int distance=0; // 左右括考之间的数字个数
public int ordinal=0; // 用来确定出题的序号
public int leftflag=0; // 用来确保不会产生只有一对括号切在式子两边的情况
public int rightflag=0; // 用来确保不会产生只有一对括号切在式子两边的情况
public int symbolflag=0; // 用来指示是否加入了平方根号三角函数符号
public String problems(int grade,int time) {
while(true) {
int bracket=r.nextInt(3); // 随机创建总的括号个数
int num=0; // 指示操作数数量
int leftbracket=0; // 多余的左括号个数
int distance=0; // 左右括考之间的数字个数
int ordinal=0; // 用来确定出题的序号
int leftflag=0; // 用来确保不会产生只有一对括号切在式子两边的情况
int rightflag=0; // 用来确保不会产生只有一对括号切在式子两边的情况
int symbolflag=0; // 用来指示是否加入了平方根号三角函数符号
problem = ""; // 重置问题
if (grade == 1) {
while(true) {
if (r.nextInt(2) == 1 && bracket > 0) { //二分之一的概率加入左括号
problem += "(";
bracket--;
leftbracket++;
distance=0;
if(num==0){
leftflag=1;
}
}
number=r.nextInt(100)+1;
problem+=String.valueOf(number);
num++;
rightflag=0;
distance++;
if (r.nextInt(2) == 1 && leftbracket > 0&&distance>1) {
problem += ")"; // 二分之一的概率在有左括号中间操作数大于1的时候加入右括号
leftbracket--;
if (leftflag==1) {
rightflag = 1;
}
}
if (bracket==0&&leftbracket==0&&num>1&&rightflag==0) {
break;
}
problem+=symbol[r.nextInt(4)]; // 加入符号
}
if (num<6) { // 过滤掉操作数过多的式子
problem+="=";
break;
}
}
if (grade == 2) {
while(true) {
if (r.nextInt(2) == 1 && bracket > 0) {
problem += "(";
bracket--;
leftbracket++;
distance=0;
if (num==0) {
leftflag=1;
}
}
if (r.nextInt(2) == 1) { // 二分之一的概率加入根号和平方
if (r.nextInt(2) == 1) { // 四分之一的概率加入平方
number=r.nextInt(100)+1;
problem+=String.valueOf(number)+symbol[4];
num++;
rightflag=0;
distance++;
symbolflag=1;
} else { // 四分之一的概率加入根号
number=r.nextInt(100)+1;
problem+=symbol[5]+String.valueOf(number);
num++;
rightflag=0;
distance++;
symbolflag=1;
}
} else { // 二分之一的概率加入纯数字
number=r.nextInt(100)+1;
problem+=String.valueOf(number);
num++;
rightflag=0;
distance++;
}
if (r.nextInt(2) == 1 && leftbracket > 0&&distance>1) {
problem += ")";
leftbracket--;
if (leftflag==1) {
rightflag = 1;
}
}
if (bracket==0&&leftbracket==0&&num>1&&rightflag==0&&symbolflag==1) {
break;
}
problem+=symbol[r.nextInt(4)];
}
if (num<6) {
problem+="=";
break;
}
}
if (grade == 3) {
while(true) {
if (r.nextInt(2) == 1 && bracket > 0) {
problem += "(";
bracket--;
leftbracket++;
distance=0;
if(num==0){
leftflag=1;
}
}
if (r.nextInt(2) == 1) { // 二分之一的概率加入平方括号或三角函数
if (r.nextInt(2) == 1) { // 四分之一的概率加入三角函数
number = r.nextInt(100) + 1;
problem += symbol[r.nextInt(3) + 6] + String.valueOf(number);
num++;
rightflag = 0;
distance++;
symbolflag=1;
} else {
if (r.nextInt(2) == 1) {
number=r.nextInt(100)+1;
problem+=String.valueOf(number)+symbol[4];
num++;
rightflag=0;
distance++;
} else {
number=r.nextInt(100)+1;
problem+=symbol[5]+String.valueOf(number);
num++;
rightflag=0;
distance++;
}
}
} else {
number=r.nextInt(100)+1;
problem+=String.valueOf(number);
num++;
rightflag=0;
distance++;
}
if (r.nextInt(2) == 1 && leftbracket > 0&&distance>1) {
problem += ")";
leftbracket--;
if(leftflag==1) {
rightflag = 1;
}
}
if (bracket==0&&leftbracket==0&&num>1&&rightflag==0&&symbolflag==1) {
break;
}
problem+=symbol[r.nextInt(4)];
}
if (num<6) {
problem+="=";
break;
}
}
}
return problem;
}
public void writeFile(int grade,int times)
{
Date d = new Date(); // 获取日期
SimpleDateFormat time = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss"); // 转换日期的格式
String date = time.format(d); // 将日期转换为字符串形式
String add=Login.x[0]; // 目标地址
String name=add+"/"+date+".txt"; // 文件名
File file = new File(add);
if (!file.exists()) {//如果没有该文件夹进行创建
file.mkdir();
}
try {
FileWriter out = new FileWriter(name,true);
for(int i=1;i<=times;i++) {
String no = String.valueOf(i) + "."; // 加入序号
out.write(no + problems(grade, times) + "\n" + "\n"); // 写入文件
}
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}

}
功能
  • 负责生成数学题目。
  • 根据年级级别和题目数量来生成不同难度的题目。
  • 将生成的题目写入到一个文本文件中。
优点
  • 通过随机数来生成不同的数学题目,增加了题目的多样性。
缺点
  • 代码中存在大量的重复代码,可以通过函数抽象来减少代码的重复。

3. InPut

import java.util.Scanner;

public class InPut {
public int out=0; // 返回一个年级代号,以便之后出题时确认年级
public int waitInPut() {
if(Login.grade==1) {
System.out.println("准备生成小学数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录):");
}
if(Login.grade==2) {
System.out.println("准备生成初中数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录):");
}
if(Login.grade==3) {
System.out.println("准备生成高中数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录):");
}
while(true) {
Scanner in=new Scanner(System.in);
String input=in.nextLine (); // 保存输入内容,在之后判断进行的操作
if(input.matches("\\d+")) {
if(input.equals("-1")) {
return out=-1;
} else if(Integer.parseInt(input)>=10&&Integer.parseInt(input)<=30) {
return out=Integer.parseInt(input); // 在10和30之间则转换为整数并返回
} else {
System.out.println("输入范围错误,请重新输入");
}
}else {
if(input.contains("切换为")) { // 对输入文字进行判断
if(input.equals("切换为小学")) {
return out = 1;
}
if(input.equals("切换为初中")) {
return out = 2;
}
if(input.equals("切换为高中")) {
return out = 3;
} else {
System.out.println("请输入小学、初中和高中三个选项中的一个");
continue;
}
} else {
System.out.println("输入内容错误,请重新输入");
}
}
}
}
}
功能
  • 负责接收用户的输入。
  • 根据用户的输入来决定题目的生成数量和年级级别。
优点
  • 有一个清晰的方法来接收和处理用户的输入。
缺点
  • 代码中存在硬编码的字符串,可以通过引入常量来避免这种情况。
  • 输入验证可以更加严格,以避免非法输入。

4. Login

import java.util.Scanner;

public class Login {
public static int grade = 0; // 全局变量便于确定年级
private int flag1 = 0; // 判断用户名是否正确的标志
private int flag2 = 0; // 判断密码是否正确的标志
public static String[] x; // 把user分成的数组定义为全局变量,为了两个方法之间通用

public int logUser() {
System.out.println("请输入用户名、密码");
while(true) {
Scanner in = new Scanner(System.in);
String user = in.nextLine();
x = user.split(" "); // 把user分为数组单独判断;
while(x.length != 0) {
if(x.length != 2) {
System.out.println("请输入正确的用户名、密码");
x = null; // 重置x
break;
} else {
if(x[0].equals("张三1") || x[0].equals("张三2") || x[0].equals("张三3")) {
flag1 = 1;
grade = 1;
break;
} else if (x[0].equals("李四1") || x[0].equals("李四2") || x[0].equals("李四3")) {
flag1 = 1;
grade = 2;
break;
} else if (x[0].equals("王五1") || x[0].equals("王五2") || x[0].equals("王五3")) {
flag1 = 1;
grade = 3;
break;
} else {
System.out.println("请输入正确的用户名、密码");
x = null;
break;
}
}
}
passWord();
if (flag1 == 1 && flag2 == 1) {
break;
}
}
dissplay(); // 登陆后的显示内容
return grade; // 返回年级
}

public void passWord() { //判断密码是否正确
while (flag1 == 1) {
if (x[1].equals("123")) {
flag2 = 1;
break;
} else {
System.out.println("请输入正确的用户名、密码");
x = null;
flag1 = 0;
break;
}
}
}

public void dissplay() {
if (grade==1) {
System.out.println("当前选择为小学出题");
} else if (grade==2) {
System.out.println("当前选择为初中出题");
} else if (grade==3) {
System.out.println("当前选择为高中出题");
}
}
}
功能
  • 负责用户的登录。
  • 根据用户名来确定年级级别。
优点
  • 有一个简单的用户验证系统来确定年级级别。
缺点
  • 用户验证系统非常简单,可以通过引入更复杂的验证系统来提高安全性。
  • 代码中存在硬编码的用户名和密码,可以通过引入用户数据库来避免这种情况。

总结

优点

  • 程序结构清晰,每个类都有其特定的功能。
  • 通过随机数来生成不同的数学题目,增加了题目的多样性。

缺点

  • 代码中存在大量的重复代码和硬编码,可以通过函数抽象和引入常量来解决这些问题。
  • 代码的可读性和可维护性可以通过引入更多的注释和文档来提高。

三、其他问题与bug

  • 无法退出
  • 方法行数超过四十