首页 > 编程语言 >个人项目-小初高算数题目生成(Java互评)

个人项目-小初高算数题目生成(Java互评)

时间:2023-09-20 13:35:15浏览次数:45  
标签:curUser Java String 互评 小初 User File new public

目录

  1. 简介
  2. 测试与分析
    1. 功能测试
    2. 代码分析
  3. 总结

一、简介

    本博客对结对编程队友高义林同学的个人项目进行分析测试,使用语言为Java。需求如下图所示:

二、测试与分析

1.功能测试

   1.登录功能测试

  分析:登录时输入错误账密、错误密码、空的账密均不可成功登录,可以满足普通的登陆需求,且提示到位,登录成功后出现准备生成题目提示,符合要求。

  分析:可以正常退出登录,退出之后可以再次登录,满足日常需要。

  2.生成题目功能与切换难度功能测试

  分析:输入10~30之间的数字可以正常生成试卷,输入不符合要求的数字会出现错误提示并返回生成界面,符合需求。试卷文件名以规定时间格式命名,每道题目之间以空行隔开,以题号开头,整洁美观,符合需求。

  分析:切换时输入错误会触发提示信息,输入正确后成功切换,生成的题目难度也切换完毕。

2.代码分析

  1.项目结构

    本项目共有7个类,包含2个抽象类Question和Check,其余5个类分别是CheckUnit,FileProduct,Main,QuestionUnit,User。其中QuestionUnit类继承Question类,CheckUnit类继承Check类,实现抽象方法。

  CheckUnit类

实现抽象类Check功能,完成查重操作

FileProduct类

    生成试卷的文件操作

  Main类

  初始化账户,实现操作界面

QuestionUnit类

      生成题目

  User类

      账户类型

  2.代码分析

  • Main.java
  • import java.util.ArrayList;
    import java.util.Scanner;
    
    public class Main {
      public static boolean flag;
      public static ArrayList<User> userList;
      public static User curUser;
    
      public static void initArray() {
        userList = new ArrayList<>();
        userList.add(new User("小学", "张三1", "123"));
        userList.add(new User("小学", "张三2", "123"));
        userList.add(new User("小学", "张三3", "123"));
        userList.add(new User("初中", "李四1", "123"));
        userList.add(new User("初中", "李四2", "123"));
        userList.add(new User("初中", "李四3", "123"));
        userList.add(new User("高中", "王五1", "123"));
        userList.add(new User("高中", "王五2", "123"));
        userList.add(new User("高中", "王五3", "123"));
      }
    
      public static void mainMenu() {
        System.out.println("请输入用户名和密码,两者之间用空格隔开,或输入exit退出");
        while (!flag) {
          String temp;
          Scanner scanner = new Scanner(System.in);
          temp = scanner.nextLine();
          if (temp.equals("exit")) {
            flag = true;
            System.out.println("系统退出");
            continue;
          }
          String[] tempUser = temp.split(" ");
          if (tempUser.length != 2) {
            System.out.println("请输入正确的用户名、密码”,重新输入用户名、密码");
          } else {
            for (User user : userList) {
              if (user.getName().equals(tempUser[0]) && user.getPassword().equals(tempUser[1])) {
                curUser.setName(user.getName());
                curUser.setPassword(user.getPassword());
                curUser.setType(user.getType());
                flag = true;
                break;
              }
            }
            if (!flag) System.out.println("请输入正确的用户名、密码”,重新输入用户名、密码");
            else {
              testProductMenu(curUser);
              flag = false;
              curUser = new User();
              System.out.println("请输入用户名和密码,两者之间用空格隔开,或输入exit退出");
            }
          }
        }
      }
    
      public static void testProductMenu(User curUser) {
        boolean flag = true;
        while (flag) {
          System.out.println("准备生成" + curUser.getType() + "数学题目,请输入生成题目数量");
          System.out.println("题目数量在10~30之间,或输入-1退出登录,或输入”切换为xx“更换出卷类型");
          Scanner scanner = new Scanner(System.in);
          String temp = scanner.nextLine();
          if (temp.length() > 3 && temp.startsWith("切换为")) {
            temp = temp.substring(3);
            switch (temp) {
              case "小学" -> curUser.setType("小学");
              case "初中" -> curUser.setType("初中");
              case "高中" -> curUser.setType("高中");
              default -> System.out.println("请输入小学、初中和高中三个选项中的一个");
            }
          } else {
            int num;
            try {
              num = Integer.parseInt(temp);
              if (num == -1) {
                flag = false;
                System.out.println("退出登录");
              } else if (num >= 10 && num <= 30) {
                FileProduct.createTest(curUser, num);
              } else System.out.println("输入数量不在10~30之间");
            } catch (NumberFormatException exc) {
              System.out.println("输入格式错误");
            }
          }
        }
      }
    
      public static void main(String[] args) {
        flag = false;
        curUser = new User();
        initArray();
        mainMenu();
      }
    }

  分析:Main类中实现了整个界面操作,flag变量标记是否切换界面。首先创建当前用户,初始化用户列表,进入主菜单,随后进行菜单操作。

  • FileProduct.java
  • import java.io.File;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    public class FileProduct {
      public static CheckUnit checkUnit = new CheckUnit();
      public static QuestionUnit questionUnit = new QuestionUnit();
    
      public static void createTest(User curUser, int num) {
        File file = createFile(curUser);
        File checkFile = checkUnit.getDir();
        FileWriter fileWriter;
        FileWriter fileWriter1;
        try {
          fileWriter = new FileWriter(file, true);
          fileWriter1 = new FileWriter(checkFile, true);
        } catch (IOException e) {
          throw new RuntimeException(e);
        }
        String tempQuestion;
        for (int i = 0; i < num; i++) {
          tempQuestion = formatQuestion(curUser, i, fileWriter1);
          try {
            fileWriter.write(tempQuestion + "\n\n");
          } catch (IOException e) {
            throw new RuntimeException(e);
          }
        }
        try {
          fileWriter.close();
          fileWriter1.close();
        } catch (IOException e) {
          throw new RuntimeException(e);
        }
        System.out.println("试卷创建成功");
      }
    
      public static File createFile(User curUser) {
        Date date = new Date();
        String time = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(date);
        String path =
            System.getProperty("user.dir") + "\\user\\" + curUser.getName() + "\\" + curUser.getType();
        String filename = time + ".txt";
        File file = new File(path + "\\" + filename);
        File dir = new File(path);
        if (!dir.exists()) {
          dir.mkdirs();
        }
        dir = new File(path + "\\check.txt");
        checkUnit.setFile(file);
        checkUnit.setDir(dir);
        return file;
      }
    
      public static String formatQuestion(User curUser, int i, FileWriter fileWriter) {
        boolean flag;
        String tempQuestion = "";
        flag = false;
        while (!flag) {
          int typeNum = 0;
          if (curUser.getType().equals("小学")) typeNum = 1;
          else if (curUser.getType().equals("初中")) typeNum = 2;
          else if (curUser.getType().equals("高中")) typeNum = 3;
          tempQuestion = questionUnit.createQuestion(typeNum) + "=";
          flag = checkUnit.checkQuestion(tempQuestion);
          if (flag) {
            try {
              fileWriter.write(checkUnit.hashCode(tempQuestion) + "\n");
            } catch (IOException e) {
              throw new RuntimeException(e);
            }
          }
          tempQuestion = i + 1 + ". " + tempQuestion;
        }
        return tempQuestion;
      }
    }

  分析:此类主要由三个方法组成,完成对文件的操作。首先createFile方法准备好文件路径,formatQuestion方法调用questionUnit.createQuestion方法和checkUnit.checkQuestion方法实现单个题目的生成和查重,最后上述两种方法被createTest方法调用生成整张试卷。

  • User.java
  • public class User {
      String name;
      String type;
      String password;
    
      public User() {}
    
      public User(String type, String name, String password) {
        this.type = type;
        this.name = name;
        this.password = password;
      }
    
      public String getName() {
        return name;
      }
    
      public void setName(String name) {
        this.name = name;
      }
    
      public String getPassword() {
        return password;
      }
    
      public void setPassword(String password) {
        this.password = password;
      }
    
      public String getType() {
        return type;
      }
    
      public void setType(String type) {
        this.type = type;
      }
    }

  分析:实现了User类的三个属性的构造和调用。

  • Check.java
  • import java.io.File;
    
    public abstract class Check {
      static File file;
      static File dir;
    
      public abstract File getFile();
    
      public abstract void setFile(File file);
    
      public abstract File getDir();
    
      public abstract void setDir(File dir);
    
      public abstract Boolean checkQuestion(String question);
    
      public abstract String hashCode(String question);
    }

  分析:实现了抽象方法的定义。

  • Question.java
  • public abstract class Question {
      public static final String[] operator0 = {"+", "-", "*", "/"};
      public static final String[] operator1 = {"sqrt", "^2"};
      public static final String[] operator2 = {"sin", "cos", "tan"};
    
      public abstract String createQuestion(int typeNum);
    }

  分析:实现了抽象方法的定义。

  • CheckUnit.java
  • import java.io.*;
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    
    public class CheckUnit extends Check {
      @Override
      public File getFile() {
        return file;
      }
    
      @Override
      public void setFile(File file) {
        Check.file = file;
      }
    
      @Override
      public File getDir() {
        return dir;
      }
    
      @Override
      public void setDir(File dir) {
        Check.dir = dir;
      }
    
      @Override
      public Boolean checkQuestion(String question) {
        FileReader fileReader;
        try {
          fileReader = new FileReader(dir);
        } catch (FileNotFoundException e) {
          throw new RuntimeException(e);
        }
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        question = hashCode(question);
        try {
          String temp = bufferedReader.readLine();
          while (temp != null) {
            if (temp.equals(question)) {
              System.out.println("A question is already in the database");
              return false;
            }
            temp = bufferedReader.readLine();
          }
        } catch (IOException e) {
          throw new RuntimeException(e);
        }
        return true;
      }
    
      @Override
      public String hashCode(String question) {
        MessageDigest md;
        try {
          md = MessageDigest.getInstance("SHA-256");
        } catch (NoSuchAlgorithmException e) {
          throw new RuntimeException(e);
        }
        byte[] hashInBytes = md.digest(question.getBytes());
        StringBuilder sb = new StringBuilder();
        for (byte b : hashInBytes) {
          sb.append(String.format("%02x", b));
        }
        return sb.toString();
      }
    }

  分析:继承抽象类,实现抽象方法。主要功能由checkQuestion方法和hashCode方法实现。其中checkQuestion方法逐条检查历史记录文件,寻找重复题目,hashCode方法将题目转换为哈希码实现加密,最后查重比较哈希码是否相同。

  • QuestionUnit.java
  • import java.util.Random;
    
    public class QuestionUnit extends Question {
    
      @Override
      public String createQuestion(int typeNum) {
        Random rand = new Random();
        int num = rand.nextInt(5) + 1;
        if (typeNum == 1) {
          num = rand.nextInt(4) + 2;
        }
        String[] numberList = new String[num];
        for (int i = 0; i < num; i++) {
          numberList[i] = String.valueOf(rand.nextInt(100) + 1);
        }
        String Question = "";
        int pos = rand.nextInt(num) + 1, caseNum;
        for (int i = 1; i <= num; i++) {
          if (typeNum == 2 && i == pos) {
            caseNum = rand.nextInt(2) + 1;
            if (caseNum == 1) Question += operator1[0] + "(" + numberList[i - 1] + ")";
            else if (caseNum == 2) Question += numberList[i - 1] + operator1[1];
          } else if (typeNum == 3 && i == pos) {
            caseNum = rand.nextInt(3) + 1;
            if (caseNum == 1) Question += operator2[0] + "(" + numberList[i - 1] + ")";
            else if (caseNum == 2) Question += operator2[1] + "(" + numberList[i - 1] + ")";
            else if (caseNum == 3) Question += operator2[2] + "(" + numberList[i - 1] + ")";
          } else Question += numberList[i - 1];
          if (i != num) Question += operator0[rand.nextInt(operator0.length)];
        }
        return Question;
      }
    }

  分析:此类继承Question类,实现抽象方法createQuestion。其主要思想在于先确定生成操作数的数量,然后选定一个操作数,根据不同难度对其进行不同操作。例如生成了五个操作数12345,选定4进行高中难度转换,就可能变成123sqrt(4)5,最后用随机符号依次拼接即可。但是这样只会对一个操作数进行难度转换。

三、总结

  此项目基本完成了所给需求,测试下来也没有bug,使用体验良好,稍加修改即可成为一个实用的小程序。此外,还有许多地方可以进行功能升级,例如将账户信息保存到本地或者云端,实现初高中难度的多个操作数难度转换,在生成试卷时等待1秒避免题目数据重复写入等功能。

标签:curUser,Java,String,互评,小初,User,File,new,public
From: https://www.cnblogs.com/H-v-H/p/17715848.html

相关文章

  • 无涯教程-JavaScript - AVERAGE函数
    描述AVERAGE函数返回参数的平均值(算术平均值)。语法AVERAGE(number1,[number2]...)争论Argument描述Required/OptionalNumber1Thefirstnumber,cellreference,orrangeforwhichyouwanttheaverage.RequiredNumber2,...Additionalnumbers,cellrefe......
  • 结对编程队友个人项目互评
    一、项目简介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.优缺点分析与总结]......
  • Java 内存模型
    目录并发编程模型的两个关键问题Java内存模型共享变量Java内存模型的抽象结构如何保证内存可见性?JMM与Java运行时内存区域的区别区别联系总结JMM与重排序为什么指令重排序可以提高性能?重排序有哪几种?JMM与顺序一致性模型什么是顺序一致性模型?JMM为什么不保证顺序一致性?JMM......
  • JAVA17/JAVA21接口和多态机制
    day08-JAVAOOP课程目标1.【理解】什么是接口2.【掌握】接口的定义格式3.【掌握】接口的使用4.【理解】接口的成员特点5.【理解】类和接口抽象类和接口之间的关系6.【掌握】单继承多实现7.【理解】接口之间的多继承8.【掌握】接口的案例9.【理解】什么是多态......
  • java dom4j操作xml
    SAXReaderreader=newSAXReader();Documentdoc=reader.read(...);ListchildNodes=doc.selectNodes("//Config/Child/ChildNode");for(Objectobj:childNodes){NodechildNode=(Node)obj;Stringname=childNode.......