首页 > 编程语言 >结对项目:自动生成小学四则运算题目的命令行程序

结对项目:自动生成小学四则运算题目的命令行程序

时间:2024-09-28 22:22:37浏览次数:8  
标签:结对 题目 String 四则运算 return static 命令行 new public

这个作业属于哪个课程 计科22级12班
这个作业要求在哪里 https://edu.cnblogs.com/campus/gdgy/CSGrade22-12/homework/13221
姓名 学号
曾繁曦 3122004841
吴健民 3122004667

PSP表格

一、流程图

二、模块设计

1.模块划分

  1. Main模块(Main.java)
    功能描述:程序的入口点,负责接收命令行参数,进行参数校验,调用其他模块的方法来生成题目、检查答案以及处理可能出现的异常情况,如超时异常和其他一般异常。
点击查看代码
```plaintext
package com.tsang.fancy_3122004841.Maths;

import com.tsang.fancy_3122004841.Maths.entity.Args;
import com.tsang.fancy_3122004841.Maths.utils.ValidationUtils;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import static com.tsang.fancy_3122004841.Maths.utils.QuizGenerator.checkExercisesAnswers;
import static com.tsang.fancy_3122004841.Maths.utils.QuizGenerator.generateQuizzes;

public class Main {

    public static void main(String[] args){
        int num = 0;
        try{
            //校验参数
            Args argsObj = ValidationUtils.validateArgs(args);
            Integer numberOfQuestions = argsObj.getNumberOfQuestions();
            num = numberOfQuestions;//?
            Integer range = argsObj.getRange();

            // 判题
            checkExercisesAnswers(argsObj.getExercisesFileName(), argsObj.getAnswerFileName());

            // 生成题目
            CompletableFuture<Void> task = CompletableFuture.runAsync(() -> generateQuizzes(numberOfQuestions, range));

            // 5秒超时
            task.get(5, TimeUnit.SECONDS);
        } catch (TimeoutException e) {
            System.err.println("数据范围不支持生成" + num + "道题,请调整参数!");
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }
    }
}

</details>
2. DuplicateChecker模块(DuplicateChecker.java)
功能描述:用于检查生成的数学表达式是否重复。通过维护一个特定结构的映射来存储已生成的表达式的结果、长度以及每个操作数和操作符的出现次数,以判断新生成的表达式是否与已有的重复。

<details>
<summary>点击查看代码</summary>

package com.tsang.fancy_3122004841.Maths.utils;

import com.tsang.fancy_3122004841.Maths.entity.Fraction;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

public class DuplicateChecker {
    // key:表达式的结果;value:map(key:表达式的长度,value:map集合(key:表达式中的每一个操作数或操作符;value:该字符串出现的次数))
    private static final Map<String, Map<Integer, List<Map<String, Integer>>>> DUMPLICATE_MAP = new HashMap<>();

    public static boolean isDuplicate(Fraction result, String expression) {
        // 已创建的表达式中,如果有计算结果相同,且表达式中的所有字符和出现的次数都一样,就认为是重复的
        String resultStr = result.toString();
        expression = expression.replaceAll("[()]", "");
        Integer length = expression.length();

        // 统计表达式中每个操作数和操作符出现的次数
        Map<String, Integer> characterCountMap = Arrays.stream(expression.split("\\s+"))
                .collect(Collectors.groupingBy(
                        Function.identity(),
                        Collectors.collectingAndThen(Collectors.counting(), Long::intValue))
                );

        Map<Integer, List<Map<String, Integer>>> expressionLengthMap = DUMPLICATE_MAP.get(resultStr);

        if (expressionLengthMap != null) {
            // 存在计算结果相同的表达式
            List<Map<String, Integer>> characterCountMapList = expressionLengthMap.get(length);
            if (characterCountMapList != null) {
                // 存在长度相同的表达式
                boolean isDuplicate = characterCountMapList.stream()
                        .anyMatch(map -> map.equals(characterCountMap));

                if (isDuplicate) {
                    // 存在操作数和操作符出现次数相同的表达式
                    return true;
                }
            }
        } else {
            expressionLengthMap = new HashMap<>();
            DUMPLICATE_MAP.put(resultStr, expressionLengthMap);
        }
        List<Map<String, Integer>> characterCountMapList = expressionLengthMap.computeIfAbsent(length, k -> new ArrayList<>());
        characterCountMapList.add(characterCountMap);
        return false;
    }
}

</details>
3. ExpressionUtils模块(ExpressionUtils.java)
功能描述:提供了将中缀表达式转换为后缀表达式的方法,判断字符串是否为数字或操作符的方法,以及对后缀表达式进行求值的方法,包括允许负数和不允许负数的情况。

<details>
<summary>点击查看代码</summary>

package com.tsang.fancy_3122004841.Maths.utils;

import com.tsang.fancy_3122004841.Maths.entity.Fraction;

import java.util.Deque;
import java.util.LinkedList;
import java.util.StringTokenizer;

public class ExpressionUtils {

    public static String infixToPostfix(String infix) {
        StringBuilder postfix = new StringBuilder();
        Deque<Character> operatorStack = new LinkedList<>();
        StringTokenizer tokens = new StringTokenizer(infix, "()+-÷×", true);

        while (tokens.hasMoreTokens()) {
            String token = tokens.nextToken().trim();
            if (token.isEmpty()) {
                continue;
            }

            if (isNumber(token)) {
                postfix.append(token).append(' ');
            } else if ("(".equals(token)) {
                operatorStack.push('(');
            } else if (")".equals(token)) {
                while (!operatorStack.isEmpty() && !operatorStack.peek().equals('(')) {
                    postfix.append(operatorStack.pop()).append(' ');
                }
                operatorStack.pop(); // Remove '('
            } else if (isOperator(token.charAt(0))) {
                while (!operatorStack.isEmpty() && precedence(operatorStack.peek()) >= precedence(token.charAt(0))) {
                    postfix.append(operatorStack.pop()).append(' ');
                }
                operatorStack.push(token.charAt(0));
            }
        }
        while (!operatorStack.isEmpty()) {
            postfix.append(operatorStack.pop()).append(' ');
        }
        return postfix.toString().trim();
    }

    private static int precedence(char op) {
        switch (op) {
            case '+':
            case '-':
                return 1;
            case '×':
            case '÷':
                return 2;
        }
        return -1;
    }

    public static boolean isNumber(String operator) {
        String regex = "^\\d+'\\d+/\\d+$|^\\d+/\\d+$|^\\d+$";
        return operator.matches(regex);
    }

    private static boolean isOperator(char c) {
        return c == '+' || c == '-' || c == '×' || c == '÷';
    }

    public static Fraction evaluatePostfix(String postfix) {
        Deque<Fraction> stack = new LinkedList<>();
        String[] tokens = postfix.split(" ");

        for (String token : tokens) {
            if (isNumber(token)) {
                stack.push(Fraction.parseFraction(token));
            } else if (isOperator(token.charAt(0))) {
                Fraction operand2 = stack.pop();
                Fraction operand1 = stack.pop();
                Fraction result = FractionUtils.calculate(operand1, operand2, token.charAt(0));
                if (result.isNegative()) {
                    // 负数
                    return null;
                }
                stack.push(result);
            }
        }
        return stack.pop();
    }

    public static Fraction evaluatePostfixAllowNegative(String postfix) {
        Deque<Fraction> stack = new LinkedList<>();
        String[] tokens = postfix.split(" ");

        for (String token : tokens) {
            if (isNumber(token)) {
                stack.push(Fraction.parseFraction(token));
            } else if (isOperator(token.charAt(0))) {
                Fraction operand2 = stack.pop();
                Fraction operand1 = stack.pop();
                Fraction result = FractionUtils.calculate(operand1, operand2, token.charAt(0));
                stack.push(result);
            }
        }
        return stack.pop();
    }
}

</details>
4. FileUtils模块(FileUtils.java)
功能描述:包含了一些与文件操作相关的实用方法,如验证文件名是否为有效的.txt格式、检查文件是否存在、删除已存在的文件等。

<details>
<summary>点击查看代码</summary>

package com.tsang.fancy_3122004841.Maths.utils;

import java.io.File;

public class FileUtils {
    private static final String TXT_FILE_PATTERN = "^[a-zA-Z0-9_-]+\\.txt$";

    public static boolean isValidTxtFileName(String fileName) {
        return fileName.matches(TXT_FILE_PATTERN);
    }

    public static boolean isNotValidTxtName(String fileName) {
        return !isValidTxtFileName(fileName);
    }

    public static void deleteFileIfExists(String filePath) {
        File file = new File(filePath);
        if (file.exists() && file.delete()) {
            System.out.println("旧题目文件已删除: " + filePath);
        }
    }

    public static void validateFileExists(String filePath) {
        if (!new File(filePath).exists()) {
            throw new IllegalArgumentException("文件不存在: " + filePath);
        }
    }
}

</details>
5. FractionUtils模块(FractionUtils.java)
功能描述:提供了生成随机真分数和随机操作数的方法,以及根据给定的操作符对两个分数进行计算的方法。

<details>
<summary>点击查看代码</summary>

package com.tsang.fancy_3122004841.Maths.utils;

import com.tsang.fancy_3122004841.Maths.entity.Fraction;

import java.util.Random;

public class FractionUtils {

    private static final Random RANDOM = new Random();

    //随机生成真分数
    public static Fraction generateRandomFraction(int range) {
        //分子 0 ~ range-1
        int numerator = RANDOM.nextInt(range);
        //分母 1 ~ range-1
        int denominator = RANDOM.nextInt(range - 1) + 1;
        return new Fraction(numerator, denominator);
    }

    public static Fraction generateRandomOperand(String operator, int range) {
        if (RANDOM.nextBoolean()) {
            // 真分数
            return generateRandomFraction(range);
        } else {
            // 自然数
            if ("÷".equals(operator)) {
                return new Fraction(RANDOM.nextInt(range - 1) + 1);
            }
            return new Fraction(RANDOM.nextInt(range));
        }
    }

    public static Fraction calculate(Fraction operand1, Fraction operand2, char operator) {
        switch (operator) {
            case '+':
                return operand1.add(operand2);
            case '-':
                return operand1.subtract(operand2);
            case '×':
                return operand1.multiply(operand2);
            case '÷':
                return operand1.divide(operand2);
            default:
                throw new IllegalArgumentException("无效的运算符");
        }
    }
}

</details>
6. QuizGenerator模块(QuizGenerator.java)
功能描述:负责生成数学题目和答案的核心模块。包括随机生成操作符、操作符数量、数学表达式,添加随机括号,生成题目和答案文件,以及检查给定的题目文件和答案文件的正确性。

<details>
<summary>点击查看代码</summary>

package com.tsang.fancy_3122004841.Maths.utils;

import cn.hutool.core.io.FileUtil;
import com.tsang.fancy_3122004841.Maths.entity.Fraction;
import groovy.lang.Tuple2;
import io.micrometer.common.util.StringUtils;

import java.io.File;
import java.util.*;

public class QuizGenerator {

    private static final String[] OPERATORS = {"+", "-", "×", "÷"};
    private static final Random RANDOM = new Random();

    public static String generateRandomOperator() {
        return OPERATORS[RANDOM.nextInt(OPERATORS.length)];
    }

    public static int generateRandomOperatorCounts() {
        return RANDOM.nextInt(3) + 1;
    }

    public static Tuple2<List<String>, List<String>> generateQuiz(int range, int numberOfQuestions) {
        int duplicateCount = 0;
        int negativeCount = 0;
        int totalCount = 0;

        List<String> quizzes = new ArrayList<>(numberOfQuestions);
        List<String> answers = new ArrayList<>(numberOfQuestions);

        for(int i = 1; i <= numberOfQuestions; i++) {
            int maxOperators = generateRandomOperatorCounts();
            while(true) {
                totalCount++;
                List<String> operands = new ArrayList<>();
                List<String> operators = new ArrayList<>();

                for (int j = 0; j < maxOperators + 1; j++){
                    String lastOperator = operators.isEmpty() ? "" : operators.get(operators.size() - 1);
                    Fraction operand = FractionUtils.generateRandomOperand(lastOperator, range);
                    operands.add(operand.toString());
                    if (j < maxOperators) {
                        operators.add(generateRandomOperator());
                    }
                }

                StringBuilder quiz = new StringBuilder();
                for (int j = 0; j < operands.size(); j++) {
                    quiz.append(operands.get(j));
                    if (j < operators.size()) {
                        quiz.append(" ").append(operators.get(j)).append(" ");
                    }
                }
                String expression = quiz.toString();

                if (operands.size() > 2 && RANDOM.nextBoolean()) {
                    expression = addRandomParentheses(expression);
                }

                String postfix = ExpressionUtils.infixToPostfix(expression);
                Fraction result = ExpressionUtils.evaluatePostfix(postfix);
                if (Objects.nonNull(result)) {
                    if (!DuplicateChecker.isDuplicate(result, expression)) {
                        quizzes.add(i + ". " + expression);
                        answers.add(i + ". " + result);
                        break;
                    } else {
                        duplicateCount++;
                    }
                } else {
                    negativeCount++;
                }
            }
        }
        System.out.println( numberOfQuestions + "道题目已生成,生成题目总次数:" + totalCount + ",重复次数(已去除该题目):" + duplicateCount + ",负数次数(已去除该题目):" + negativeCount);
        return new Tuple2<>(quizzes, answers);
    }

    public static void generateQuizzes(int numberOfQuestions, int range) {
        System.out.printf("生成题目的个数:" + numberOfQuestions + ",题目中数值的范围:0~%d(不包含%d)\n", range, range);

        Tuple2<List<String>, List<String>> quizAndAnswers = QuizGenerator.generateQuiz(range, numberOfQuestions);
        //当前用户目录("user.dir")(即工程根目录)
        String generateExercisesFilePath = System.getProperty("user.dir") + "/Exercises.txt";
        String generateAnswerFilePath = System.getProperty("user.dir") + "/Answers.txt";

        // 删除文件
        File exercisesFile = new File(generateExercisesFilePath);
        File answerFile = new File(generateAnswerFilePath);

        FileUtils.deleteFileIfExists(exercisesFile.getName());
        FileUtils.deleteFileIfExists(answerFile.getName());

        // 将题目和答案写入文件
        FileUtil.writeUtf8Lines(quizAndAnswers.getFirst(), exercisesFile);
        FileUtil.writeUtf8Lines(quizAndAnswers.getSecond(), answerFile);

        System.out.println("新生成的题目问题存入执行程序的当前目录下的Exercises.txt文件,路径如下:" + generateExercisesFilePath);
        System.out.println("新生成的题目答案存入执行程序的当前目录下的Exercises.txt文件,路径如下:" + generateAnswerFilePath);

    }
    private static String addRandomParentheses(String expression) {
        String[] tokens = expression.split(" ");
        StringBuilder result = new StringBuilder();
        List<Integer> addSubIndices = new ArrayList<>();

        for (int i = 1; i < tokens.length; i += 2) {
            String operator = tokens[i];
            if ("+".equals(operator) || "-".equals(operator)) {
                addSubIndices.add(i);
            }
        }

        if (!addSubIndices.isEmpty()) {
            Integer index = addSubIndices.get(RANDOM.nextInt(addSubIndices.size()));
            for (int i = 0; i < tokens.length; i++) {
                if (i == index - 1) {
                    result.append("(");
                }
                result.append(tokens[i]);
                if (i == index + 1) {
                    result.append(")");
                } else if (i < tokens.length - 1) {
                    result.append(" ");
                }
            }
        } else {
            result.append(expression);
        }
        return result.toString();
    }

    public static void checkExercisesAnswers(String exercisesFileName, String answerFileName) {
        if (StringUtils.isBlank(exercisesFileName) && StringUtils.isBlank(answerFileName)) {
            return;
        }
        String exercisesFilePath = System.getProperty("user.dir") + "/" + exercisesFileName;
        String answerFilePath = System.getProperty("user.dir") + "/" + answerFileName;
        FileUtils.validateFileExists(exercisesFilePath);
        FileUtils.validateFileExists(answerFilePath);
        List<String> exercises = FileUtil.readUtf8Lines(exercisesFilePath);
        List<String> answers = FileUtil.readUtf8Lines(answerFilePath);

        if (exercises.size() != answers.size()) {
            throw new IllegalStateException("题目和答案的数量不一致!");
        }

        System.out.println("开始校验题目和答案...");
        List<String> rightAnswers = new ArrayList<>();
        List<String> wrongAnswers = new ArrayList<>();

        for (int i = 0; i < exercises.size(); i++) {
            String[] parts = exercises.get(i).trim().split("\\.\\s+");
            String exercise = parts[1];
            String answer = answers.get(i).trim().split("\\.\\s+")[1];
            String infixToPostfix = ExpressionUtils.infixToPostfix(exercise);
            Fraction result = ExpressionUtils.evaluatePostfixAllowNegative(infixToPostfix);

            if (Objects.equals(result.toString(), answer)) {
                rightAnswers.add(String.valueOf(parts[0]));
            } else {
                wrongAnswers.add(String.valueOf(parts[0]));
            }
        }

        List<String> gradeList = new ArrayList<>();
        gradeList.add("Correct: " + rightAnswers.size() + "(" + String.join(", ", rightAnswers) + ")");
        gradeList.add("Wrong: " + wrongAnswers.size() + "(" + String.join(", ", wrongAnswers) + ")");
        FileUtil.writeUtf8Lines(gradeList, System.getProperty("user.dir") + "/Grade.txt");

        System.out.println("校验完成,结果已保存至 " + System.getProperty("user.dir") + "/Grade.txt");

    }
}

</details>
7. ValidationUtils模块(ValidationUtils.java)
功能描述:用于验证命令行参数的合法性。从命令行参数中读取和解析特定的参数,如题目数量参数-n,题目文件参数-e和答案文件参数-a,并进行相应的合法性检查。

<details>
<summary>点击查看代码</summary>

package com.tsang.fancy_3122004841.Maths.utils;

import com.tsang.fancy_3122004841.Maths.entity.Args;

import java.util.Objects;

public class ValidationUtils {
    public static Args validateArgs(String[] args) {
        Args argsObj = new Args();
        String exercisesFileName = null;
        String answerFileName = null;

        //从命令行参数读取 -n 和 -r 参数
        for(int i = 0; i < args.length; i++){
            if(Objects.equals("-n", args[i]) && i+1 < args.length) {
                try{
                    int numberOfQuestions = Integer.parseInt(args[i+1]);
                    argsObj.setNumberOfQuestions(numberOfQuestions);
                }catch (NumberFormatException e) {
                    throw new IllegalArgumentException("题目个数参数不合法:" + args[i+1]);
                }
            } else if (Objects.equals("-e", args[i]) && i+1 < args.length) {
                exercisesFileName = args[i + 1];
            } else if (Objects.equals("-a", args[i]) && i+1 < args.length) {
                answerFileName = args[i + 1];
            }
        }

        //验证 -e 和 -a 参数的存在性?
        if ((exercisesFileName == null && answerFileName != null) || (exercisesFileName != null && answerFileName == null)){
            throw new IllegalArgumentException("如果需要对给定题目文件和答案文件进行校验,则参数 -e 和 -a 必须同时给出");
        }

        //如果 -e 和 -a 参数都存在,校验文件名并进行答案校验
        if (exercisesFileName != null) {
            if(FileUtils.isNotValidTxtName(exercisesFileName)) {
                throw new IllegalArgumentException("题目文件格式不正确:" + exercisesFileName + ",必须为txt文件");
            }
            if(FileUtils.isNotValidTxtName(answerFileName)) {
                throw new IllegalArgumentException("答案文件格式不正确:" + answerFileName + ",必须为txt文件");
            }
            argsObj.setExercisesFileName(exercisesFileName);
            argsObj.setAnswerFileName(answerFileName);
        }
        return argsObj;
    }
}

</details>

2.接口设计
1. ValidationUtils.validateArgs方法(ValidationUtils.java)
功能:接收命令行参数数组,对参数进行校验,并返回一个包含校验结果的Args对象。
输入参数:String[] args,命令行参数数组。
输出参数:Args对象,包含校验后的题目数量、题目文件和答案文件等信息。
2. QuizGenerator.generateQuiz方法(QuizGenerator.java)
功能:生成指定数量和数值范围的数学题目和答案。
输入参数:int range,数值范围;int numberOfQuestions,题目数量。
输出参数:Tuple2<List<String>, List<String>>,包含生成的题目列表和答案列表。
3. QuizGenerator.generateQuizzes方法(QuizGenerator.java)
功能:根据给定的题目数量和数值范围生成题目和答案文件。
输入参数:int numberOfQuestions,题目数量;int range,数值范围。
无特定输出参数,但会生成题目和答案文件,并在控制台输出相关信息。
4. QuizGenerator.checkExercisesAnswers方法(QuizGenerator.java)
功能:检查给定的题目文件和答案文件,并生成校验结果文件。
输入参数:String exercisesFileName,题目文件名;String answerFileName,答案文件名。
无特定输出参数,但会生成校验结果文件,并在控制台输出相关信息。

##三、性能分析
![](/i/l/?n=24&i=blog/3512942/202409/3512942-20240928215116850-1867623322.png)

##四、优化改进
* 代码优化方向:
1. 多线程与并发优化: 题目生成与校验部分已经采用了 CompletableFuture 实现异步执行,可以在题目生成过程中添加一些进度反馈机制(例如当前生成的题目数量),提升用户体验。 
2. 错误处理: 当前的异常处理相对简单,主要捕获 TimeoutException 和一般的 Exception。可以考虑为不同类型的错误定制化错误信息,例如文件读取失败、题目生成失败等,增加调试信息。
* 面向对象设计: 考虑进一步引入接口和抽象类的概念,将 FractionUtils 等工具类的逻辑拆分为更小的职责单元。可以创建一个 MathOperation 接口,每个运算符实现不同的运算逻辑。


##五、测试结果
运行结果:
![](/i/l/?n=24&i=blog/3512942/202409/3512942-20240928220019584-1770128857.png)
Exercises.txt文件:
![](/i/l/?n=24&i=blog/3512942/202409/3512942-20240928220117912-694444517.png)
Answers.txt文件:
![](/i/l/?n=24&i=blog/3512942/202409/3512942-20240928220141267-1133094941.png)
Grade.txt文件:
![](/i/l/?n=24&i=blog/3512942/202409/3512942-20240928220208269-1088567821.png)

##六、项目总结
我们两人合作完成了小学四则运算题目生成程序,项目成功实现了自动生成题目、控制数量与范围、存入文件及答案校验统计等功能。过程中解决了题目重复、高效处理大量题目及确保文件格式正确数量一致等问题。通过合作,我们学会团队协作,提升了 Java 编程及软件开发能力,收获颇丰,未来将继续优化性能与拓展功能。

标签:结对,题目,String,四则运算,return,static,命令行,new,public
From: https://www.cnblogs.com/tanjange/p/18438531

相关文章

  • 结对项目
    这个作业属于哪个课程https://edu.cnblogs.com/campus/gdgy/CSGrade22-34/这个作业要求在哪里https://edu.cnblogs.com/campus/gdgy/CSGrade22-34/homework/13230这个作业的目标实现一个小学四则运算系统github地址:https://github.com/Pluto-wz/SoftwareCourse/......
  • 结对项目
    这个作业属于哪个课程班级链接这个作业要求在哪里作业要求链接这个作业的目标要求实现一个自动生成小学四则运算题目的命令行程序学号姓名Github仓库地址3122004404王钦鹏Github链接PSP表格PSP2.1PersonalSoftwareProcessStages预估......
  • 结对项目
    这个作业属于哪个课程https://edu.cnblogs.com/campus/gdgy/CSGrade22-34这个作业要求在哪里https://edu.cnblogs.com/campus/gdgy/CSGrade22-34/homework/13230这个作业的目标<结对完成实现一个自动生成小学四则运算题目的命令行程序>项目成员李响3121002802......
  • 结对项目
    结对编程:小学四则运算这个作业属于哪个课程软件工程课程这个作业要求在哪里个人项目-作业-计科22级34班-班级博客-博客园(cnblogs.com)这个作业的目标成员一迪力拜尔3222004889成员二坤杜孜阿依3222004768github链接 https://github.com/......
  • 结对项目
    这个作业属于哪个课程22级计科2班这个作业要求在哪里作业要求这个作业目标实现一个自动生成小学四则运算题目的命令行程序(也可以用图像界面,具有相似功能)。Github地址:https://github.com/JiangJiazhe/PairWork/tree/main项目设计函数功能main模块:设置mai......
  • 实现一个自动生成小学四则运算题目的命令行程序
    这个作业属于哪个课程计科22级12班这个作业要求在哪里结对项目这个作业的目标实现一个自动生成小学四则运算题目的命令行程序。一:詹洛熙3122004800GitHub链接(https://github.com/Zhannoi/-/tree/main)二:PSP表格PSP2.1PersonalSoftwarePr......
  • 结对项目——四则运算
    结对项目——四则运算这个作业属于哪个课程软工22级计科12班这个作业的要求在哪里作业要求这个作业的目标实现四则运算的结对编程项目成员姓名学号GitHub链接分工谭立业3122004365github项目功能的基本实现,博客的编写罗锴佳3122001905gith......
  • 结对项目
    成员姓名学号李心怡3222004336郑梦瀚3222004340作业这个作业属于哪个课程班级链接这个作业要求在哪里作业链接这个作业的目标二人合作实现一个自动生成小学四则运算题目的命令行程序Github链接:点击此处PSP表格PSP2.1PersonalSoftwar......
  • 结对项目
    这个作业属于哪个课程计科22级12班这个作业要求在哪里作业要求这个作业的目标实现一个自动生成小学四则运算题目的命令行程序姓名&学号:姓名学号董雯霖3122004780陈金星3122004774GitHub链接:https://github.com/1534063091/Arithmometer一......
  • 结对项目
    这个作业属于哪个课程计科2班这个作业要求在哪里作业要求这个作业的目标<要求实现一个自动生成小学四则运算题目的命令行程序>[作业地址](https://github.com/cr1017/3122004813)一、时间预估及实际花费时间PSP表格PSP2.1PersonalSoftwareProcessS......