作业3:结对项目

这个作业属于哪个课程 软工23级
这个作业要求在哪里 结对项目
这个作业的目标 合作实现一个自动生成小学四则运算题目的命令行程序
项目成员 陈日强 3123004736, 李铭恩 3123004745
Github仓库链接 Math-Quiz-Generator

一、PSP表格

PSP2.1 阶段 任务 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 60 65
· Estimate 估计任务所需时间 60 65
Development 开发 600 700
· Analysis 需求分析(包括学习新技术) 80 85
· Design Spec 生成设计文档 60 65
· Design Review 设计复审(和同事审核设计文档) 40 45
· Coding Standard 代码规范(为目前的开发制定规范) 30 35
· Design 具体设计 60 70
· Coding 具体编码 180 190
· Code Review 代码复审 50 55
· Test 测试(自我测试,修改代码,提交修改) 100 110
Reporting 报告 90 100
· Test Report 测试报告 40 45
· Size Measurement 计算工作量 30 35
· Postmortem & Process Improvement Plan 事后总结,并提出过程改进计划 20 20
合计 900 980

二、性能分析图


三、设计实现过程

QuizGeneratorApp.java:主应用程序类,处理用户交互和命令行参数
manager:管理器包
ExerciseFileManager.java:管理练习题和答案文件的创建、读取和写入
QuizExpressionManager.java:可能用于管理表达式的生成和处理
generator:生成器包
ExpGenerator.java:用于生成数学表达式
evaluator:计算器包
ExpsEvaluator.java:计算数学表达式
各类之间的关系
QuizGeneratorApp:作为应用程序的入口,负责用户交互和命令行参数解析。它使用ExerciseFileManager来管理文件操作,并调用ExpGenerator和ExpsEvaluator来生成和计算数学表达式。
ExerciseFileManager:负责文件的创建、读取和写入操作,确保生成的练习题和答案被正确保存。
ExpGenerator:生成数学表达式,供QuizGeneratorApp使用。
ExpsEvaluator:计算生成的数学表达式,计算其结果

四、关键代码

public class ExpGenerator {
    public static String[] operators = {"+", "-", "×", "÷"};
    public static Random random = new Random();
    public static int max;
    public static int min;
    public static int num;

    public static ATRIExp generateExp(int operatorNum, int min, int max) {
        ExpGenerator.max = max;
        ExpGenerator.min = min;
        ExpGenerator.num = operatorNum;
        return new ATRIExp(generateNode(operatorNum, 1, Integer.MAX_VALUE));
    }

    /**
     * 生成多个表达式
     * @param num 表达式数量
     * @param operatorNum 运算符数量
     * @param min 最小值
     * @param max 最大值
     * @return 表达式数组
     */
    public static ATRIExp[] generateExps(int num, int operatorNum, int min, int max) {
        ATRIExp[] exps = new ATRIExp[num];
        Set<String> expSet = new HashSet<>();
        while (expSet.size() < num) {
            ATRIExp exp = generateExp(operatorNum, min, max);
            String expStr = exp.toString();
            if (!expSet.contains(expStr)) {
                expSet.add(expStr);
                exps[expSet.size() - 1] = exp;
            }
        }
        return exps;
    }

    public static Node generateNode(int num, int min, int max) {
        if (ExpGenerator.num < 2 && (random.nextBoolean() || ExpGenerator.num == 0)) {
            return generateNumberNode(min, max);
        } else {
            int i = random.nextInt(4);
            String operator = operators[i];
            Function function = ExpParser.functions.get(operator);
            FunctionNode functionNode = new FunctionNode(function);
            int left = 0;
            --ExpGenerator.num;
            Node[] temp = new Node[2];
            for (int j = 0; j < 2; j++) {
                Node node;
                if (j == 1) {
                    switch (operator) {
                        case "+":
                            node = generateNode(ExpGenerator.num, min - left, max - left);
                            break;
                        case "×":
//                            if (left == 0) {
//                                node = new NumberNode(0);
//                            } else {
                                // 向上取整
                                node = generateNode(ExpGenerator.num, (int)Math.ceil(((double) min) / left) , (int)Math.ceil(((double) max) / left));
//                            }
                            break;
                        case "-":
                            node = generateNode(ExpGenerator.num, left - max, left - min);
                            break;
                        case "÷":
//                            try {
                            if (left == 1 && min > 1) {
                                max = 1;
                            }
                                node = generateNode(ExpGenerator.num, Math.max(left, (int) Math.ceil((float) left / max)), max);
//                            } catch (Exception e){
//                                node = new NumberNode(1);
//                            }
                            break;
                        default:
                            throw new IllegalArgumentException("Invalid operator");
                    }
                } else {
                    if (operator.equals("-")) {
                        node = generateNode(ExpGenerator.num, min + 1, max);
                    } else {
                        node = generateNode(ExpGenerator.num, min, max);
                    }
                    left = node.getIntValue();
                }
                temp[j] = node;
                if (node instanceof FunctionNode) {
                    ((FunctionNode) node).setParent(functionNode);
                }
            }
            // 交换两个节点的位置
            functionNode.addChild(temp[1]);
            functionNode.addChild(temp[0]);
            functionNode.calculateIntValue();
            return functionNode;
        }
    }

    private static Node generateNumberNode(int min, int max) {
//        System.out.println("source: " + min + " " + max);
        max = Math.min(max, ExpGenerator.max);
        max = Math.max(ExpGenerator.min, max);
        min = Math.max(min, ExpGenerator.min);
//        System.out.println("clip: " + min + " " + max);
        if (min >= max) {
            return new NumberNode(max);
        }
        if (random.nextBoolean()) {
            try {
                NumberNode numberNode = new NumberNode(random.nextInt(max - min + 1) + min);
                return numberNode;
            }catch (Exception e){
                return Fraction.toNode(Fraction.randomFraction(min, max));
            }
        } else {
            return Fraction.toNode(Fraction.randomFraction(min, max));
        }
    }
}

五、测试数据

六、总结

两个人合作共同实现了该四则运算生成器的基本需求,能够按照要求生成四则运算题目(支持一万道题目生成)、计算答案以及检查对错。

posted @ 2025-03-22 16:02  Chenss1  阅读(30)  评论(0)    收藏  举报