首页 > 编程语言 >【个人项目互评】结对互评-中小学数学试卷自动生成程序

【个人项目互评】结对互评-中小学数学试卷自动生成程序

时间:2023-09-20 13:55:21浏览次数:36  
标签:结对 题目 互评 static user 数学试卷 new public User

目录

  • 1. 简介
  • 2. 项目要求
  • 3. 代码分析
  • 4. 运行测试
  • 5. 优缺点分析

  1.简介

本篇博客是对结对编程队友对于项目《中小学数学卷子自动生成系统》的学习,分析与总结,选用的编程语言为Java.

  2.项目要求

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

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

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

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

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

   3.代码分析

3.1.整体架构

3.2 代码解读

  main方法:

public static void main(String[] args) {
    userList.add(user1);
    userList.add(user2);
    userList.add(user3);
    userList.add(user4);
    userList.add(user5);
    userList.add(user6);
    userList.add(user7);
    userList.add(user8);
    userList.add(user9);
    loginMenu();
  }
}

 User类:

class User {
  private String userType;
  private String userName;
  private String userPassword;
  private List<Question> questions = new ArrayList<>();

  public User() {
    this.userType = "0";
    this.userName = "0";
    this.userPassword = "0";
  }

  public User(String userType, String userName, String userPassword) {
    this.userType = userType;
    this.userName = userName;
    this.userPassword = userPassword;
    FileManager.createFolder(this);
  }

  public String getType() {
    return userType;
  }

  public String getName() {
    return userName;
  }

  public String getPassword() {
    return userPassword;
  }

  public void setUserType(String userType) {
    this.userType = userType;
  }

  public void addQuestion(Question question) {
    this.questions.add(question);
  }

  public List<Question> getQuestions() {
    return this.questions;
  }
}

分析:每个用户会有独自的存储题目的List,在保存进入文件前题目存储在List中。我认为可以在生成题目时用一个List存储数据,这样可以减少内存占用,同时避免了同一用户多次出题需要清空List的操作

 Main类:

public class Main {
  // 预置的用户
  static User user1 = new User("小学", "张三1", "123");
  static User user2 = new User("小学", "张三2", "123");
  static User user3 = new User("小学", "张三3", "123");
  static User user4 = new User("初中", "李四1", "123");
  static User user5 = new User("初中", "李四2", "123");
  static User user6 = new User("初中", "李四3", "123");
  static User user7 = new User("高中", "王五1", "123");
  static User user8 = new User("高中", "王五2", "123");
  static User user9 = new User("高中", "王五3", "123");
  // 用户列表
  public static List<User> userList = new ArrayList<>();
  // 当前用户的历史题目
  public static List<String> questionList = new ArrayList<>();

  // 登陆界面
  public static void loginMenu() {
    while (true) {
      System.out.println("====================\n请输入用户名和密码:");
      Scanner input = new Scanner(System.in);
      String id = input.next();
      User user = new User();
      int searched = 0;
      // 遍历用户列表查找账号
      for (User value : userList) {
        if (id.equals(value.getName())) {
          user = value;
          searched++;
        }
      }
      if (searched == 0) {
        System.out.println("请输入正确的用户名、密码!");
        continue;
      }
      // 检测密码正确性
      String password = input.next();
      if (password.equals(user.getPassword())) {
        userMenu(user);
        break;
      } else {
        System.out.println("请输入正确的用户名、密码!");
      }
    }
  }

  // 用户界面
  public static void userMenu(User user) {
    // 读取用户历史题目
    FileManager.readTxt(user, questionList);
    while (true) {
      System.out.println("====================\n准备生成"
              + user.getType() + "数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录):");
      Scanner input = new Scanner(System.in);
      String quest = input.next();
      int num;
      try {
        num = Integer.parseInt(quest);
      } catch (NumberFormatException e) {
        int law = 0;
        if (quest.startsWith("切换为") && quest.length() > 4) {
          if (quest.startsWith("小学", 3)) {
            user.setUserType("小学");
            law = 1;
          }
          if (quest.startsWith("初中", 3)) {
            user.setUserType("初中");
            law = 1;
          }
          if (quest.startsWith("高中", 3)) {
            user.setUserType("高中");
            law = 1;
          }
        }
        if (law == 0) {
          System.out.println("请输入小学、初中和高中三个选项中的一个");
        }
        continue;
      }
      if (num == -1) {
        loginMenu();
      } else {
        QuestMaker(user, num);
      }
      break;
    }
  }

  // 题目生成界面
  public static void QuestMaker(User user, int num) {
    while (true) {
      if (num < 10 || num > 30) {
        System.out.println("请输10~30内的数字");
        userMenu(user);
        break;
      }
      // 生成多个题目
      int i = 0;
      while (i < num) {
        Question question = QuestionFactory.creat(user);
        // 对新生成的题目查重
        if (!questionList.contains(question.expression)) {
          i++;
          user.addQuestion(question);
          System.out.println(i + ".  " + question.expression);
        }
      }
      FileManager.createTxt(user);
      userMenu(user);
    }
  }

分析:main类进行了用户数据的初始化,值得一提的是,输入时处理数据采用了try catch结构对输入进行判断为切换模式或者题目数量或-1,其他情况均会给出输入不合法提示,避免了处理其他未知输入的情况,值得学习. 

  NumberMaker类:

class NumberMaker {
  public static String makeNum(String type) {
    Random rNum = new Random();
    //随机生成1~100的数字
    int num = rNum.nextInt(100) + 1;
    String variable = Integer.toString(num);
    if (type.equals("初中")) {
      switch (rNum.nextInt(4)) {
        case 0:
          variable = variable + "²";
          break;
        case 1:
          variable = "√(" + variable + ")";
          break;
        default:
          // Nothing
      }
    }
    if (type.equals("高中")) {
      switch (rNum.nextInt(10)) {
        case 0:
          variable = "sin" + variable;
          break;
        case 1:
          variable = "cos" + variable;
          break;
        case 2:
          variable = "tan" + variable;
          break;
        case 3:
          variable = variable + "²";
          break;
        case 4:
          variable = "√(" + variable + ")";
          break;
        default:
          // Nothing
      }
    }
    return variable;
  }
}

分析:number类将各个难度特殊运算符与操作数共同生成,并且在根号,平方,三角函数运算符后加入括号来避免歧义,值得学习。但其中“rNum”的命名最好采用小驼峰式命名法

 Question类:

abstract class Question {
  public String type;
  public String expression;

  // 拓展题目的方法
  public static void questionEx(StringBuilder buf, User user) {
    Random rNum = new Random();
    // 通过四则运算拓展题目,包含加括号
    switch (rNum.nextInt(8)) {
      case 0:
        buf.append("+").append(NumberMaker.makeNum(user.getType()));
        break;
      case 1:
        buf.append("-").append(NumberMaker.makeNum(user.getType()));
        break;
      case 2:
        buf.append("*").append(NumberMaker.makeNum(user.getType()));
        break;
      case 3:
        buf.append("/").append(NumberMaker.makeNum(user.getType()));
        break;
      case 4:
        buf.insert(0, NumberMaker.makeNum(user.getType()) + "+(").append(")");
        break;
      case 5:
        buf.insert(0, NumberMaker.makeNum(user.getType()) + "-(").append(")");
        break;
      case 6:
        buf.insert(0, NumberMaker.makeNum(user.getType()) + "*(").append(")");
        break;
      case 7:
        buf.insert(0, NumberMaker.makeNum(user.getType()) + "/(").append(")");
        break;
      default:
        //Nothing
    }
  }
}

分析:通过抽象类Question完成包含加减乘除的基础题目,接下来三个具体类QuestionLevel1,QuestionLevel2,QuestionLevel3继承抽象类,在生成题目过程中加入相应难度运算符.

  FileManager类:

class FileManager {
  // 创建文件夹
  public static void createFolder(User user) {
    File fileTotal = new File("D:\\questions");
    if (fileTotal.mkdir()) {
      System.out.println("已在D盘创建questions文件夹");
    }
    File fileUser = new File("D:\\questions\\" + user.getName());
    if (fileUser.mkdir()) {
      System.out.println("已在questions文件夹内创建" + user.getName() + "的文件夹");
    }
  }

  // 创建txt文件
  public static void createTxt(User user) {
    SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
    Date date = new Date(System.currentTimeMillis());
    try {
      File file = new File("D:\\questions\\"
              + user.getName() + "\\" + formatter.format(date) + ".txt");
      if (file.createNewFile()) {
        System.out.println("结果已保存至D盘questions对应文件夹内");
      }
    } catch (IOException e) {
      System.out.println("结果保存失败!");
      e.printStackTrace();
    }
    // 向txt写入题目
    try {
      FileWriter write = new FileWriter("D:\\questions\\"
              + user.getName() + "\\" + formatter.format(date) + ".txt");
      BufferedWriter questions = new BufferedWriter(write);
      int sNum = 0;
      // 将用户类中暂存的题目存入文件中
      while (!user.getQuestions().isEmpty()) {
        sNum++;
        questions.write(sNum + ".  " + user.getQuestions().get(0).expression + "\n\n");
        user.getQuestions().remove(0);
      }
      questions.close();
      write.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  // 读取用户之前的题目
  public static void readTxt(User user, List<String> questionList) {
    // 清空当前列表
    while (!questionList.isEmpty()) {
      questionList.remove(0);
    }
    File file = new File("D:\\questions\\" + user.getName());
    File[] files = file.listFiles();
    // 遍历用户文件夹内文件
    if (files != null) {
      for (File f : files) {
        try {
          // 从缓冲区读取文件内容
          FileReader read = new FileReader(f.getPath());
          BufferedReader questions = new BufferedReader(read);
          String question;
          question = questions.readLine();
          do {
            if (question.length() > 4) {
              question = question.substring(question.indexOf(".  ") + 3);
              questionList.add(question);
            }
            // 跳过空行
            questions.readLine();
            question = questions.readLine();
          } while (question != null);
          questions.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
  }
}

分析:FileManager类用于文件读取写入查重操作,结构清晰,代码简洁易懂。但是存储方式采取绝对路径,此处可以考虑改进。其次,“sNum”的命名最好采用小驼峰式命名法。

  QuestionFactory类:

class QuestionFactory {
  public static Question creat(User user) {
    return switch (user.getType()) {
      case "小学" -> new questionLevel1(user);
      case "初中" -> new questionLevel2(user);
      case "高中" -> new questionLevel3(user);
      default -> null;
    };
  }
}

分析:采用了设计模式中的工厂模式,通过swtich case结构使得难度的选择更为简洁.

 总结:

1.代码作者了解并善于运用java的设计模式,以及高级复杂的结构来使代码更加简洁,高级。

2.作者采用的生成题目的方式具有较高的灵活性。并且合理规范的使用括号来避免题目歧义,值得学习。

3.存储的方式没有采取相对路径,一些“rNum”,“sNum”的小驼峰式命名语义不明确。除此之外,作者对于java的代码规范较为熟悉,并且循规蹈矩,没有其他问题。

 

  4.运行测试

 登录界面:

当输入错误用户名或者不合法同户名,错误密码时均为输出提示

出题界面:

出题界面可以切换模式,当输入符号要求时切换对应模式,否则给出对应提示,输入为-1时退出登录,重新登录

生成题目:

输入不符合10-30的范围时均报错,给出提示信息

在生成题目后可以在输出栏看到题目,并且可以看到存储的文件夹位置

测试三次输出高中题目结果,没有重复题目。

  5.优缺点分析

优点:

  • 代码中包含高级语法,代码结构简洁清晰,可读性高
  • 使用了工厂模式进行设计,增加了可拓展性
  • 正确实现了抽象类与继承抽象类的应用

缺点:

  • 文件存储采取绝对路径存储
  • 一处命名不规范

标签:结对,题目,互评,static,user,数学试卷,new,public,User
From: https://www.cnblogs.com/HNUzhang/p/17717025.html

相关文章

  • 个人项目-小初高算数题目生成(Java互评)
    目录简介测试与分析功能测试代码分析总结一、简介本博客对结对编程队友高义林同学的个人项目进行分析测试,使用语言为Java。需求如下图所示:二、测试与分析1.功能测试1.登录功能测试分析:登录时输入错误账密、错误密码、空的账密均不可成功登录,可......
  • 结对编程队友个人项目互评
    一、项目简介1.项目名称:中小学数学卷子自动生成程序2.项目作者:党郑骅霖3.项目编程语言:Java 二、项目分析1.类图 2.流程图3.代码分析核心方法解析:1.`main`方法:-程序的入口点,包含主要的程序逻辑。-初始化已有用户列表,接收用户输入,允许用户登录,并根据用户的......
  • 软件工程导论个人项目互评
    本博客记录湖南大学2021级软件工程导论个人项目互评与代码分析成员:评价人:软件5班高义林项目作者:软件5班谢宇鑫需求:命令行输入用户名和密码,两者之间用空格隔开(程序预设小学、初中和高中各三个账号,具体见附表),如果用户名和密码都正确,将根据账户类型显示“当前选择为XX出题”,X......
  • 【HNU个人项目互评】--java
    湖南大学软件工程个人项目互评评测者:李姝萱项目作者:张乐盈 一.基本信息:  1.被评队友满足了个人项目要求的所有需求  1.1.登录:只有规定的账户可以登陆,其他的输入不会因为异常抛出强制终止程序 输入不满足格式要求,不会越界异常错误账户不能登陆登陆成功,清晰......
  • 中小学数学卷子自动生成程序——结对编程队友互评
    结对编程队友互评代码:软件2105何志成评价:软件2105陈相彤一、题目介绍用户:小学、初中和高中数学老师。功能:1、命令行输入用户名和密码,两者之间用空格隔开(程序预设小学、初中和高中各三个账号,具体见附表),如果用户名和密码都正确,将根据账户类型显示“当前选择为XX出题”,XX为......
  • HNU个人项目互评博客
    HNU个人项目——中小学数学卷子自动生成程序一.前言本次个人项目中我的搭档袁秀广同学使用了Java进行开发。袁秀广同学的代码实现了自动生成题目的基本功能,注解详细,内容丰富,但在一些细节上也存在一些可优化的地方。二.需求分析1、命令行输入用户名和密码,两者之间用空格隔开(程......
  • 【结对编程互评-C++】中小学数学卷子自动生成程序
    【结对编程互评-C++】中小学数学卷子自动生成程序项目名称:中小学数学卷子自动生成程序编程语言:C++代码作者:李义评价人:张恒硕目录[1.项目要求][1.1目标用户][1.2实现功能][2.代码分析][3.功能测试][3.1登录功能测试][3.2出题功能测试][4.优缺点分析与总结]......
  • 个人项目互评
    结队编程,分析结队队友的代码能够让小组队员之间更加了解彼此的风格。指出队友的优缺点,既能两个人互相提醒改进,也可以在往后的结队编程项目达到更好的效果。后续我将分析队友方缘的C++代码的功能及性能。基本功能实现基本要求:用户:小学、初中和高中数学老师。功能:1、命令行输......
  • 个人项目互评-中小学数学试卷生成
    个人项目互评-中小学数学试卷生成队友:软件2104李锦华队友语言选择:Python题目要求个人项目:中小学数学卷子自动生成程序用户:小学、初中和高中数学老师。功能:1、命令行输入用户名和密码,两者之间用空格隔开(程序预设小学、初中和高中各三个账号,具体见附表),如果用户名和密码都正......
  • 结对项目队友个人项目互评
    一、概述1.项目名称:中小学数学卷子自动生成程序2.编程语言:Python3.目标:分析结对编程队友的个人项目代码,分析其代码的优缺点 二、整体架构1.代码整体基于面向对象的思想,根据功能分为了数量相对较多的类,其类图如下:  根据类图可以总结其思路为:Account作为账户类......