这个作业属于哪个课程 | 软工23级 |
---|---|
这个作业要求在哪里 | 作业要求链接 |
这个作业的目标 | 合作实现一个自动生成小学四则运算题目的命令行程序 |
项目成员 | 陈日强 3123004736, 李铭恩 3123004745 |
Github仓库链接 | Math-Quiz-Generator |
一、PSP表格
PSP2.1 阶段 | 任务 | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 60 | 65 |
· Estimate | 估计任务所需时间 | 60 | 65 |
Development | 开发 | 600 | 620 |
· Analysis | 需求分析(包括学习新技术) | 80 | 85 |
· Design Spec | 生成设计文档 | 60 | 65 |
· Design Review | 设计复审(和同事审核设计文档) | 40 | 45 |
· Coding Standard | 代码规范(为目前的开发制定规范) | 30 | 35 |
· Design | 具体设计 | 60 | 70 |
· Coding | 具体编码 | 180 | 190 |
· Code Review | 代码复审 | 50 | 55 |
· Test | 测试(自我测试,修改代码,提交修改) | 100 | 110 |
Reporting | 报告 | 90 | 100 |
· Test Report | 测试报告 | 40 | 45 |
· Size Measurement | 计算工作量 | 30 | 35 |
· Postmortem & Process Improvement Plan | 事后总结,并提出过程改进计划 | 20 | 20 |
合计 | 900 | 900 |
二、性能分析图
三、设计实现过程
QuizGeneratorApp.java:主应用程序类,处理用户交互和命令行参数
manager:管理器包
ExerciseFileManager.java:管理练习题和答案文件的创建、读取和写入
QuizExpressionManager.java:可能用于管理表达式的生成和处理
generator:生成器包
ExpGenerator.java:用于生成数学表达式
evaluator:评估器包
ExpsEvaluator.java:用于评估数学表达式
各类之间的关系
QuizGeneratorApp:作为应用程序的入口,负责用户交互和命令行参数解析。它使用ExerciseFileManager来管理文件操作,并调用ExpGenerator和ExpsEvaluator来生成和评估数学表达式。
ExerciseFileManager:负责文件的创建、读取和写入操作,确保生成的练习题和答案被正确保存。
ExpGenerator:生成数学表达式,供QuizGeneratorApp使用。
ExpsEvaluator:评估生成的数学表达式,计算其结果
四、关键代码
public class ExpGenerator {public static String[] operators = {"+", "-", "×", "÷"};public static Random random = new Random();public static int max;public static int min;public static int num;public static ATRIExp generateExp(int operatorNum, int min, int max) {ExpGenerator.max = max;ExpGenerator.min = min;ExpGenerator.num = operatorNum;return new ATRIExp(generateNode(operatorNum, 1, Integer.MAX_VALUE));}/*** 生成多个表达式* @param num 表达式数量* @param operatorNum 运算符数量* @param min 最小值* @param max 最大值* @return 表达式数组*/public static ATRIExp[] generateExps(int num, int operatorNum, int min, int max) {ATRIExp[] exps = new ATRIExp[num];Set<String> expSet = new HashSet<>();while (expSet.size() < num) {ATRIExp exp = generateExp(operatorNum, min, max);String expStr = exp.toString();if (!expSet.contains(expStr)) {expSet.add(expStr);exps[expSet.size() - 1] = exp;}}return exps;}public static Node generateNode(int num, int min, int max) {if (ExpGenerator.num < 2 && (random.nextBoolean() || ExpGenerator.num == 0)) {return generateNumberNode(min, max);} else {int i = random.nextInt(4);String operator = operators[i];Function function = ExpParser.functions.get(operator);FunctionNode functionNode = new FunctionNode(function);int left = 0;--ExpGenerator.num;Node[] temp = new Node[2];for (int j = 0; j < 2; j++) {Node node;if (j == 1) {switch (operator) {case "+":node = generateNode(ExpGenerator.num, min - left, max - left);break;case "×":
// if (left == 0) {
// node = new NumberNode(0);
// } else {// 向上取整node = generateNode(ExpGenerator.num, (int)Math.ceil(((double) min) / left) , (int)Math.ceil(((double) max) / left));
// }break;case "-":node = generateNode(ExpGenerator.num, left - max, left - min);break;case "÷":
// try {if (left == 1 && min > 1) {max = 1;}node = generateNode(ExpGenerator.num, Math.max(left, (int) Math.ceil((float) left / max)), max);
// } catch (Exception e){
// node = new NumberNode(1);
// }break;default:throw new IllegalArgumentException("Invalid operator");}} else {if (operator.equals("-")) {node = generateNode(ExpGenerator.num, min + 1, max);} else {node = generateNode(ExpGenerator.num, min, max);}left = node.getIntValue();}temp[j] = node;if (node instanceof FunctionNode) {((FunctionNode) node).setParent(functionNode);}}// 交换两个节点的位置functionNode.addChild(temp[1]);functionNode.addChild(temp[0]);functionNode.calculateIntValue();return functionNode;}}private static Node generateNumberNode(int min, int max) {
// System.out.println("source: " + min + " " + max);max = Math.min(max, ExpGenerator.max);max = Math.max(ExpGenerator.min, max);min = Math.max(min, ExpGenerator.min);
// System.out.println("clip: " + min + " " + max);if (min >= max) {return new NumberNode(max);}if (random.nextBoolean()) {try {NumberNode numberNode = new NumberNode(random.nextInt(max - min + 1) + min);return numberNode;}catch (Exception e){return Fraction.toNode(Fraction.randomFraction(min, max));}} else {return Fraction.toNode(Fraction.randomFraction(min, max));}}
}
五、测试数据
六、总结
两个人合作共同实现了该四则运算生成器的基本需求,能够按照要求生成四则运算题目(支持一万道题目生成)、计算答案以及检查对错。