软件工程导论——对结对伙伴袁永杰的个人项目评价

发布时间 2023-09-20 21:32:46作者: 欲掇盈盈玥

一 前言

      很感谢老师安排的这次互评,我从伙伴的代码中得到了一些收获,也对Java编程有了更多的理解,思维也变得更加清晰。同伴选择的也是Java,基于面向对象的思想,在进行评价的同时我也会学习他的优点,不断努力进步。

二 项目需求与评分标准

用户:

小学、初中和高中数学老师。

功能:

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

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

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

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

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

三  测试与评价

     1.登录

能够正常登录,有一定的提示语

  2.切换身份以及退出登录

切换后有提示语,并且进行错误输入时能进行提醒

3.出题

 

能够正常创建文件夹

 

 

能够正常创建试卷并进行规范命名,出题也符合规范,但是初高中的题目中没有设置括号,美中不足

我在运行时每个年级都进行了出题,出题数量不等,未发现有多出少出,试卷合并的情况

 

检查代码书写:

运用了一些抽象类,代码可复用性高,将check抽象,三个年级的查重分别继承,思路清晰。

用户类中使用private,再提供获取信息的函数,安全性高。

代码所使用的类名以及函数名大部分命名符合规范。

代码中有部分精炼注释,可读性高,逻辑紧密。

没有方法代码超过四十行,符合规范。

主函数中只调用了用户类,代码简洁,运行方便。

有一点小小缺点在于进行文件创建时的路径代码中使用的是他电脑的c盘路径,导致换一台电脑运行要改路径,不然会报错。

整体来说实现的非常不错,完成了需求中写到的要求,用户体验良好。

 

四 具体代码

Main

public class Main {

  public static void main(String[] args) {
    //主函数只需要调用登陆类即可。
    Loginstructure loginstructure = new Loginstructure();
    User user = new User();
    loginstructure.logininterface(user);

  }
}

Check

//检查类的抽象类
public abstract class Check {

  abstract int checkright(String[] testpaper, String problem);


}

FileIO

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

//文件流类
public class FileIO {
    //该函数用于检测属于用户的文件夹是否创建,没有则需先按照要求创建文件夹。
    File filecreator(User user) {
        String path = "C:\\Users\\溪午不闻钟\\Desktop\\创新作业\\paper\\" + user.getName();   //保存文件夹的位置。-1
        File file = new File(path);                                   //在该目录下创建一个文件对象。
        Date date = new Date();                                       //用于获取当前时间。
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");//按要求的格式。
        String name = simpleDateFormat.format(date) + ".txt";
        //创建文件夹
        if (!file.exists()) {
            file.mkdirs();
        }
        //创建txt文件
        File txtfile = new File(path, name);
        try {
            txtfile.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return txtfile;
    }

    //写入文件一条数据
    public void writein(File file, Integer n, String title) {
        try {
            //传入文件,类型为续写
            FileWriter fileWriter = new FileWriter(file, true);
            //序号
            String num = n.toString();
            fileWriter.append(num + ". " + title);
            fileWriter.append("\r\n");
            fileWriter.append("\r\n");
            //保存文件
            fileWriter.flush();
            //关闭文件
            fileWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    //将所有数据写入文件
    void writein(User user, String[] testpaper) {
        File writefile = filecreator(user);
        for (int i = 0; i < testpaper.length; i++) {
            writein(writefile, i + 1, testpaper[i]);
        }
    }
}

HighCheck

//高中题目的检查
public class HighCheck extends Check {

  @Override
  int checkright(String[] testpaper, String problem) {
    int errorflag = 0;
    char[] problemCharArray = problem.toCharArray();
    //查重
    for (int i = 0; i < testpaper.length; i++) {
      if (testpaper[i].equals(problem)) {
        errorflag = 1;
      }
    }
    //剔除没有三角函数的问题
    int have = 0;
    for (int i = 0; i < problemCharArray.length; i++) {
      //sin cos 含有s tan 含有a,若是都没有则不合理
      if (problemCharArray[i] == 's' || problemCharArray[i] == 'a') {
        have = 1;
      }
    }
    if (have == 0) {
      errorflag = 1;
    }
    return errorflag;
  }
}

HighTopicgenerater

import java.util.Random;
//出高中题目
public class HighTopicgenerator extends Topicgenerator {

  Random r = new Random();
  //出单到题
  String topic() {
    String problem = new String();
    String[] symbol = new String[]{"+", "-", "*", "/", "sin", "cos", "tan"}; //符号数组
    int breakflag = 0; //暂停标志
    int operationnum = 5; //操作数最多为5
    int flagnum = 0; //记录问题的位数
    while (operationnum-- > 0) {
      int highflag = 0;
      breakflag = r.nextInt(5); //判断是否结束,为1时循环结束,结束后需要加上一个符号位一个数字位。
      int symbolnum = r.nextInt(7); //三角函数
      int symbolnum2 = r.nextInt(4); //常规符号
      if (symbol[symbolnum].equals("sin") || symbol[symbolnum].equals("cos")
          || symbol[symbolnum].equals("tan")) {
        highflag = 1;
      }
      int number1 = r.nextInt(100) + 1; //生成1-100的数
      if (highflag == 1) {
        problem += symbol[symbolnum];
        flagnum++;
      }
      problem += String.valueOf(number1);
      //结束条件,flag!=1保证了不会产生只有一位的算式。
      if ((breakflag == 1 || operationnum == 0) && flagnum != 1) {
        break;
      }
      problem += symbol[symbolnum2];
      flagnum++;
    }
    //补上等于号
    problem += '=';
    return problem;
  }
}
Loginstructure
import java.util.Scanner;
//登录类

public class Loginstructure {

  Scanner in = new Scanner(System.in);

  public void logininterface(User user) {
    System.out.println("输入账号与密码");
    while (true) {
      String input = in.nextLine();
      if (input.equals("-1")) {
        break;
      }
      String[] temparr = input.split(" ");  //将输入分割开账号和密码。
      if (temparr.length != 2) {           //输入显然不为2则错误
        System.out.println("请输入正确的用户名、密码");
      } else {
        user.setName(temparr[0]);
        user.setPassword(temparr[1]);
        if (user.getName().equals("张三1") || user.getName().equals("张三2") || user.getName()
            .equals("张三3")) {
          user.setType("小学");
        }
        if (user.getName().equals("李四1") || user.getName().equals("李四2") || user.getName()
            .equals("李四3")) {
          user.setType("初中");
        }
        if (user.getName().equals("王五1") || user.getName().equals("王五2") || user.getName()
            .equals("王五3")) {
          user.setType("高中");
        }
        if (user.getPassword().equals("123") && !(user.getType().equals("kong"))) {  //账号不对或密码不对都不行
          Operationstructure operationstructure = new Operationstructure();
          operationstructure.operationinterface(user);
        } else {
          System.out.println("请输入正确的用户名、密码");
        }
      }

    }
  }
}

MiddleCheck

//初中题目的检查
public class MiddleCheck extends Check {

  @Override
  int checkright(String[] testpaper, String problem) {
    int errorflag = 0;
    char[] problemCharArray = problem.toCharArray();
    //查重
    for (int i = 0; i < testpaper.length; i++) {
      if (testpaper[i].equals(problem)) {
        errorflag = 1;
      }
    }
    //剔除没有根号或者平方的问题
    int have = 0;
    for (int i = 0; i < problemCharArray.length; i++) {
      //不带有根号或则平方号就错误
      if (problemCharArray[i] == '^' || problemCharArray[i] == '√') {
        have = 1;
      }
    }
    if (have == 0) {
      errorflag = 1;
    }
    return errorflag;
  }
}

MiddleTopicgenreater

import java.util.Random;

public class MiddleTopicgenerator extends Topicgenerator {

  Random r = new Random();
  //问题
  String[] symbol = new String[]{"+", "-", "*", "/", "^2", "√", "sin", "cos", "tan"}; //符号数组
  //出单道初中题目
  @Override
  String topic() {
    String problem = new String();
    int breakflag = 0; //暂停标志
    int operationnum = 5; //操作数最多为5
    int flagnum = 0; //记录问题的位数
    while (operationnum-- > 0) {
      int middleflag = 0;
      breakflag = r.nextInt(5); //判断是否结束,为1时循环结束,结束后需要加上一个符号位一个数字位。
      int symbolnum = r.nextInt(6);
      int symbolnum2 = r.nextInt(4);
      if (symbol[symbolnum].equals("√")) {
        middleflag = 1;
      }
      if (symbol[symbolnum].equals("^2")) {
        middleflag = 2;
      }
      int number1 = r.nextInt(100) + 1; //生成1-100的数
      if (middleflag == 1) {
        problem += symbol[symbolnum];
      }
      if (middleflag == 2) {
        problem += String.valueOf(number1);
        flagnum++;
        problem += symbol[symbolnum];
      }
      if (middleflag == 0 || middleflag == 1) {
        problem += String.valueOf(number1);
        flagnum++;
      }
      //结束条件
      if ((breakflag == 1 || operationnum == 0) && flagnum != 1) {
        break;
      }
      problem += symbol[symbolnum2];
      flagnum++;
    }
    //加等于号
    problem += '=';
    return problem;
  }
}

Operationstructure

import java.util.ArrayList;
import java.util.Scanner;
import java.util.List;

public class Operationstructure {

  Scanner in = new Scanner(System.in);

  void turn(User user, String turntype) {    //转换函数
    int turnok = 0;
    if (turntype.equals("切换为小学")) {
      user.setType("小学");
      turnok = 1;
    }
    if (turntype.equals("切换为初中")) {
      user.setType("初中");
      turnok = 1;
    }
    if (turntype.equals("切换为高中")) {
      user.setType("高中");
      turnok = 1;
    }
    if (turnok != 1) {
      System.out.println("请输入小学、初中和高中三个选项中的一个");
    }
  }

  String[] topicgenerator(User user, int topicnum) {   //题目生成函数
    List<String> testpaper = new ArrayList<>();    //存储题目,使用List类型,方便在数组中增加元素
    //与用户的出题类型有关
    if (user.getType().equals("小学")) {
      PrimaryTopicgenerator primaryTopicgenerator = new PrimaryTopicgenerator();  //小学题目产生
      int topicindex = 0;
      while (topicindex < topicnum) {
        String problem = primaryTopicgenerator.topic();
        PrimaryCheck primaryCheck = new PrimaryCheck();
        String[] temparray = testpaper.toArray(new String[0]);      //将试卷转换为字符串数组类型,方便比较
        //题目检查无误则加入书卷
        if (primaryCheck.checkright(temparray, problem) == 0) {
          testpaper.add(problem);
          topicindex++;
        }
      }
    }
    if (user.getType().equals("初中")) {
      MiddleTopicgenerator middleTopicgenerator = new MiddleTopicgenerator();
      int topicindex = 0;
      while (topicindex < topicnum) {
        String problem = middleTopicgenerator.topic();
        MiddleCheck middleCheck = new MiddleCheck();
        String[] temparray = testpaper.toArray(new String[0]);
        if (middleCheck.checkright(temparray, problem) == 0) {
          testpaper.add(problem);
          topicindex++;
        }
      }
    }
    if (user.getType().equals("高中")) {
      HighTopicgenerator highTopicgenerator = new HighTopicgenerator();
      int topicindex = 0;
      while (topicindex < topicnum) {
        String problem = highTopicgenerator.topic();
        HighCheck highCheck = new HighCheck();
        String[] temparray = testpaper.toArray(new String[0]);
        if (highCheck.checkright(temparray, problem) == 0) {
          testpaper.add(problem);
          topicindex++;
        }
      }
    }
    String[] testpaperArray = testpaper.toArray(new String[0]);
    return testpaperArray;         //返回字符串数组类型的试卷
  }

  void operationinterface(User user) {
    String[] testpaper;
    String input;
    int topicnum;
    while (true) {
      System.out.println("准备生成" + user.getType() + "数学题目");
      System.out.println("请输入你要生成的题目数量,输入-1即退出当前用户重新登录");
      input = in.nextLine();
      char[] tempinput = input.toCharArray();
      //转换指令
      if (tempinput[0] == '切' && tempinput[1] == '换' && tempinput[2] == '为') {
        turn(user, input);
      } else {
        topicnum = Integer.parseInt(input);
        //按要求判断题目数量
        if (topicnum >= 10 && topicnum <= 30) {
          System.out.println("开始生成题目");
          testpaper = topicgenerator(user, topicnum);
          FileIO fileIO = new FileIO();
          fileIO.writein(user, testpaper);
        } else {
          if (topicnum == -1) {
            System.out.println("请重新登录");
            System.out.println("输入账号与密码");
            break;
          }
          System.out.println("输入的数字不符合要求,请重新输入");
        }
      }

    }
  }

}

Person

public abstract class Person {

  private String name;
  private String password;

  public String getName() {
    return name;
  }

  public String getPassword() {
    return password;
  }

  public void setName(String name) {
    this.name = name;
  }

  public void setPassword(String password) {
    this.password = password;
  }


}

PrimaryCheck

public class PrimaryCheck extends Check {

  @Override
  int checkright(String[] testpaper, String problem) {
    int errorflag = 0;
    //查重
    for (int i = 0; i < testpaper.length; i++) {
      if (testpaper[i].equals(problem)) {
        errorflag = 1;
      }
    }
    //剔除大括号
    char problemchar[] = problem.toCharArray();
    if (problemchar[0] == '(' && problemchar[problemchar.length - 2] == ')') {
      errorflag = 1;
    }
    return errorflag;
  }
}

PrimaryTopicgenerater

import java.util.Random;

public class PrimaryTopicgenerator extends Topicgenerator {

  Random r = new Random();

  String topic() {
    String problem = new String();            //问题
    String[] symbol = new String[]{"+", "-", "*", "/", "^2", "√", "sin", "cos", "tan"}; //符号数组
    int breakflag = 0; //暂停标志
    int operationnum = 5; //操作数最多为5
    int leftbracket = 0; //记录左括号初始位
    int bracket = 0; //记录跨括号数
    int flagnum = 0; //记录问题的位数
    while (operationnum-- > 0) {
      breakflag = r.nextInt(5); //判断是否结束,为1时循环结束,结束后需要加上一个符号位一个数字位。
      //随机加入左括号
      if (r.nextInt(2) == 1 && operationnum != 0 && breakflag != 1) {
        leftbracket = flagnum;
        flagnum++;
        bracket++;
        problem += '(';
      }
      int number1 = r.nextInt(100) + 1; //生成1-100的数
      problem += String.valueOf(number1);
      flagnum++;
      //结束条件
      if ((breakflag == 1 || operationnum == 0) && flagnum != 1) {
        break;
      }
      //随机加入右括号
      if (r.nextInt(2) == 1 && operationnum != 0 && breakflag != 1 && bracket != 0
          && (flagnum - leftbracket) > 2) {
        problem += ')';
        flagnum++;
        bracket--;
      }
      //随机加入符号
      int symbolnum = r.nextInt(4);
      problem += symbol[symbolnum];
      flagnum++;
    }
    while (bracket > 0) {
      problem += ')';
      bracket--;
    }
    problem += '=';
    return problem;
  }
}

Topicgenerater

public abstract class Topicgenerator {

  abstract String topic();
}

User

public class User extends Person {

  private String name;
  private String password;
  private String type;

  public User() {
    this.type = "kong";
  }

  public String getType() {
    return type;
  }

  public void setType(String type) {
    this.type = type;
  }
}

 

 

五 总结

       通过这次互评,我们都发现了对方与自己的优缺点,也向对方进行了学习,改正了一些自己的缺点。我对Java编程思想有了更深的理解,也记住了一些编程时必须注意的细节,获得了一些新的思路。总的来说,这次互评我受益匪浅!