结对项目:自动生成小学四则运算题目
这个作业属于哪个课程 | https://edu.cnblogs.com/campus/gdgy/Networkengineering1834 |
---|---|
这个作业要求在哪里 | https://edu.cnblogs.com/campus/gdgy/Networkengineering1834/homework/11148 |
这个作业的目标 | 队友之间相互协作,实现一个自动生成小学四则运算题目的命令行程序 |
项目成员:
甄海晖 学号:3118005300
袁宇芳 学号:3118005297
###[toc]
1. Github仓库
https://github.com/YuanYF6/calculation
2. PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 40 | 60 |
· Estimate | · 估计这个任务需要多少时间 | 30 | 30 |
Development | 开发 | 450 | 550 |
· Analysis | · 需求分析 (包括学习新技术) | 60 | 60 |
· Design Spec | · 生成设计文档 | 60 | 60 |
· Design Review | · 设计复审 | 50 | 60 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 15 | 15 |
· Design | · 具体设计 | 30 | 30 |
· Coding | · 具体编码 | 250 | 300 |
· Code Review | · 代码复审 | 60 | 60 |
· Test | · 测试(自我测试,修改代码,提交修改) | 40 | 40 |
Reporting | 报告 | 50 | 60 |
· Test Report | · 测试报告 | 30 | 40 |
· Size Measurement | · 计算工作量 | 10 | 10 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 30 | 25 |
Total | · 合计 | 1205 | 1340 |
3.效能分析
4.设计实现过程
###5.代码说明
-5.1随机生成运算式。最多只有3个运算符。左括号和右括号数量都小于或等于运算符的数量,且左括号和右括号数量相等。每生成一个问题,就用Check.mainCheck方法检查运算式是否符合要求,若不符合,则剔除;若符合,则接着用Generate.generateAnswer检查答案是否为负数;若为负数,则剔除
public static void generateProblems(int problemCount,int numericalRange){ //生成问题
//problemCount问题数量,numericalRange数值范围
private static final String[] symbols = {"+","-","×","÷"};
Random random = new Random();
int e;
String num;
int count = 1,symbol = 0;
int Parentheses;//总括号数
int openParentheses,closeParentheses; //左括号,右括号个数
for(int i = 1;i<=problemCount;i++){
boolean invalid = false;
String expression = "";
do{
e = random.nextInt(4); //随机生成运算符的个数,不超过3个。
}while(e==0);
Parentheses = openParentheses = random.nextInt(e);
closeParentheses = 0;
int[] ParenthesesRepeat = new int[Parentheses];
int parindex = 0;
// System.out.println("Parentheses = "+Parentheses);
// System.out.println("e = "+e);
for(int j = 0;j<=e;j++){
boolean probability;
if(j==e){
if(symbol==3){ //若有÷号
do{
num = generateNum(numericalRange);
}while("0".equals(num));
}
else num = generateNum(numericalRange);
expression=expression+" "+num+" ";
if(closeParentheses!=0){
do{
expression+=") ";
closeParentheses--;
}while(closeParentheses!=0);
}
if(Check.mainCheck(expression,true)){//剔除不符合要求的问题;题目数-1;
i--;
break;
}
// System.out.println("已完成问题生成:"+count+"."+expression);
if("ERROR".equals(generateAnswer(count,expression))){//检查答案是否为负数,若是则剔除这道题;
i--;
break;
}
IOModule.outPut(count,expression,true);
count++;
break;
}
if(symbol==3){
do{
num = generateNum(numericalRange);
}while("0".equals(num));
}
else num = generateNum(numericalRange);
symbol = random.nextInt(4);
if(openParentheses!=0){
String exp = "";
do{
if(parindex!=0 && ParenthesesRepeat[parindex-1]==(e-j))
break;
if(invalid && j==e-1)
break;
probability = (random.nextInt(e)>=Parentheses);
if(probability){
if(!invalid)
invalid = true;
exp=exp+" (";
openParentheses--; closeParentheses++; ParenthesesRepeat[parindex]++;
}
}while(probability&&openParentheses!=0);
exp=exp+" "+num+" "+symbols[symbol];
// System.out.println("左:");
// System.out.println(expression);
if(ParenthesesRepeat[parindex]!=0){
parindex++;
expression+=exp;
continue;
}
}
if(closeParentheses!=0){
// String exp = "";
expression=expression+" "+num+" ";
do{
probability = (random.nextInt(e)>=Parentheses);
// System.out.println("j= "+j+" e= "+e);
// System.out.println("ParenthesesRepeat[parindex-1]= "+ParenthesesRepeat[parindex-1]);
if(ParenthesesRepeat[parindex-1]>=(e-j))
probability = true;
if(probability){
expression+=") ";
closeParentheses--;
ParenthesesRepeat[parindex-1]--;
}
if(ParenthesesRepeat[parindex-1]==0){
parindex--;
}else
break;
}while(probability&&closeParentheses!=0);
expression=expression+symbols[symbol];
// System.out.println("右:");
// System.out.println(expression);
continue;
}
expression=expression+" "+num+" "+symbols[symbol];
}
}
}
-5.2计算答案,拆分表达式,先计算括号内,然后计算括号外。先乘除后加减
public static String calculation(String[] expression){ //计算答案
int count = 0;
boolean haveBrackets = false;
String[] exp = new String[expression.length];
String[] e = new String[expression.length];
for(int i = 0,j = 0,k = 0;i<expression.length;i++){ //将括号分割成式子
if(expression[i]==null)
break;
if(("(").equals(expression[i])){
count++;
if(!haveBrackets){
haveBrackets = true;
continue;
}
}
if((")").equals(expression[i])){
count--;
if(count==0){
haveBrackets = false;
String temp = calculation(e);
if("ERROR".equals(temp))
return "ERROR";
exp[k++] = temp;
continue;
}
}
if(!haveBrackets)
exp[k++] = expression[i];
else e[j++] = expression[i]; //要递归的式子
}
// System.out.println("exp= ");
// for(String s : exp){
// System.out.print(s);
// }
// System.out.println("");
//处理乘除加减法
String result = "0";
int lastSymbol = 1;
String[] exp2 = new String[exp.length];
String lastNum = null;
for(int i = 0,k = 0;i<exp.length;i++){
if(("×").equals(exp[i])||("÷").equals(exp[i])){ //一级处理,先计算乘除算术表达式
String num = "1";
if(lastNum!=null)
num = lastNum;
int firstSymbol = 0;
for(;!(("+").equals(exp[i])||("-").equals(exp[i]));i++){
if(firstSymbol==1){ //乘法
num = calculation.times(num,exp[i]);
firstSymbol=0;
}else if(firstSymbol==2){ //除法
num = calculation.divides(num,exp[i]);
if("ERROR".equals(num))
return "ERROR";
firstSymbol=0;
}else if(("×").equals(exp[i])){
firstSymbol=1;
}else if(("÷").equals(exp[i])){
firstSymbol=2;
}
if(i==exp.length-1)
break;
}
exp2[k-1] = String.valueOf(num);
if(i==exp.length-1)
break;
}
lastNum = exp[i];
exp2[k++] = lastNum;
}
// System.out.println("完成一级处理");
for(String str : exp2){ //二级处理,计算加减算术表达式
if(str==null)
continue;
switch (str){
case "+":
lastSymbol = 1;
break;
case "-":
lastSymbol = 2;
break;
default:
// String num = str;
switch (lastSymbol){
case 1:
result = calculation.plus(result,str);
break;
case 2:
result = calculation.minus(result,str);
break;
}
}
}
// System.out.println(result);
// System.out.println("完成二级处理");
return result;
}
###6.测试运行
程序能支持生成10000道题和程序计算出的答案
程序计算出的结果
将Answers.txt的答案复制到answerfile.txt,并将1-5题的答案改为随意的错误答案,将两份答案对比,将结果输出到Grade.txt中。
###7.项目小结
这次项目是由两位编程能力相差较大的同学共同编写的。由编程能力较强的同学先起总的项目所需要的类,然后再由我编写其中比较容易写出的方法。对于一些对于我来说难以实现的方法,我们一般先讨论,两人一起合作,能产生更多更好的想法。还能相互帮助解决问题。效率较高。我:对java的熟悉度不够,项目经验不多,对于这次大佬带我机会,我也是尽自己的能力多学了点东西。这次结对也充分锻炼了两个人的合作。虽然整个代码有些功能写的不是很好,但我们也总结了经验,努力提升自己。