• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

zongyoufengchui

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

软工作业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  阅读(33)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3