Java教程

结对编程之个人项目代码互评

本文主要是介绍结对编程之个人项目代码互评,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

结对编程之个人项目代码互评

简介

这篇文章是我的结对编程搭档刘正豪——豪神的个人项目代码的总结评价。
豪神使用Java语言实现中小学数学卷子自动生成程序的预期功能,代码结构清晰,其中的某些函数不乏亮点。

项目需求

  • 针对小学、初中和高中数学老师为主体用户的程序
  • 要完成的功能有:
    • 命令行输入用户名和密码进行登录,两者用空格隔开。
    • 登录成功显示用户可生成的题目类型,可以输入所需的题目数量(限制在10-30之间),若输入-1可以退出当前登录并重新登录。
    • 生成的题目保存到目标用户名文件中并以"年-月-日-时-分-秒.txt"的形式保存,每个用户名一个文件夹,每道题目以(+题号+)开头并且每题之间要空一行,同一账号生成的题目不允许和已生成的题目重复。
    • 用户可以在任何时刻输入“切换为”+类型切换到指定教师类型,同时具备该类型老师的出题资格。
  • 备注:
    1. 预制账户:
      账户类型 用户名 密码
      小学 张三1 123
      小学 张三2 123
      小学 张三3 123
      初中 李四1 123
      初中 李四2 123
      初中 李四3 123
      高中 王五1 123
      高中 王五2 123
      高中 王五3 123
    2. 题目要求:
      小学 初中 高中
      难度要求 +,-,*./ 平方、开方 sin,cos,tan
      备注 只能有+,-,*./和() 题目中至少有一个平方或开根号的运算符 题目中至少有一个sin,cos或tan的运算符

代码结构

USer

由于代码全部复制过来太多,只说几个关键的。

public class User {
  private String id;
  private String psw;
  private String type;
  private boolean convert;

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (o == null || getClass() != o.getClass()) {
      return false;
    }
    User user = (User) o;
    return id.equals(user.id) && psw.equals(user.psw);
  }

  @Override
  public int hashCode() {
    return Objects.hash(id, psw);
  }

}

成员属性有4个,convert用于判断后续的是否重新登录的判断。
equals()函数用于登录时的判断
hashCode()函数用于后续查重

Login

剩余的代码都写在了Login里面,由于代码量较大,只展示其中几个关键的函数:

    private void paper(int cnt,User u) throws IOException {
        Random r = new Random();
        String[] specialSigns = {"?","√","sin","cos","tan"};
        HashSet<String> hisQ = historyPaper(u);

        String path = "F:\\4\\Auto_Math\\out\\production\\Mathpaper\\" + u.getId() + "/";
        Calendar date = Calendar.getInstance();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
        String time = formatter.format(date.getTime());
        path = path + time + ".txt";
        //生成题目
        FileWriter fw = new FileWriter(path,true);
        for(int i = 0;i < cnt;i++){
        String question;
        //生成单个题目
        question = singleQuestion(u, r, specialSigns);
        //查询是否与历史题目重复
        if(hisQ.contains(question)){
            i--;
            continue;
        }
        question = "第" + (i + 1) + "题: " + question + "=";
        fw.write(question+"\r\n");
        }
        fw.close();
    }

本次的关键是生成题目,先生成路径后生成题目,生成单个题目之后进行查重,最后输出到文件里,思路清晰,代码简洁。

private String singleQuestion(User u, Random r, String[] specialSigns) {
    String[] signs = {"+","-","×","÷"};
    String question = null;
    String[] opQ = null;
    String type= u.getType();
    switch (type){
      case "小学" -> {
        int opNum = r.nextInt(4) + 2;
        opQ = new String[opNum];
        for(int i = 0;i < opNum;i++){
          opQ[i] = String.valueOf(r.nextInt(100) + 1);
        }
        //括号
        addBracket(r, opQ, opNum);
      }
      case "初中" -> {
        int opNum = r.nextInt(5) + 1;
        opQ = new String[opNum];
        for(int i = 0;i < opNum;i++){
          opQ[i] = String.valueOf(r.nextInt(100) + 1);
        }
        //特殊符号数
        int sopNum = r.nextInt(opNum) + 1;
        while((sopNum--) != 0){
          int rPos = r.nextInt(opNum);
          if(!opQ[rPos].contains("?") && !opQ[rPos].contains("√")){
            opQ[rPos]= r.nextBoolean()? opQ[rPos]+"?": "√"+opQ[rPos];
          }
        }
        addBracket(r, opQ, opNum);
      }
      case "高中" -> {
        int opNum = r.nextInt(5) + 1;
        opQ = new String[opNum];
        for(int i = 0;i < opNum;i++){
          opQ[i] = String.valueOf(r.nextInt(100) + 1);
        }
        //特殊符号数
        int sopNum = r.nextInt(opNum) + 1;
        boolean[] speOpFlag = new boolean[opNum];
        //确保至少有一个三角函数
        int tri = 0;
        while((sopNum--) != 0){
          int rPos = r.nextInt(opNum);
          if(tri == 0 && !opQ[rPos].contains("sin") && !opQ[rPos].contains("cos") && !opQ[rPos].contains("tan")){
            opQ[rPos] = specialSigns[r.nextInt(3)+2] + opQ[rPos];
            tri++;
            speOpFlag[rPos] = true;
          }
          if(!speOpFlag[rPos]){
            int rOp = r.nextInt(5);
            opQ[rPos] = rOp < 1 ? opQ[rPos] + specialSigns[rOp] : specialSigns[rOp] + opQ[rPos];
            speOpFlag[rPos] = true;
          }
        }
        addBracket(r, opQ, opNum);
      }
      default -> System.out.println("error");
    }
    assert opQ != null;

    for(int i = 0;i < opQ.length ;i++){
      int opType = r.nextInt(4);
      question = (question == null?"":question) + (i!=0?signs[opType]:"") + opQ[i];
    }
    return question;
  }

这是生成单个题目的函数,分为三类来进行。逻辑基本是差不多的,先通过随机数生成几个操作数,之后再利用循环判断添加操作符。

  private void addBracket(Random r, String[] opQ, int opNum) {
    boolean bracket = r.nextBoolean() && opNum > 2;
    if(bracket){
      int range = r.nextInt(opNum - 2) + 1;
      int left = r.nextInt(opNum - range);
      opQ[left] = "(" + opQ[left];
      opQ[left+range] =  opQ[left+range] + ")";
    }
  }

括号是在算式最后添加的,通过随机数来确定位置。

private HashSet<String> historyPaper(User u) throws IOException {
    HashSet<String> hisQuestions = new HashSet<>();
    String path = "F:\\4\\Auto_Math\\out\\production\\Mathpaper" + "\\" + u.getId();
    File folder = new File(path);
    if(!folder.exists()){
      folder.mkdir();
    }
    File[] fList = folder.listFiles();
    assert fList != null;
    for(File f : fList){
      if (f.isFile() && f.getName().endsWith(".txt")){
        BufferedReader br = new BufferedReader(new FileReader(f));
        String s;
        while((s = br.readLine()) != null){
          hisQuestions.add(s);
        }
        br.close();
      }
    }
    return hisQuestions;
  }

对于题目查重,豪神采用了哈希表,将同一用户名文件夹下的题目导入哈希表中,挨个查询,这样做大大节省了查询的复杂度,好评!

优缺点分析

优点

  • 因为我使用的C++,在我看来Java的代码更加的简洁,功能强大,同时不会出现编码上的问题,看的出来豪神的编程能力十分强力。
  • 生成题目的方式和我相比非常的易于理解,同时不会出现看起来特别怪异的题目,思路比较清晰。
  • 在查重时使用哈希表,非常的妙啊。

缺点

  • 有些地方命名不是很规范,过于简单,同时有些地方欠缺一点注释,希望下次可以多一点。
  • 初高中题目不够随机,可以有一些复杂符号的多重组合,折磨一下考生(bushi
  • 比较主观的见解:可以分更多的类出来,而不是几乎全部写在其中一个类里面,让代码的复用性更好。

心得

Java还是非常好用的,要今后多学习Java的使用,很多都封装好了可以直接拿来用,不需要我再写了。多看看其他人的代码一方面可以让我学到更多的编程思路,学习其他人的切入点,另一方面通过检查他人代码的缺陷,我也能反省自身,不再犯类似的错误。

这篇关于结对编程之个人项目代码互评的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!