结对项目
这个作业属于哪个课程 | 计科22级12班 |
---|---|
这个作业要求在哪里 | 结对项目 |
这个作业的目标 | 实现一个自动生成小学四则运算题目的命令行程序 |
成员 | 梁晓君(3222004682) 阿丽娅·阿力木(3222004678) |
github地址 | 作业github链接 |
PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 25 | 30 |
· Estimate | · 估计这个任务需要多少时间 | 25 | 30 |
Development | 开发 | 740 | 1030 |
· Analysis | · 需求分析 (包括学习新技术) | 100 | 120 |
· Design Spec | · 生成设计文档 | 30 | 30 |
· Design Review | · 设计复审 | 30 | 40 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 10 | 15 |
· Design | · 具体设计 | 20 | 30 |
· Coding | · 具体编码 | 300 | 450 |
· Code Review | · 代码复审 | 30 | 60 |
· Test | · 测试(自我测试,修改代码,提交修改) | 120 | 200 |
Reporting | 报告 | 40 | 30 |
· Test Repor | · 测试报告 | 20 | 25 |
· Size Measurement | · 计算工作量 | 20 | 10 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 20 | 20 |
· 合计 | 765 | 1060 |
效能分析
设计实现过程
- 思路
1.将整数统一为分数形式,利用random随机生成数和符号,以字符串数组的方式存储(一个数组只包含一个分数或者一个符号),编写加减乘除算法。
2.在 题目 文件的控制台输入 题目数 数的上限 ,就可生成对应题目在 Execise.txt,对应答案存放在 Answer.txt 文件中,学生在 MyAnswer.txt中输入每题答案,对错和分数在 Grade.txt中呈现。 - 流程图
代码说明
GenerateUtil.java
点击查看代码
public class GenerateUtil {
/**
* 生成题目
* @param n 控制生成题目的个数
* @param r 控制题目中数值(自然数、真分数和真分数分母)的范围
*/
public static void getExercise(int n,int r){
if (n < 1){
System.out.println("题目数量输入错误!(1<=n<=10000)");
return;
}
// 算式的结果
int sum = 0;
// 已生成题目的数量
int count = 0;
// a~h是数值,operator1~3是运算符,num代表运算符个数
int a,b,c,d,e,f,g,h,operator1,operator2,operator3,num;
// 存储题目以及答案(为方便,编号为1~n)
String[] exercise = new String[n + 1];
String[] results = new String[n + 1];
// 随机运算符:+ - * /,
// 0表示+, 1表示-, 2表示*, 3表示/
while (count<n){
operator1 = (int) (Math.random()*4);
operator2 = (int) (Math.random()*4);
operator3 = (int) (Math.random()*4);
a = (int) (Math.random() * r);
b = (int) (Math.random() * r);
c = (int) (Math.random() * r);
d = (int) (Math.random() * r);
e = (int) (Math.random() * r);
f = (int) (Math.random() * r);
g = (int) (Math.random() * r);
h = (int) (Math.random() * r);
num = (int) (Math.random() * 3);
// 一个运算符的情况下
if (b != 0 && d!= 0&& num == 0){
if (operator1 == 0){
exercise[++count] = a + "/" + b + " + " + c + "/" + d + " =";
// 存储临时值,方便化简
sum = a * d + b * c;
b = b * d;
// 判断是否为假分数,下同
if (sum > b){
// 将其转换成带分数,下同
results[count] = FractionUtil.changeToProperFraction(sum,b);
}else {
// 将分数化简,下同
results[count] = FractionUtil.simplifiedFraction(sum,b);
}
} else if (operator1 == 1) {
if ((a/b) > (c/d)){
exercise[++count] = a + "/" + b + " - " + c + "/" + d + " =";
// 储存临时值,方便化简
sum = a * d - b * c;
b *= d;
if (sum > b){
results[count] = FractionUtil.changeToProperFraction(sum,b);
}else {
results[count] = FractionUtil.simplifiedFraction(sum,b);
}
}
} else if (operator1 == 2) {
exercise[++count] = a + "/" + b + " * " + c + "/" + d + " =";
// 储存临时值,方便化简
sum = a * c;
b *= d;
if (sum > b){
results[count] = FractionUtil.changeToProperFraction(sum,b);
} else {
results[count] = FractionUtil.simplifiedFraction(sum,b);
}
} else if (operator1 == 3) {
// 防止分母为0
if (c == 0){
continue;
}
exercise[++count] = a + "/" + b + " ÷ " + c + "/" + d + " =";
sum = a * d;
b *= c;
if (sum > b){
results[count] = FractionUtil.changeToProperFraction(sum,b);
} else {
results[count] = FractionUtil.simplifiedFraction(sum,b);
}
}
// 有两个运算符的情况下
} else if (b != 0&& d != 0 && f != 0 && num ==1) {
if (operator1 == 0) {
if (operator2 == 0){
exercise[++count] = a + "/" + b + " + " + c + "/" + d + " + " + e + "/" + f + " =";
sum = a*d*f + c*b*f + e*b*d;
b = b * d * f;
if (sum > b){
results[count] = FractionUtil.changeToProperFraction(sum,b);
}else {
results[count] = FractionUtil.simplifiedFraction(sum,b);
}
} else if (operator2 == 1) {
// 保证不会生成结果为负数的题目
if (a/b + c/d - e/f > 0){
exercise[++count] = a + "/" + b + " + " + c + "/" + d + " - " + e + "/" + f + " =";
sum = a*d*f + c*b*f + e*b*d;
b = b * d * f;
if (sum > b){
results[count] = FractionUtil.changeToProperFraction(sum,b);
}else {
results[count] = FractionUtil.simplifiedFraction(sum,b);
}
}
} else if (operator2 == 2) {
exercise[++count] = a + "/" + b + " + " + c + "/" + d + " * " + e + "/" + f + " =";
sum = b*c*e + a*d*f;
b = b * d * f;
if (sum > b){
results[count] = FractionUtil.changeToProperFraction(sum,b);
}else {
results[count] = FractionUtil.simplifiedFraction(sum,b);
}
} else if (operator3 == 3 && e != 0) {
exercise[++count] = a + "/" + b + " + " + c + "/" + d + " + " + e + " ÷ " + f + " =";
sum = a*d*e + b*c*f;
b = b * d * e;
if (sum > b){
results[count] = FractionUtil.changeToProperFraction(sum,b);
}else {
results[count] = FractionUtil.simplifiedFraction(sum,b);
}
}
}
}
}
// 将生成的题目和答案存入txt文本文件
FileUtil.insertExercise(exercise);
FileUtil.insertAnswer(results);
// 将答案存起来
CorrectUtil.setResults(results);
}
}
FractionUtil.java
点击查看代码
public class FractionUtil {
/**
* 真分数化简
* @param a 分子
* @param b 分母
* @return 化简后的分数(字符串形式)
*/
public static String simplifiedFraction(int a, int b){
// 分子为0,直接返回0
if (a == 0){
return 0+"";
}
// 当分母为1时,直接返回分子
if (b==1){
return a+"";
}
int simplified = simplified(a,b);
return a/simplified + "/" + b/simplified;
}
/**
* 处理假分数化简:化为真分数
* @param a 分子
* @param b 分母
* @return 化简后的分数
*/
public static String changeToProperFraction(int a,int b){
// 当分子为0,直接返回0
if (a == 0){
return 0 + "";
}
if (b == 1){
return a + "";
}
int temp = a / b;
int t = a % b;
if (t ==0 ){
return temp + "";
}
int simplified = simplified(t,b);
return temp+"'"+t/simplified+"/"+b/simplified;
}
/**
* 递归调用,求最大公约数
* @param a 分子
* @param b 分母
* @return 分子a与分母b的最大公约数
*/
private static int simplified(int a,int b){
if (b==0){
return a;
}else {
return simplified(b,a%b);
}
}
}
FileUtil.java
点击查看代码
public class FileUtil {
File file = new File("1.txt");
// 生成题目的文件路径
private static final String exerciseFile = "Exercise.txt";
// 答案的文件路径
private static final String answerFile = "Answer.txt";
/**
* 生成题目文件
* @param exercise 题目的数组
*/
public static void insertExercise(String[] exercise) {
File file = new File(exerciseFile);
FileOutputStream fos = null;
OutputStreamWriter osw = null;
BufferedWriter bw = null;
try{
if (!file.exists()){
file.createNewFile();
}
fos = new FileOutputStream(file);
osw = new OutputStreamWriter(fos);
bw = new BufferedWriter(osw);
for (int i = 1; i < exercise.length; i++) {
bw.write(i+"."+exercise[i]+"\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bw != null){
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (osw != null){
try {
osw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fos != null){
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 生成答案文件
* @param answer 答案的数组
*/
public static void insertAnswer(String[] answer){
File file = new File(answerFile);
FileOutputStream fos = null;
OutputStreamWriter osw = null;
BufferedWriter bw = null;
try{
if (!file.exists()){
file.createNewFile();
}
fos = new FileOutputStream(file);
osw = new OutputStreamWriter(fos);
bw = new BufferedWriter(osw);
for (int i = 1; i < answer.length ; i++) {
bw.write(i+"."+" "+answer[i]+"\n");
}
}catch (IOException e){
e.printStackTrace();
}finally {
if (bw!=null){
try {
bw.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
if (osw!=null){
try {
osw.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
if (fos!=null){
try {
fos.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
测试运行
生成十个题目
项目小结
- 项目成败得失
在项目初期,我们对需求的理解不够透彻,导致在开发过程中出现了一些不必要的返工,大大增加了我们开发项目的时间。 - 分享经验
我觉得结对项目中沟通和配合还是很重要的,我和队员本来就是好朋友在一个宿舍,在项目开发中出现任何问题我们都能及时沟通解决。 * 结对感受:结对开发的时候两个人一起配合讨论能更好的分析项目需求,两人配合可以避免一些不必要的错误。 - 对彼此的评价
阿丽娅:此次项目代码大体是她来负责,我平时思考反应会慢一点,她会很耐心的帮助我。
梁晓君:我的队员观察能力很强,会很细心的发现一些我没发现的问题。