HNU个人项目互评(中小学数学卷子自动生成程序)

发布时间 2023-09-20 20:53:01作者: jeferry

一. 项目简介

  本次项目为设计一个中小学数学卷子的自动生成程序,本文为对我的结对编程对象lhq同学的个人项目进行评价与建议。

 

二.项目结构

 

  先来看看项目的构成:

 

如同类名所示,各个类各司其职。

具体来说:

  1. main类中负责用户的登录和切换出题难度
  2. Makeallquestion 接口中包含了一个方法makequestion,在makequestion类中得到了具体实现
  3. Makequestion类中实现了2中接口的方法,对于小学,初中,高中的题目,各给出了具体的题目生成方法。同时实现了整张试卷的生成。
  4. FileIn类中实现了文件的写入,获取目标路径下所有文件的字符串和将目标文件进行清除的功能
  5. checkpaper类实现了文件查重的功能
  6. Teacher类进行了教师基本属性的构建

 

三.功能测试

  1. 用户的登录

    当输入错误的用户名,密码时,能够自动进行判断

  2. 题目的生成

    小学,初中,高中题目都符合规范

     

    而当输入数量超过限制范围时,能正确地进行提示

     

    3.切换难度出题目

     

    当切换不符合规定时,能够进行正确地提示

     

四.核心代码分析

Main类:

 

public class Main {
  static String[] count = {"张三1", "张三2", "张三3", "李四1", "李四2", "李四3", "王五1", "王五2", "王五3"};
  static String[] password = {"123", "123", "123", "123", "123", "123", "123", "123", "123"};
  static String[] type = {"小学", "小学", "小学", "初中", "初中", "初中", "高中", "高中", "高中"};

  public static void main(String[] args) throws IOException {
    while (true) {
      System.out.println("请输入正确的用户名和密码:");
      Scanner input = new Scanner(System.in);
      String countIn = input.next();
      String passwordIn = input.next();
      for (int ii = 0; ii < count.length; ii++) {
        if (count[ii].equals(countIn) && password[ii].equals(passwordIn)) {
          Teacher user = new Teacher(count[ii], type[ii]);
          back:
          while (true) {
            user.print1();
            String in = input.next();
            switch (in) {
              case "切换为小学":
                user.changeType("小学");
                continue back;
              case "切换为初中":
                user.changeType("初中");
                continue back;
              case "切换为高中":
                user.changeType("高中");
                continue back;
              default:
                try {
                  int num = Integer.parseInt(in);
                  if (num == -1) {
                    break back;
                  }
                  if (num < 10 || num > 30) {
                    System.out.println("数量范围:[10,30],请重新输入");
                    continue back;
                  }
                  MakeQuestion paper = new MakeQuestion(user.getType(), num);
                  FileIn fileIn1 = new FileIn(user);
                  File file2 = fileIn1.makeFile();
                  paper.makePaper(num, file2, paper, fileIn1);
                } catch (NumberFormatException n) {
                  System.out.println("输入错误,请重新输入");
                }
            }
          }
        }
      }
    }

  }
}
View Code

 

main类里进行了用户地登录和切换,值得一提地是,作者使用了java中的标签,使得程序的逻辑显得十分简单,避免了复杂的跳转判断

 

Teacher类:

  public void print1() {
    if (this.type.equals("小学")) {
      System.out.println("准备生成小学数学题目,请输入题目个数(范围:[10,30],输入-1推出当前账户)");
    }
    if (this.type.equals("初中")) {
      System.out.println("准备生成初中数学题目,请输入题目个数(范围:[10,30],输入-1推出当前账户)");
    }
    if (this.type.equals("高中")) {
      System.out.println("准备生成高中数学题目,请输入题目个数(范围:[10,30],输入-1推出当前账户)");
    }
  }
View Code

进行了用户地创建,其中将一些集成性地语句浓缩到print1方法中,避免了在main函数中过多的解释,提高了代码的复用性

 

FileIn类:

 

  public File makeFile() {
    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
    String date = df.format(new Date());
    String name = user.getCountName();
    String str = "./paper\\paper of " + name;
    File dirt = new File(str);
    if (!dirt.exists()) {
      dirt.mkdirs();
    }
    File file = new File(str, date + ".txt");
    try {
      file.createNewFile();
    } catch (IOException e) {
      e.printStackTrace();
    }
    return file;
  }
  public void fileInput(File file, String line) throws IOException {
    boolean append = true;
    FileWriter fw = new FileWriter(file, append);
    fw.write(line);
    fw.append("\r\n");
    fw.flush();
    fw.close();
  }
View Code

 

 

进行了用户文件夹的创建以及不同文件之间的查重,使用了相对路径,使得保存文件比较方便

 

CheckPaper类:

 

public boolean compare(String file1, String file2) throws IOException {
    Path path1 = Paths.get(file1);
    Path path2 = Paths.get(file2);
    try
        (InputStream inp1 = Files.newInputStream(path1);
         InputStream inp2 = Files.newInputStream(path2)) {
      int bt1;
      int bt2;
      do {
        bt1 = inp1.read();
        bt2 = inp2.read();
        if (bt1 != bt2) {
          return false;
        }
      } while (bt1 != -1);
      return true;
    }
  }


  public boolean checkPaper(String[] path, String filename) throws IOException {
    boolean res = false;
    for (int i = 0; i < path.length; i++) {
      if (compare(path[i], filename) && !filename.equals(path[i])) {
        res = true;
      }
    }
    return res;
  }
View Code

 

进行了文件的查重,其中又将查重的具体代码进行浓缩,使得代码逻辑清晰

MakeQuestion类:

 

public class MakeQuestion implements MakeAllQuestion {
  /**
   * 这个方法用来生成问题.
   *
   * @param type 类别参数
   * @return {@link String} 返回相应生成的题目
   */
  public String makeQuestion(String type) {
    if (type.equals("小学")) {
      return makePrimaryQuestion();
    } else if (type.equals("初中")) {
      return makeJuniorQuestion();
    } else if (type.equals("高中")) {
      return makeHighQuestion();
    } else {
      return "1";
    }
  }

  String type;
  int num;
  String[] primaryChar = {"+", "-", "*", "/"};
  String[] juniorChar = {"^2", "√", " "};
  String[] highChar1 = {"sin", "cos", "tan", " "};


  /**
   * 该类的构造函数.
   *
   * @param type 参数类别
   * @param num  题目的数量
   */
  public MakeQuestion(String type, int num) {
    this.num = num;
    this.type = type;
  }

  /**
   * 获取该类的类别.
   *
   * @return {@link String} 返回类别
   */
  public String getType() {
    return this.type;
  }

  /**
   * 根据不同的标志位返回左括号还是右括号.
   *
   * @param flag 标志位
   * @return {@link String} 返回括号字符
   */
  public String getBracket(boolean flag) {
    if (flag) {
      return "(";
    } else {
      return ")";
    }
  }

  /**
   * 根据不同的标志位来添加左括号.
   *
   * @param g        标志位
   * @param i        循环次数
   * @param a        操作数个数
   * @param question 题目
   * @param flag     标志位
   * @return {@link String}返回加完左括号的题目
   */
  public String leftBracket(int[] g, int i, int a, String question, boolean[] flag) {
    if (g[0] == 0 && i != (a - 1) && flag[0]) {
      question = question + getBracket(flag[0]);
      flag[0] = !flag[0];
      g[0] = 1;
    }
    return question;
  }

  /**
   * 根据不同的标志位来添加右括号.
   *
   * @param g        标志位
   * @param i        循环次数
   * @param a        操作数个数
   * @param question 题目
   * @param flag     标志位
   * @return {@link String}返回加完右括号的题目
   */
  public String rightBracket(int[] g, int i, int a, String question, boolean[] flag) {
    if (g[0] == 0 && i != (a - 1) && !flag[0]) {
      question = question + getBracket(flag[0]);
      flag[0] = !flag[0];
    }
    return question;
  }

  /**
   * 生成随机的高中题目.
   *
   * @param a        操作数个数
   * @param question 题目
   * @param flag     标志位
   * @param flag1    是否有高中符号的标志位
   * @return {@link String}返回生成的题目
   */
  public String switchIntHigh(int a, String question, boolean[] flag, int[] flag1) {
    for (int i = 0; i < a; i++) {
      int c = (int) (Math.random() * 100 + 1);
      int d = (int) (Math.random() * 4);
      int e = (int) (Math.random() * 4);
      int g = (int) (Math.random() * 2);
      String str1 = Integer.toString(c);
      String str2 = primaryChar[d];
      String str3 = highChar1[e];
      switch (e) {
        case 0:
        case 1:
        case 2:
          question = question + str2;
          if (g == 0 && i != (a - 1) && flag[0]) {
            question = question + getBracket(flag[0]);
            flag[0] = !flag[0];
            g = 1;
          }
          question = question + str3;
          question = question + str1;
          if (g == 0 && i != (a - 1) && !flag[0]) {
            question = question + getBracket(flag[0]);
            flag[0] = !flag[0];
          }
          flag1[0] = 1;
          break;
        case 3:
          question = question + str2;
          if (g == 0 && i != (a - 1) && flag[0]) {
            question = question + getBracket(flag[0]);
            flag[0] = !flag[0];
            g = 1;
          }
          question = question + str1;
          if (g == 0 && i != (a - 1) && !flag[0]) {
            question = question + getBracket(flag[0]);
            flag[0] = !flag[0];
          }
          break;
        default:
          break;
      }
    }
    return question;
  }

  /**
   * 生成添加一个操作数和一个符号或者一个括号的部分题目.
   *
   * @param a        操作数个数
   * @param question 题目
   * @param flag     标志位
   * @param flag1    判断有没有符号的标志位
   * @return {@link String} 返回生成的部分题目
   */
  public String switchIntJunior(int a, String question, boolean[] flag, int[] flag1) {
    for (int i = 0; i < a; i++) {
      int[] g = new int[1];
      g[0] = (int) (Math.random() * 2);
      int c = (int) (Math.random() * 100 + 1);
      int d = (int) (Math.random() * 4);
      int e = (int) (Math.random() * 3);
      String str1 = Integer.toString(c);
      String str2 = primaryChar[d];
      String str3 = juniorChar[e];
      switch (e) {
        case 0:
          question = question + str3;
          question = question + str2;
          question = leftBracket(g, i, a, question, flag);
          question = question + str1;
          question = rightBracket(g, i, a, question, flag);
          flag1[0] = 1;
          break;
        case 1:
          question = question + str2;
          question = question + str3;
          question = leftBracket(g, i, a, question, flag);
          question = question + str1;
          question = rightBracket(g, i, a, question, flag);
          flag1[0] = 1;
          break;
        case 2:
          question = question + str2;
          question = leftBracket(g, i, a, question, flag);
          question = question + str1;
          question = rightBracket(g, i, a, question, flag);
          break;
        default:
          break;
      }
    }
    return question;
  }

  /**
   * 生成一个完整的小学题目.
   *
   * @return {@link String} 返回生成好的小学题目
   */
  public String makePrimaryQuestion() {
    boolean flag = true;
    int c = (int) (Math.random() * 4 + 1);
    int d = (int) (Math.random() * 100 + 1);
    String question = Integer.toString(d);
    int f = (int) (Math.random() * 2);
    if (f == 0) {
      question = getBracket(flag) + question;
      flag = !flag;
    }
    for (int i = 0; i < c; i++) {
      int e = (int) (Math.random() * 2);
      int a = (int) (Math.random() * 100 + 1);
      int b = (int) (Math.random() * 4);
      String str1 = Integer.toString(a);
      String str2 = primaryChar[b];
      question = question + str2;
      if (e == 0 && i != (c - 1) && flag) {
        question = question + getBracket(flag);
        flag = !flag;
        e = 1;
      }
      question = question + str1;
      if (e == 0 && i != (c - 1) && !flag) {
        question = question + getBracket(flag);
        flag = !flag;
      }
    }
    if (!flag) {
      question = question + ")";
    }
    return question;
  }

  /**
   * 生成一个完整的初中题目.
   *
   * @return {@link String} 返回生成好的初中题目
   */
  public String makeJuniorQuestion() {
    boolean[] flag = new boolean[1];
    flag[0] = true;
    int[] flag1 = new int[1];
    int a = (int) (Math.random() * 4 + 1);
    int b = (int) (Math.random() * 100 + 1);
    String question = Integer.toString(b);
    int f = (int) (Math.random() * 2);
    if (f == 0) {
      question = getBracket(flag[0]) + question;
      flag[0] = !flag[0];
    }
    question = switchIntJunior(a, question, flag, flag1);
    if (flag1[0] == 0) {
      question = juniorChar[1] + question;
    }
    if (!flag[0]) {
      question = question + ")";
    }
    return question;
  }

  /**
   * 生成一个完整的高中题目.
   *
   * @return {@link String} 返回生成好的高中题目
   */
  public String makeHighQuestion() {
    boolean[] flag = new boolean[1];
    flag[0] = true;
    int[] flag1 = new int[1];
    int a = (int) (Math.random() * 4 + 1);
    int b = (int) (Math.random() * 100 + 1);
    String question = Integer.toString(b);
    int f = (int) (Math.random() * 2);
    if (f == 0) {
      question = getBracket(flag[0]) + question;
      flag[0] = !flag[0];
    }
    question = switchIntHigh(a, question, flag, flag1);
    if (flag1[0] == 0) {
      int h = (int) (Math.random() * 3);
      question = highChar1[h] + question;
    }
    if (!flag[0]) {
      question = question + ")";
    }
    return question;
  }

  /**
   * 将生成的题目加入文件中形成试卷.
   *
   * @param num    题目的个数
   * @param file   相应的文件
   * @param paper  制作题目的对象
   * @param fileIn 加入文件的对象
   * @throws IOException 抛出异常
   */
  public void makePaper(int num, File file, MakeQuestion paper, FileIn fileIn) throws IOException {
    boolean flag = true;
    while (flag) {
      fileIn.fileClear(file);
      switch (paper.getType()) {
        case "高中":
          for (int k = 0; k < num; k++) {
            String question1 = paper.makeQuestion("高中");
            System.out.println(question1);
            String str = Integer.toString(k + 1) + ". " + question1;
            fileIn.fileInput(file, str);
          }
          break;
        case "初中":
          for (int k = 0; k < num; k++) {
            String question1 = paper.makeQuestion("初中");
            System.out.println(question1);
            String str = Integer.toString(k + 1) + ". " + question1;
            fileIn.fileInput(file, str);
          }
          break;
        case "小学":
          for (int k = 0; k < num; k++) {
            String question1 = paper.makeQuestion("小学");
            System.out.println(question1);
            String str = Integer.toString(k + 1) + ". " + question1;
            fileIn.fileInput(file, str);
          }
          break;
        default:
          break;
      }
      CheckPaper check = new CheckPaper();
      String filename = file.getPath();
      if (!check.checkPaper(fileIn.getAllFile(), filename)) {
        flag = false;
      }
    }
    System.out.println("题目生成完毕");
  }

}
View Code

 

根据步骤:

1.先判断进行创建的是什么类型的问题

2.根据类型进行出题:paper.makequestion(type),并将题目写入相应的文件,filein.fileinput(file,str);

3.进行查重判断,如果有重复,则终止试卷的生成 check.checkpaper();

五.优缺点分析

优点:

  1. 代码编写符合Google编程规范,在相应的地方加入了合适的注解以便于阅读与理解
  2. 代码复用性高,减少了重复冗余代码的数量
  3. 代码阅读性强,基本实现见名知义
  4. 类与类之间分工明确,为功能的修改与移植增添了更多的可能性

缺点:

  1. 查重功能可以进一步完善,并选择合适的查重方式
  2. 某些地方可以增添更多注释,某些变量可以取合适的名字来便于理解

六.总结

  总的来说,该项目实现了基本应该实现的功能,完成度较高,在评价过程中,我也认识到了自己的不足,对于他人的项目也需要进行优点的吸纳,希望能在之后的学习过程中互相激励,争取完成更好的项目