这个作业属于那个课程 | 广工2023软件工程课程 |
---|---|
作业要求 | 作业要求 |
作业目标 | 用绝对编程的方式实现自动生成小学四则运算题目的程序 |
成员 | 赵光明——3121005104 钟海超——3121005105 |
仓库地址 | 地址 |
1.PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 30 | 40 |
· Estimate | · 估计这个任务需要多少时间 | 750 | 900 |
Development | 开发 | 500 | 800 |
· Analysis | · 需求分析 (包括学习新技术) | 100 | 140 |
· Design Spec | · 生成设计文档 | 30 | 40 |
· Design Review | · 设计复审 | 50 | 60 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 50 | 50 |
· Design | · 具体设计 | 70 | 90 |
· Coding | · 具体编码 | 100 | 140 |
· Code Review | · 代码复审 | 40 | 60 |
· Test | · 测试(自我测试,修改代码,提交修改) | 60 | 100 |
Reporting | 报告 | 120 | 150 |
· Test Repor | · 测试报告 | 60 | 80 |
· Size Measurement | · 计算工作量 | 30 | 30 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 30 | 40 |
· 合计 | 780 | 1090 |
2. 效能分析
从性能分析中可以看出,字符类调用比较多,这是因为在此次开发中,我们把所有的运算算式封装成对象进行存储以及运算
3. 设计实现过程
- 项目结构
- 项目运行流程
4. 代码说明
- 算式设计:把每一个算式存储为一个对象
public class OperatorConstant {
public static final String ADD = "+";
public static final String SUB = "-";
public static final String MULTIPLY = "*";
public static final String DIVIDE = "÷";
public static final String LEFT_BRACKETS = "(";
public static final String RIGHT_BRACKETS = ")";
public static final String EQUAL_SIGN = "=";
public static final HashMap<Integer,String> operatorMap = new HashMap<>();
static{
operatorMap.put(1, OperatorConstant.ADD);
operatorMap.put(2, OperatorConstant.SUB);
operatorMap.put(3, OperatorConstant.MULTIPLY);
operatorMap.put(4, OperatorConstant.DIVIDE);
}
}
- 生成算数式子
public class ArithmeticProblemGenerator {
public MathProblem generateOneMathProblem(int range) {
MathProblem mathProblem = new MathProblem();
//获得随机运算法数量
int operatorNum = RandomProblemUtils.getRandomNum(1,3);
List<String> operatorList = new ArrayList<String>();
String operator = null;
//给运算符赋值
for (int i = 0; i < operatorNum ; i++) {
operator = OperatorConstant.operatorMap.get((Integer) RandomProblemUtils.getRandomNum(1, 4));
operatorList.add(operator);
}
//给运算值赋值
List<String> numList = new ArrayList<String>();
int flag = 0;
for (int i = 0; i < operatorList.size()+1 ; i++) {
flag = RandomProblemUtils.getRandomNum(0,1);
if(flag == 0){
//生成分数
numList.add(RandomProblemUtils.generateFraction(range));
}else {
//生成自然数
numList.add(RandomProblemUtils.generateNaturalNumber(range));
}
}
mathProblem.setData(numList);
mathProblem.setOperator(operatorList);
mathProblem.setProblemString(generateExerciseStr(mathProblem));
mathProblem.setAnswer(getAnswer(mathProblem));
return mathProblem;
}
/**
* 根据MathProblem对象获取符合题目格式的输出
* @param mathProblem 题目
* @return
*/
private static String generateExerciseStr(MathProblem mathProblem) {
Queue<String> queue = new LinkedList<>();
List<String> operators = mathProblem.getOperator();
List<String> numbers = mathProblem.getData();
for (int i = 0; i < numbers.size() ; i++) {
queue.add(numbers.get(i));
}
String exerciseStr = "";
for (int i = 0; i < operators.size() ; i++) {
String operator = operators.get(i);
String num1 = queue.remove();
String num2 = queue.remove();
if(i != operators.size()-1){
exerciseStr = OperatorConstant.LEFT_BRACKETS+num1+operator+num2+OperatorConstant.RIGHT_BRACKETS;
}else {
exerciseStr = num1+operator+num2;
}
queue.add(exerciseStr);
}
StringBuilder sb = new StringBuilder("").append(queue.remove()).append("=");
return sb.toString();
}
/**
* 获取题目答案
* @param mathProblem 题目
* @return
*/
private static String getAnswer(MathProblem mathProblem) {
List<String> numbers = mathProblem.getData();
List<String> operators = mathProblem.getOperator();
Queue<String> queue = new LinkedList<>();
for (int i = 0; i < numbers.size() ; i++) {
String s = numbers.get(i);
if(RandomProblemUtils.checkFraction(s) == 3){
s = RandomProblemUtils.DaiFractionToFalseFraction(s);
}
queue.add(s);
}
for (int i = 0; i < operators.size() ; i++) {
String operator = operators.get(i);
String num1 = queue.remove();
String num2 = queue.remove();
String answer = RandomProblemUtils.BinocularOperation(num1,num2,operator);
if(answer == null){
mathProblem.setAnswer(null);
return "";
}
if(RandomProblemUtils.checkFraction(answer) == 2){
answer = RandomProblemUtils.FalseFractionToDaiFraction(answer);
}
queue.add(answer);
}
return queue.remove();
}
/**
* 根据题目数量和范围获取练习题
* @param mathProblemsNum 生成题目数量
* @param range 题目运算数的范围
* @return 所有题目
*/
public List<MathProblem> getMathProblemList(int mathProblemsNum, int range) {
List<MathProblem> mathProblemList = new ArrayList<>();
for (int i = 1; i <= mathProblemsNum; ++i){
MathProblem mathProblem = generateOneMathProblem(range);
mathProblem.setTitleNumber(i);
mathProblemList.add(mathProblem);
}
return mathProblemList;
}
}
- 异常处理
public class MathException extends RuntimeException{
public MathException() {}
public MathException(String message) {
super(message);
}
}
5. 测试运行
- 根据要求生成测试用例及答案
- 进行答案对比
- 支持最大生成10000道题
6. 项目小结
在本次结对学习的过程中我们合力解决的许多问题,在遇到困难时互相帮助,互补短处,如果遇到了两个人共同的盲区也可以一起上网寻找解决思路。这比个人编程效率高了很多,毕竟人多力量大。而且结对编程不仅仅是提升了彼此的能力,同样也加强了我们的沟通能力,这同样是作为程序员所必备的素养。当然最开始也存在分工不太合理的情况,导致在某些板块卡住太久。希望在以后的学习中还能继续与彼此合作,互相讨论、纠错,互相分享学习经验,在实践操作中不断提升自己。