1. 队友代码测试
-
登陆
-
注册(要求外添加的功能)
-
退出
-
出题(以下为三种难度的题目)
-
切换难度
-
切换账号
2.代码分析
接下来将主要分析核心代码
首先是展示模块,这部分代码刘同学主要用了两个类来实现
首先是正常输入正确的情况
点击查看代码
package login;
import java.util.List;
import java.util.Scanner;
import teachers.Teacher;
/**
*Multiple lines of Javadoc text are written here,
*wrapped normally...
*/
public class Login {
/**
*Multiple lines of Javadoc text are written here,
*wrapped normally...
*/
public static Teacher login(List<Teacher> teachers) {
System.out.println("请输入你的用户名和密码,用空格隔开:");
Scanner in = new Scanner(System.in);
Teacher t = new Teacher();
boolean loggedIn = false;
while (!loggedIn) {
try {
String input = in.nextLine();
String[] inputParts = input.split("\\s+");
if (inputParts.length != 2) {
System.out.println("请按照正确格式输入用户名和密码:");
continue;
}
String username = inputParts[0];
String password = inputParts[1];
int userType = 0;
for (Teacher teacher : teachers) {
if (teacher.getTname().equals(username)) {
if (teacher.getTpassword().equals(password)) {
loggedIn = true;
System.out.println("登录成功!");
t.setTname(teacher.getTname());
t.setTpassword(teacher.getTpassword());
t.setType(teacher.getType());
userType = teacher.getType();
switch (userType) {
case 1:
System.out.println("当前选择为小学出题");
break;
case 2:
System.out.println("当前选择为初中出题");
break;
case 3:
System.out.println("当前选择为高中出题");
break;
default:
System.out.println("未知类型");
break;
}
break;
}
}
}
if (!loggedIn) {
System.out.println("输入的用户名或密码错误,请重新输入:");
}
} catch (Exception e) {
System.out.println("发生错误,请重新输入用户名和密码:");
//清除输入缓冲区,避免无限循环
in.nextLine();
}
}
return t;
}
}
点击查看代码
package system;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;
import login.Login;
import paper.CreatePaper;
import teachers.GetTeacher;
import teachers.Teacher;
/**
*Multiple lines of Javadoc text are written here,
*wrapped normally...
*/
public class DisplayChange {
public static String primary = "小学";
public static String junior = "初中";
public static String senior = "高中";
static int input(int state) {
//对应的年级输出相应的提示语
System.out.print("准备生成");
String[] gradeNames = {primary, junior, senior};
//使用数组来获取年级名称
System.out.print(gradeNames[state - 1]);
System.out.println("数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录):");
int temp;
Scanner sc = new Scanner(System.in);
while (true) {
String userInput = sc.nextLine();
if (userInput.equals("-1")) {
temp = -1;
break;
} else if (userInput.startsWith("切换为")) {
//获取切换年级的部分并去除首尾空格
String gradeInput = userInput.substring(3).trim();
temp = getGradeFromInput(gradeInput);
if (temp != 0) {
break;
} else {
System.out.println("输入的年级不正确,请重新输入(输入-1将退出当前用户,重新登录)");
}
} else if (userInput.matches("\\d+")) {
int num = Integer.parseInt(userInput);
if (num >= 10 && num <= 30) {
temp = num;
break;
} else {
System.out.println("输入范围错误,请重新输入(输入-1将退出当前用户,重新登录)");
}
} else {
System.out.println("输入错误,请重新输入(输入-1将退出当前用户,重新登录)");
}
}
return temp;
}
//获得年级
private static int getGradeFromInput(String gradeInput) {
switch (gradeInput) {
case "小学":
return 1;
case "初中":
return 2;
case "高中":
return 3;
default:
return 0;
}
}
/**
*Multiple lines of Javadoc text are written here,
*wrapped normally...
*/
public void change(Teacher teacher) throws IOException {
GetTeacher getTeacher = new GetTeacher();
Login login = new Login();
CreatePaper createPaper = new CreatePaper();
ArrayList<Teacher> teachers = getTeacher.initial();
int grade = teacher.getType();
while (true) {
int inputGrade = input(grade);
switch (inputGrade) {
//退出当前用户重新登录
case -1:
teacher = login.login(teachers);
grade = teacher.getType();
break;
case 1:
case 2:
case 3:
grade = inputGrade;
break;
default:
createPaper.createPaper(teacher.getTname(), grade, inputGrade);
break;
}
}
}
}
点击查看代码
public static void createPaper(String name, int type, int num) throws IOException {
GetFormula g = new GetFormula();
//获取生成不同年级算式的类对象
JuniorFormula j = new JuniorFormula();
PrimaryFormula p = new PrimaryFormula();
SeniorFormula s = new SeniorFormula();
String formula = null;
//获取所有该老师的试题
HashSet<String> all = g.getFormula(name);
String pathdoc = name;
File file = new File(pathdoc);
if (!file.exists()) {
file.mkdir();
}
final SimpleDateFormat Sdf = new SimpleDateFormat();
Sdf.applyPattern("yyyy-MM-dd-HH-mm-ss");
//按照要求的格式或得到时间写进文件名里面
String path = pathdoc + "\\" + Sdf.format(new Date()) + ".txt";
try {
FileWriter every = new FileWriter(path, true);
for (int i = 0; i < num; i++) {
//调用生成不同年级算式的类方法
if (type == 1) {
formula = p.createFormula();
}
if (type == 2) {
formula = j.createFormula();
}
if (type == 3) {
formula = s.createFormula();
}
//卷子查重
if (!all.contains(formula)) {
every.write(i + 1 + "." + formula + "\n" + "\n");
}
}
System.out.println("卷子生成成功!");
every.close();
} catch (IOException e) {
e.printStackTrace();
}
}
点击查看代码
@Override
public String createFormula() {
Random random = new Random();
StringBuilder formula;
while (true) {
formula = new StringBuilder();
int oper = 0;
int trigFunc = random.nextInt(5) + 1;
int number = random.nextInt(5);
int left = 0;
int temp = 0;
while (true) {
if (random.nextInt(2) == 0 && number > 0) {
formula.append("(");
number--;
left++;
temp = 0;
}
//下面的这段代码用来实现操作数之后添加平方、开根号后添加操作数、三角函数之后添加操作数、直接添加一个操作数
temp++;
int num = random.nextInt(100) + 1;
if (random.nextInt(3) == 0) {
if (random.nextInt(2) == 0) {
formula.append(num).append("^2");
} else {
formula.append("√").append(num);
}
} else {
if (random.nextInt(2) == 0) {
formula.append(getOperator(random.nextInt(3) + 4)).append(num);
trigFunc--;
} else {
formula.append(num);
}
}
//左括号还有没有配对的,左括号后面跟的操作数数量大于1才能添加右括号
if (random.nextInt(2) == 0 && left > 0 && temp >= 2) {
formula.append(")");
left--;
}
//添加完一个右括号就判断一次算式的合法性,必须至少有一个运算符同时随机可以生成的三角函数、括号个数都已经添加到算式中
if (oper >= 1 && trigFunc <= 0 && number <= 0 && left <= 0) {
break;
}
formula.append(getOperator(random.nextInt(4)));
oper++;
}
if (oper < 5 && temp < 5) {
break;
}
}
formula.append("=");
return formula.toString();
}
3.优点
-
模块化:
代码通过分包组织成了多个模块,每个模块都有明确定义的功能和职责。这样的组织结构使得代码更易于维护和理解,同时也降低了出现混乱和冲突的可能性。 -
封装:
代码通过封装各种函数,仅仅只需要运行main函数,在里面调用各种函数,实现了很好的封装,比较好修改bug和扩展 -
合理的文件部署及运用:
在用户方面巧用文件存储用户信息,已经登录等都用到了文件操作,可以实现即使退出这个系统也还能够将改变后的用户信息等存储下来,而不是系统需要一直运行,我的代码就是运行一次程序里面存储的用户是一个版本,退出重启之后就是一开始的初始版本。 -
异常处理:
代码捕获了可能抛出的IOException异常并进行了处理,通过打印堆栈跟踪信息,有助于诊断问题。虽然没有采取更复杂的异常处理策略,但这是一个良好的起点。
4.缺点
-
逻辑处理不当
一旦登录后就不能直接退出系统了,而只能在一开始退出,这很不合理也不方便(只有一开始能输入3退出,其他【均不可以)
-
查重功能有问题
查重的时候,在从文件中读题目的时候,刘同学的代码并没有将题号去除再对比,而时直接读入一整行,所以查重的时候连着题号一起读进去了,由于题号在改变,在本文件内查重无法实现,而在其他文件中查重成功概率很低,只有题目和题号均相同才能查出来,这是很大的bug
以下是获取文件里的代码
点击查看代码
public HashSet<String> getFormula(String name) {
File file = new File(name);
if (!file.exists()) {
file.mkdir();
}
File[] files = file.listFiles();
HashSet<String> allformula = new HashSet<>();
for (File f : files) {
if (!f.isDirectory()) {
try {
FileInputStream ff = new FileInputStream(f);
BufferedReader b = new BufferedReader(new InputStreamReader(ff));
String line;
//逐行读取文件中的内容并且添加到哈希set中
while ((line = b.readLine()) != null) {
allformula.add(line);
}
b.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
return allformula;
}
而在生成卷子时调用的代码如下
点击查看代码
//卷子查重
if (!all.contains(formula)) {
every.write(i + 1 + "." + formula + "\n" + "\n");
}
- 出题不合理
随机出的题目有一部分有一些不太必要的括号,这一个小小的bug在我的项目里也同样出现,例如以下题目
5.总结
刘同学在实现这个系统功能的时候在文件方面确实熟练运用,不仅是用文件流,还善于规划文件部署,最让我欣赏的就是分包以及用文件存用户,以及她多加的注册功能等,很人性化,以及除了查重功能没有实现完全存在bug之外几乎没有其他问题,是一个很好的项目