首页 > 编程语言 >个人项目分析——中小学生数学卷子自动生成程序

个人项目分析——中小学生数学卷子自动生成程序

时间:2023-09-20 13:44:26浏览次数:37  
标签:中小学生 题目 String 生成 user 卷子 new 项目分析 输入

目录

一. 简介

二. 项目要求

三. 代码分析

  整体架构

  核心代码

四. 功能测试

五. 优缺点总结

 

一. 简介

  本篇博客为对廖心怡同学的个人编程项目 “中小学数学卷子自动生成程序” 的分析与总结,在阅读代码的过程中学习到了许多优点,也发现了一些代码书写、代码结构等方面的不足,希望可以对该同学接下来的学习有所帮助。

 

 

二. 项目要求

面向用户:

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

用户登录:

  • 命令行输入账号和密码,中间用空格隔开;
  • 输入错误或用户不存在,给出提示 “请输入正确的用户名、密码” ;
  • 输入正确即输入用户存在显示“当前选择为XX出题”(XX为小学、初中和高中三个选项中的一个)。

生成试卷:

  • 登录后,系统提示 “准备生成XX数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录):”;
  • 用户输入所需出的卷子的题目数量,每道题目的操作数在1-5个之间,操作数取值范围为1-100;
  • 题目数量的有效输入范围是“10-30”(含10,30,或-1退出登录);
  • 同一个老师的卷子中的题目不能与以前的已生成的卷子中的题目重复。

切换类型:

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

文件要求:

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

 

 

三. 代码分析

整体架构:

  该项目共有八个java文件,包含七个类一个接口:题目生成类StyleChange、小学试卷类Primary、初中试卷类Junior、高中试卷类Senior、试卷生成接口Function、用户类User、登录界面类Login、主函数所在类Main,对类进行提取和功能封装,做到了模块化。

 

核心代码:

StyleChange.java

  该类包含六个函数,方法有切换类型函数changeStyle、生成题目函数doPapersOut,以及三个不同类型的生成题目函数。

  三个不同类型的生成题目函数结构基本相同,分析随机生成题目函数doSeniorPapers:首先生成一个操作符,如果是“(”则加入题目,再获取三角函数操作数,有1/2概率加入题目,然后再添加一个操作数;之后随机生成除+ - * /外的特殊操作符数量,for循环随机生成特殊操作符,如果是“(”或“)”则根据情况添加,其余的特殊操作符均有1/2的概率加入,再添加操作数,每次for循环加入+ - * /中的一个,这样for循环结束便生成了一个题目。思路清晰,易于理解,生成的题目也能较好的满足要求。

  存在的问题是,没有考虑一个操作数带括号和整个题目带括号的情况。

 1   public String doSeniorPapers() {
 2     Random random = new Random();
 3     StringBuilder problem = new StringBuilder();
 4     String operator = operatorList.get(random.nextInt(6));
 5     int leftbraket = 0;     //左括号个数
 6     int sympleNum  = 0;
 7     if (operator.equals("(")) {
 8       problem.append(operator);
 9       leftbraket++;
10     }
11     if (random.nextBoolean()) {
12       problem.append(operatorList.get(random.nextInt(3)+8));
13       sympleNum++;
14     }
15     problem.append(random.nextInt(100)+1);
16     operator = operatorList.get(random.nextInt(11));
17     if (operator.equals(")") && leftbraket!=0) {
18       problem.append(operator);
19       leftbraket--;
20     }
21     int operatorNum = random.nextInt(4) + 1;
22     for(int i=0; i<operatorNum; i++) {
23       problem.append(operatorList.get(random.nextInt(4)));
24       operator = operatorList.get(random.nextInt(11));
25       if (operator.equals("(")) {
26         problem.append(operator);
27         leftbraket++;
28       }
29       if (random.nextBoolean()) {
30         problem.append(operatorList.get(random.nextInt(3)+8));
31         sympleNum++;
32       }
33       if (i==operatorNum-1 && sympleNum==0) {
34         problem.append(operatorList.get(random.nextInt(3)+8));
35       }
36       problem.append(random.nextInt(100)+1);
37       operator = operatorList.get(random.nextInt(11));
38       if (operator.equals(")") && leftbraket!=0) {
39         problem.append(operator);
40         leftbraket--;
41       }
42     }
43     for (int i = 0; i<leftbraket; i++) {
44       problem.append(")");
45     }
46     return problem.toString();
47   }
doSeniorPapers

 

Primary.java、Junior.java、Senior.java

  三各类包含的方法相同,试卷生成界面outPapers、写入文件函数writeFile、查重函数checkRepeat。

  outPapers函数根据用户类型和输入的题目数量生成试卷。但是该函数同时具有类型切换功能,存在不合理性。

 1   public void outPapers(User user, int questionNum, String grade) {
 2     Scanner sr = new Scanner(System.in);
 3     if (questionNum >= 10 && questionNum <= 30) {
 4       StyleChange output = new StyleChange();
 5       writeFile(user, questionNum, grade, output);
 6       System.out.println("题目已生成,请查看!");
 7       System.out.println("是否切换用户类型?");
 8       if (sr.next().equals("是")) {
 9         output.changeStyle(user);
10       } else {
11         System.out.println("已退出登录!!");
12       }
13     } else if (questionNum == -1) {
14       System.out.println("已退出登录!!");
15       System.out.println("请输入用户名、密码:");
16       Login login = new Login();
17       login.loginSystem(sr.next(), sr.next());
18     } else {
19       System.out.println("请输入范围为10-30的题目数量:");
20       outPapers(user, sr.nextInt(), user.getGrade());
21     }
22   }
outPapers

  writeFile函数是生成试卷,使用了一系列文件生成与书写的函数,运用了try-catch-finally结构,代码完整清晰。

 1   public void writeFile(User user, int questionNum, String grade, StyleChange output) {
 2     String filePath = "D:/mathPapers/" + user.getGrade() + "/" + user.getUserName();
 3     Date date = new Date();
 4     SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-hh-mm-ss");
 5     String childPath = sdf.format(date) + ".txt";
 6     FileWriter fw = null;
 7     try {
 8       File file = new File(filePath, childPath);
 9       if (!file.exists()) {
10         file.createNewFile();
11       }
12       fw = new FileWriter(filePath + "/" + childPath);
13       BufferedWriter bw = new BufferedWriter(fw);
14       int tcount = 0; // 题目编号
15       while (true) {
16         tcount++;
17         if (!checkRepeat(file, output.doPapersOut(grade))) {
18           bw.write(tcount + ":" + output.doPapersOut(grade) + "=\n");
19           bw.write("\n");
20           questionNum--;
21         }
22         if (questionNum == 0) {
23           break;
24         }
25       }
26       bw.close();
27     } catch (Exception e) {
28       e.printStackTrace();
29     } finally {
30       try {
31         fw.close();
32       } catch (Exception e) {
33         e.printStackTrace();
34       }
35     }
36 
37   }
writeFile

   checkRepeat函数对检查生成的题目是否在为该用户生成过,方法为遍历用户的每一个试卷文件,对每一个试卷文件遍历其每一行,获取题目,与生成题目进行比对,生成过则返回true,否则返回false。

 1   public boolean checkRepeat(File file, String problem) {
 2     boolean repeatOrNot = false;
 3     String path = file.getParent();
 4     File parentFile = new File(path);
 5     File[] files = parentFile.listFiles();
 6     for (int i = 0; i < files.length; i++) {
 7       try {
 8         FileReader fileReader = new FileReader(files[i]);
 9         BufferedReader br = new BufferedReader(fileReader);
10         while (true) {
11           String line = br.readLine();
12           // if (line.equals("\n")) {
13           // continue;
14           // }
15           if (line == null) {
16             break;
17           }
18           String[] testLine = line.split(":");
19           if (testLine.length > 1) {
20             if (testLine[1].equals(problem)) {
21               repeatOrNot = true;
22             }
23           }
24         }
25       } catch (Exception e) {
26         e.printStackTrace();
27       }
28     }
29     return repeatOrNot;
30   }
checkRepeat

 

Function.java

  试卷生成接口,包含outPapers函数,Primary、Junior、Senior类分别实现该函数。

1 interface Function {
2   public void outPapers(User user, int questionNum, String grade);
3 }
interface Function

 

User.java

  用户类,包含用户的账号、密码、类型属性和getUserName、getPassPort、getGrade获取属性方法。

 1 public class User {
 2   private String userName;
 3   private String passPort;
 4   private String grade;
 5   public User(String userName, String passPort, String grade) {
 6     this.userName = userName;
 7     this.passPort = passPort;
 8     this.grade    = grade;
 9   }
10   public String getUserName() {
11     return userName;
12   }
13   public String getPassPort() {
14     return passPort;
15   }
16   public String getGrade() {
17     return grade;
18   }
19 }
class User

 

Login.java

  用户登录之前通过生成Login实体加载已存在用户,存入哈希表userHashMap中,用户输入账号密码进行登录时,loginSysem函数进行检查,看输入的用户是否存在于userHashMap。

  分析loginSystem函数,利用containsKey函数判断用户名及密码是否存在,如果存在则登陆成功,提示输入题目数量来生成试卷,否则重新输入。

 1   public void loginSystem (String userName, String passPort) {
 2     if (userHashMap.containsKey(userName)) {
 3       User user = userHashMap.get(userName);
 4       if (user.getPassPort().equals(passPort)) {
 5         System.out.println("当前选择为" + user.getGrade() + "出题");
 6         System.out.println("准备生成" + user.getGrade() + "数学题目,请输入生成题目数量:");
 7         Scanner sr = new Scanner(System.in);
 8         if (user.getGrade().equals("小学")) {
 9           Function outWithPapers = new Primary();
10           outWithPapers.outPapers(user, sr.nextInt(), user.getGrade());
11         } else if (user.getGrade().equals("初中")) {
12           Function outWithPapers = new Junior();
13           outWithPapers.outPapers(user, sr.nextInt(), user.getGrade());
14         } else if (user.getGrade().equals("高中")) {
15           Function outWithPapers = new Senior();
16           outWithPapers.outPapers(user, sr.nextInt(), user.getGrade());
17         }
18       } else {
19         System.out.println("请输入正确的用户名和密码:");
20         Scanner sr = new Scanner(System.in);
21         loginSystem(sr.next(), sr.next());
22       }
23     } else {
24         System.out.println("请输入正确的用户名和密码:");
25         Scanner sr = new Scanner(System.in);
26         loginSystem(sr.next(), sr.next());
27     }
28   }
loginSystem

 

Main.java

  包含主函数,用来加载系统。存在的不足是,输入的账号密码是一个包含空格的字符串,应该分别提取账号密码传入loginSysem,而直接用(input.next(), input.next())传入参数会使账号和密码可以换行输入,不满足要求。

1 public class Main {
2     public static void main(String[] args) {
3         Scanner input = new Scanner(System.in);
4         System.out.println("请输入用户名、密码:");
5         Login login = new Login();
6         login.loginSystem(input.next(), input.next());
7     }
8 }
class Mian

 

 

四. 功能测试

  按照正确格式输入正确的账号密码可以成功登录,但是没有提示输入格式“输入账号和密码,中间用空格隔开”;另外,可以看出代码书写也有问题,账号密码用空格隔开或者换行都可以成功登录。

  输入有效的题目数量可以成功生成试卷,输入无效的题目数量也会给出提示。

  生成的题目数量正确,每题操作数为1-5,操作数的值为1-100;但是有的题目括号里只有一个操作数,有的题目首尾用括号括起,不符合习惯。

  正确输入后可以成功切换类型,之后也可以正常生成切换类型后的试卷,但是没有提示正确的输入格式;输入错误后没有给出提示,而是直接退出系统,即未对错误输入作出处理,不能连续生成试卷。

  输入-1可以退出程序,但是没有给出文字描述提示该功能;要求输入-1退出登录后可以重新登录,而这里直接退出程序,不满足要求。

 

 

五. 优缺点总结

 优点:

  1. 代码书写规范,遵守Google的Java代码规范,清晰易读;
  2. 对数据结构及相关函数的使用合理,程序编写简洁完善;
  3. 进行了类的提取和方法封装,使用接口,便于扩展;
  4. 题目生成基本满足要求;
  5. 进了异常处理操作;
  6. 实现了基本功能,功能完善。

缺点:

  1. 有的方法的功能混乱,没能进行合理的封装。比如,outPapers函数的切换类型功能单独分离出来作为一个方法更好;
  2. 类的方法划分不合理,有多处函数重复实现、某个函数在某个类中不合理的问题。比如,Primary、Junior、Senior类的三个方法函数完全相同,可以将三个函数提取出来封装到一个类中,再考虑这三个类与新产生的类的关系,合理划分;
  3. 函数调用混乱,使程序存在多处不合理的地方;比如,切换类型输入错误直接退出程序、生成一次试卷后直接询问是否切换类型而无法多次生成试卷等;
  4. 缺少文字提示,影响使用;比如,没有提示账号密码、切换类型的输入格式,没有提示输入-1退出登录等;
  5. 生成的题目规范性不强;比如,单个操作数会加上括号、整个式子会加上括号等;
  6. 文件使用了绝对地址,使用相对地址更好。

标签:中小学生,题目,String,生成,user,卷子,new,项目分析,输入
From: https://www.cnblogs.com/yusiyany/p/17716668.html

相关文章

  • 中小学数学卷子自动生成程序——结对编程队友互评
    结对编程队友互评代码:软件2105何志成评价:软件2105陈相彤一、题目介绍用户:小学、初中和高中数学老师。功能:1、命令行输入用户名和密码,两者之间用空格隔开(程序预设小学、初中和高中各三个账号,具体见附表),如果用户名和密码都正确,将根据账户类型显示“当前选择为XX出题”,XX为......
  • 【结对编程互评-C++】中小学数学卷子自动生成程序
    【结对编程互评-C++】中小学数学卷子自动生成程序项目名称:中小学数学卷子自动生成程序编程语言:C++代码作者:李义评价人:张恒硕目录[1.项目要求][1.1目标用户][1.2实现功能][2.代码分析][3.功能测试][3.1登录功能测试][3.2出题功能测试][4.优缺点分析与总结]......
  • HNU个人项目互评——中小学数学卷子自动生成程序
    HNU个人项目互评——中小学数学卷子自动生成程序代码作者:刘蕴哲评价人:李锦华一、个人项目需求1.用户小学、初中和高中数学老师。2.功能(1)命令行输入用户名和密码,两者之间用空格隔开(程序预设小学、初中和高中各三个账号,具体见附表),如果用户名和密码都正确,将根据账户类型显......
  • 中小学数学卷子自动生成程序-个人项目互评
    前言:首先,很有幸能有这样一次和队友互相学习的机会。正好我们两个人都是选择的C++,通过对比分析对方的代码,学习到了很多,也深刻认识到了自己的不足,还有很长的路要走。程序结构:队友的代码用了一个cpp文件便包含了所有代码,这稍微有点不好,如果能够将各个功能函数各自放在头文件,就能让......
  • 个人项目:中小学数学卷子自动生成程序互评
    前言:我和队友使用的都是c++来实现这个程序,通过沟通交流,我们明白了彼此代码的优缺点,对这个程序有了更深的理解。 结构:队友的代码主要包括一个cpp文件和三个h头文件,将功能函数分散开来,我觉得这是一个很好的点。优点:1.功能分解成了多个函数,在运行时方便查找错误出现的位置; ......
  • HNU个人项目互评——中小学数学卷子自动生成程序
    结对编程互评代码作者:软件2104潘胜蓝互评作者:软件2104苏晨阳一、摘要该作业是由潘胜蓝同学使用Java语言完成的“中小学数学卷子自动生成程序”。在代码设计方面,对小学教师、初中教师、高中教师三种角色属性进行了抽象提取,利用java抽象类和继承的优点进行编写;通过自行编......
  • HNU个人项目互评:中小学数学卷子自动生成程序
    一、功能测试1.登录功能命令行输入用户名与密码,当用户名与密码都正确时,显示当前为XX出题 正常输入时功能正常,但是当只输入用户名时发生了异常,应该是没有考虑只输入一个(没有测试bug呀!)Stringstr[]=in.nextLine().split("\\s+");nuser.setName(str[0]);......
  • HNU个人项目中小学数学卷子自动生成程序互评
    一、简介本博客是对结对编程队友代码的分析与总结,代码使用语言为JAVA。完成情况:很好的实现了项目的需求,功能完整。同时每个页面的提示信息都比较完整,在不需要他人协助的情况下,可以根据屏幕上的提示信息进行操作,如果用户输入不正确,系统会出现指示,显示正确输入格式,用户可根据提示......
  • 中小学数学卷子生成程序-个人项目互评
    一、项目需求用户:小学、初中和高中数学老师。功能:命令行输入用户名和密码,两者之间用空格隔开(程序预设小学、初中和高中各三个账号,具体见附表),如果用户名和密码都正确,将根据账户类型显示“当前选择为XX出题”,XX为小学、初中和高中三个选项中的一个。否则提示“请输入正确的用户......
  • 分析队友个人项目:中小学数学卷子自动生成程序
    一、前言  上周完成了个人项目的编写。这里对伙伴的个人项目代码稍作分析,学习她的长处,分析不足,使我们都能得到进步。二、分析(一)功能需求:  总的来说,队友的项目实现了老师给出的需求,可以进行登录、切换登录、出题、题目查重、切换试卷类型等功能。在对细节的处理上,队友的......