软工作业3:结对项目
这个作业属于哪个课程 | 班级链接 |
---|---|
这个作业要求在哪里 | 作业链接 |
这个作业的目标 | 实现一个自动生成小学四则运算题目的命令行程序 |
一、Github地址
二、PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 30 | 40 |
· Estimate | · 估计这个任务需要多少时间 | 30 | 40 |
Development | 开发 | 600 | 540 |
· Analysis | · 需求分析 (包括学习新技术) | 60 | 120 |
· Design Spec | · 生成设计文档 | 60 | 30 |
· Design Review | · 设计复审(和同事审核设计文档) | 60 | 30 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 30 | 30 |
· Design | · 具体设计 | 120 | 30 |
· Coding | · 具体编码 | 120 | 150 |
· Code Review | · 代码复审 | 30 | 60 |
· Test | · 测试(自我测试,修改代码,提交修改) | 120 | 240 |
Reporting | 报告 | 150 | 120 |
· Test Repor | · 测试报告 | 60 | 30 |
· Size Measurement | · 计算工作量 | 60 | 60 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 30 | 30 |
合计 | 780 | 870 |
3、代码展示
修改前:
import java.io.*;
import java.util.*;
public class MathExerciseGenerator {
private static final String OPERATORS = "+-*/"; // 可用的运算符
private static final int MAX_OPERATORS = 3; // 运算符个数上限
private static int exerciseCount;
private static int range;
public static void main(String[] args) {
if (args.length < 2) {
System.out.println("参数不正确,请按照以下格式输入:");
System.out.println("Myapp.exe -n 题目个数 -r 数值范围");
return;
}
try {
parseArguments(args);
generateExercises();
System.out.println("题目生成完毕!");
} catch (Exception e) {
System.out.println("发生错误:" + e.getMessage());
}
}
private static void parseArguments(String[] args) throws IllegalArgumentException {
for (int i = 0; i < args.length; i++) {
if (args[i].equals("-n")) {
try {
exerciseCount = Integer.parseInt(args[i + 1]);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("题目个数必须为正整数!");
}
} else if (args[i].equals("-r")) {
try {
range = Integer.parseInt(args[i + 1]);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("数值范围必须为正整数!"); }
}}
if (exerciseCount <= 0 || range <= 0) {
throw new IllegalArgumentException("题目个数和数值范围必须为正整数!");
}}
private static void generateExercises() throws IOException {
List<String> exercises = new ArrayList<>();
List<String> answers = new ArrayList<>();
Random random = new Random();
while (exercises.size() < exerciseCount) {
String expression = generateExpression(random);
if (expressionIsValid(expression) && !exercises.contains(expression)) {
exercises.add(expression);
answers.add(calculateAnswer(expression));
}
}
writeToFile("Exercises.txt", exercises);
writeToFile("Answers.txt", answers);}
private static String generateExpression(Random random) {
StringBuilder sb = new StringBuilder();
int operatorCount = random.nextInt(MAX_OPERATORS) + 1; // 随机生成运算符个数
int numberCount = operatorCount + 1; // 数字个数等于运算符个数加1
for (int i = 0; i < numberCount; i++) {
if (i > 0) {
sb.append(getRandomOperator(random)); // 在数字之间插入运算符
}
sb.append(generateNumber(random)); // 生成随机数
}
return sb.toString();}
private static String generateNumber(Random random) {
int number = random.nextInt(range) + 1; // 生成一个范围内的随机数
return String.valueOf(number);}
private static char getRandomOperator(Random random) {
char[] operators = {'+', '-', '*', '/'}; // 可用的运算符数组
int index = random.nextInt(operators.length); // 生成一个随机索引
return operators[index];}
private static boolean expressionIsValid(String expression) {
// 表达式不允许以运算符开头或结尾
if (isOperator(expression.charAt(0)) || isOperator(expression.charAt(expression.length() - 1))) {
return false;
}
// 表达式中不允许连续出现两个运算符
for (int i = 1; i < expression.length(); i++) {
if (isOperator(expression.charAt(i)) && isOperator(expression.charAt(i - 1))) {
return false;
}
}
return true;}
private static boolean isOperator(char ch) {
return ch == '+' || ch == '-' || ch == '*' || ch == '/';}
private static String calculateAnswer(String expression) {
Stack<Integer> numberStack = new Stack<>();
Stack<Character> operatorStack = new Stack<>();
for (int i = 0; i < expression.length(); i++) {
char ch = expression.charAt(i);
if (Character.isDigit(ch)) {
int number = ch - '0';
while (i + 1 < expression.length() && Character.isDigit(expression.charAt(i + 1))) {
number = number * 10 + (expression.charAt(i + 1) - '0');
i++;
}
numberStack.push(number);
} else if (isOperator(ch)) {
while (!operatorStack.isEmpty() && hasHigherPrecedence(operatorStack.peek(), ch)) {
int operand2 = numberStack.pop();
int operand1 = numberStack.pop();
char operator = operatorStack.pop();
int result = performOperation(operand1, operand2, operator);
numberStack.push(result);
}
operatorStack.push(ch);
}
}
while (!operatorStack.isEmpty()) {
int operand2 = numberStack.pop();
int operand1 = numberStack.pop();
char operator = operatorStack.pop();
int result = performOperation(operand1, operand2, operator);
numberStack.push(result);
}
return String.valueOf(numberStack.peek());}
private static boolean hasHigherPrecedence(char operator1, char operator2) {
return (operator1 == '*' || operator1 == '/') && (operator2 == '+' || operator2 == '-');
}
private static int performOperation(int operand1, int operand2, char operator) {
switch (operator) {
case '+':
return operand1 + operand2;
case '-':
return operand1 - operand2;
case '*':
return operand1 * operand2;
case '/':
return operand1 / operand2;
default:
throw new IllegalArgumentException("不支持的运算符: " + operator);
}
}
private static void writeToFile(String filePath, List<String> lines) throws IOException {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath))) {
for (String line : lines) {
writer.write(line);
writer.newLine();
}
} catch (IOException e) {
throw new IOException("无法写入文件: " + filePath, e);
}
}}
answer.txt
exercises.txt
出现的问题
1、代码中不包含grade.txt即无法检验
2、代码无法处理分数
更改后代码
import javax.script.ScriptEngineManager;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;
import java.io.File;
import java.io.FileNotFoundException;
public class MathExerciseGenerator {
private static final int MAX_OPERATORS = 3;
private static final String[] OPERATORS = {"+", "-", "*", "/"};
private static final Random RANDOM = new Random();
public static void main(String[] args) {
if (args.length == 2 && args[0].equals("-n") && isInteger(args[1])) {
int exerciseCount = Integer.parseInt(args[1]);
generateExercises(exerciseCount);
} else if (args.length == 2 && args[0].equals("-r") && isInteger(args[1])) {
int range = Integer.parseInt(args[1]);
generateExercisesWithRange(range);
} else if (args.length == 4 && args[0].equals("-e") && args[2].equals("-a")) {
String exerciseFile = args[1];
String answerFile = args[3];
checkAnswers(exerciseFile, answerFile);
} else {
showHelpMessage();
}
}
private static void generateExercises(int exerciseCount) {
List<String> exercises = new ArrayList<>();
List<String> answers = new ArrayList<>();
while (exercises.size() < exerciseCount) {
String expression = generateExpression();
String answer = calculateAnswer(expression);
if (!exercises.contains(expression) && isValidExercise(expression, answer)) {
exercises.add(expression);
answers.add(answer);
}
}
writeToFile("Exercises.txt", exercises);
writeToFile("Answers.txt", answers);
}
private static void generateExercisesWithRange(int range) {
if (range < 1) {
System.out.println("范围参数必须为正整数。");
return;
}
int exerciseCount = 10000;
List<String> exercises = new ArrayList<>();
List<String> answers = new ArrayList<>();
while (exercises.size() < exerciseCount) {
String expression = generateExpression(range);
String answer = calculateAnswer(expression);
if (!exercises.contains(expression) && isValidExercise(expression, answer)) {
exercises.add(expression);
answers.add(answer);
}
}
writeToFile("Exercises.txt", exercises);
writeToFile("Answers.txt", answers);
}
private static void checkAnswers(String exerciseFile, String answerFile) {
List<String> exerciseLines = readLinesFromFile(exerciseFile);
List<String> answerLines = readLinesFromFile(answerFile);
if (exerciseLines.isEmpty() || answerLines.isEmpty() || exerciseLines.size() != answerLines.size()) {
System.out.println("题目文件或答案文件格式不正确。");
return;
}
int exerciseCount = exerciseLines.size();
int correctCount = 0;
List<Integer> correctIndices = new ArrayList<>();
List<Integer> wrongIndices = new ArrayList<>();
for (int i = 0; i < exerciseCount; i++) {
String exercise = exerciseLines.get(i);
String answer = answerLines.get(i);
String calculatedAnswer = calculateAnswer(exercise);
if (answer.equals(calculatedAnswer)) {
correctCount++;
correctIndices.add(i + 1);
} else {
wrongIndices.add(i + 1);
}
}
List<String> resultLines = new ArrayList<>();
resultLines.add("Correct: " + correctCount + " (" + joinIndices(correctIndices) + ")");
resultLines.add("Wrong: " + (exerciseCount - correctCount) + " (" + joinIndices(wrongIndices) + ")");
writeToFile("Grade.txt", resultLines);
}
private static String generateExpression() {
int operatorCount = RANDOM.nextInt(MAX_OPERATORS) + 1;
int operandCount = operatorCount + 1;
StringBuilder expression = new StringBuilder();
int remainingOperands = operandCount;
for (int i = 0; i < operatorCount; i++) {
int operandsToUse = Math.min(2, remainingOperands);
int operatorIndex = RANDOM.nextInt(operandsToUse);
int operand = RANDOM.nextInt(9) + 1; // 生成1-9之间的随机数
expression.append(operand);
if (i < operatorCount - 1) {
expression.append(getRandomOperator());
}
remainingOperands--;
}
expression.append(RANDOM.nextInt(9) + 1); // 生成1-9之间的随机数
return expression.toString();
}
private static String generateExpression(int range) {
int operatorCount = RANDOM.nextInt(MAX_OPERATORS) + 1;
int operandCount = operatorCount + 1;
StringBuilder expression = new StringBuilder();
int remainingOperands = operandCount;
for (int i = 0; i < operatorCount; i++) {
int operandsToUse = Math.min(2, remainingOperands);
int operatorIndex = RANDOM.nextInt(operandsToUse);
int operand = RANDOM.nextInt(range - 1) + 1; // 生成1到range-1之间的随机数
expression.append(operand);
if (i < operatorCount - 1) {
expression.append(getRandomOperator());
}
remainingOperands--;
}
expression.append(RANDOM.nextInt(range - 1) + 1); // 生成1到range-1之间的随机数
return expression.toString();
}
private static String calculateAnswer(String expression) {
return new ScriptEngineManager().getEngineByName("JavaScript").eval(expression).toString();
}
private static String getRandomOperator() {
int index = RANDOM.nextInt(OPERATORS.length);
return OPERATORS[index];
}
private static boolean isValidExercise(String expression, String answer) {
if (expression.contains("/") && !answer.contains("'")) {
// 包含除法且答案不是带分数形式
return false;
}
if (expression.contains("-") && !answer.contains("-")) {
// 包含减法但答案为正数
return false;
}
return true;
}
private static void writeToFile(String fileName, List<String> lines) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))) {
for (String line : lines) {
writer.write(line);
writer.newLine();
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static List<String> readLinesFromFile(String fileName) {
List<String> lines = new ArrayList<>();
try (Scanner scanner = new Scanner(new File(fileName))) {
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
lines.add(line);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return lines;
}
private static String joinIndices(List<Integer> indices) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < indices.size(); i++) {
sb.append(indices.get(i));
if (i < indices.size() - 1) {
sb.append(", ");
}
}
return sb.toString();
}
private static boolean isInteger(String s) {
try {
Integer.parseInt(s);
return true;
} catch (NumberFormatException e) {
return false;
}
}
private static void showHelpMessage() {
System.out.println("使用方法:");
System.out.println("生成题目: Myapp.exe -n <题目数量>");
System.out.println("生成题目(指定范围): Myapp.exe -r <范围>");
System.out.println("检查答案: Myapp.exe -e <题目文件> -a <答案文件>");
}
}
解决的问题
增加了检查答案的代码
新出现并未解决的问题
未处理 异常: javax.script.ScriptException
问题原因:未安装完整的JDK
四、性能分析
原代码:
五、总结
由于前期忘记寻找队友导致单独一人完成该作业,有些吃力,更加体会到了团队协作的重要性,特别是一个人解决不了问题时,没有其他同学的想法进行碰撞。
posted on 2023-09-29 01:59 biemaleyaaa 阅读(26) 评论(0) 编辑 收藏 举报