作业3:结对项目
| 这个作业属于哪个课程 | 软工23级 |
|---|---|
| 这个作业要求在哪里 | 结对项目 |
| 这个作业的目标 | 合作实现一个自动生成小学四则运算题目的命令行程序 |
| 项目成员 | 陈日强 3123004736, 李铭恩 3123004745 |
| Github仓库链接 | Math-Quiz-Generator |
一、PSP表格
| PSP2.1 阶段 | 任务 | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| Planning | 计划 | 60 | 65 |
| · Estimate | 估计任务所需时间 | 60 | 65 |
| Development | 开发 | 600 | 700 |
| · 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 | 980 |
二、性能分析图


三、设计实现过程
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));
}
}
}
五、测试数据

六、总结
两个人合作共同实现了该四则运算生成器的基本需求,能够按照要求生成四则运算题目(支持一万道题目生成)、计算答案以及检查对错。

浙公网安备 33010602011771号