结对项目

这个作业属于哪个课程 https://edu.cnblogs.com/campus/gdgy/SoftwareEngineeringClassof2023
这个作业要求在哪里 https://edu.cnblogs.com/campus/gdgy/SoftwareEngineeringClassof2023/homework/13326
这个作业的目标 合作实现一个四则运算题目生成系统

GitHub链接
前端:https://github.com/Rainnnu/ForntenedCulculate.git
后端:https://github.com/lzw0312/randomExpessionGenerator.git

协作成员
林梓维 3223004212
许婉婷 3223004215

一.PSP表格

Personal Software Process Stages 预估耗时(分钟 实际耗时(分钟
计划 30 30
估计这个任务需要多少时间 5days 5days
开发 500 500
需求分析 (包括学习新技术) 20 20
生成设计文档 30 30
设计复审 30 40
代码规范 (为目前的开发制定合适的规范) 10 5
具体设计 20 20
具体编码 30 20
代码复审 20 15
测试(自我测试,修改代码,提交修改 30 30
报告 40 60
测试报告 30 30
计算工作量 20 20
事后总结, 并提出过程改进计划 30 30
合计 5days 5days

二.计算模块接口的设计与实现

项目结构

三.性能分析图

由性能分析图可知 public String[] getExercises(@RequestParam @Validated @NotBlank @Positive int num, @RequestParam @Validated @NotBlank @Positive int max),即生成四则运算的接口函数耗时最大,后续可通过优化生成算法进行优化项目

四.代码说明

1.生成四则运算算法

点击查看代码
public String[] getExercises(int num, int max) {
        Random random = new Random();
        //标准化之后存入set中,set里面数据个数不发生变化,重新生成
        //随机运算符数量和运算符,根据运算符数目生成运算数,随机是否需要括号,对式子进行标准化(只有+或者只有*的时候才需要)
        int sum = 0;

        String[] exercises = new String[num]; //题目
        Set<String> exercisesSet = new HashSet<>(); //判断是否重复的set集合
        int count = exercisesSet.size();

        while (sum < num) {
            String threeNumber[] = new String[3]; //三个数
            for (int i = 0; i < threeNumber.length; i++) {
                threeNumber[i] = "";
            }
            int[] threeNum = new int[9]; //三个分数各个部分 数,分母,分子
            for (int i = 0; i < threeNum.length; i++) {
                threeNum[i] = -1;
            }
            String[] operators = new String[2]; //运算符
            for (int i = 0; i < operators.length; i++) {
                threeNumber[i] = "";
            }

            //生成
            //生成运算符数目和运算符
            int operatorNum = random.nextInt(2) + 1;
            int[] operatorNumber = new int[operatorNum];
            for (int i = 0; i < operatorNum; i++) {
                int operator = random.nextInt(4);
                operatorNumber[i] = operator;
                switch (operator) {
                    case 0:
                        operators[i] = "+";
                        break;
                    case 1:
                        operators[i] = "-";
                        break;

                    case 2:
                        operators[i] = "*";
                        break;

                    case 3:
                        operators[i] = "/";
                        break;
                    default:
                        break;
                }
            }
            //生成运算数,比运算符多一个
            for (int k = 0; k < operatorNum + 1; k++) {
                int num1 = random.nextInt(2) + 1; //1是自然数,2是分数
                if (num1 == 1) {
                    threeNum[3 * k] = random.nextInt(max);
                    threeNumber[k] = String.valueOf(threeNum[3 * k]);
                } else {
                    //分数
                    //第一个
                    threeNum[3 * (k)] = random.nextInt(max);
                    threeNum[3 * (k) + 1] = random.nextInt(100) + 2; //分母
                    threeNum[3 * (k) + 2] = random.nextInt(threeNum[3 * (k) + 1]) + 1; //分子
                    if (threeNum[3 * (k) + 2] == threeNum[3 * (k) + 1]) {
                        threeNum[3 * (k) + 1] += 1;
                    }
                    if (threeNum[3 * (k)] == 0) {
                        threeNumber[k] = (String.valueOf(threeNum[3 * (k) + 2] + "/" + threeNum[3 * (k) + 1]));
                    } else {
                        threeNumber[k] = (String.valueOf(threeNum[3 * (k)] + "'" + threeNum[3 * (k) + 2] + "/" + threeNum[3 * (k) + 1]));
                    }
                }
            }

            //分两个运算符还是三个
            //两个
            //规范化前判断大小
            if (operatorNum == 1) {
                double[] numbers = new double[2];
                for (int i = 0; i < 2; i++) {
                    if (threeNum[3 * i + 1] != -1) {
                        //分数
                        numbers[i] = (threeNum[3 * i] * threeNum[3 * i + 1] + threeNum[3 * i + 2]) / threeNum[3 * i + 1];
                    } else {
                        //自然数
                        numbers[i] = threeNum[3 * i];
                    }
                }
                if (Objects.equals(operators[0], "/") && numbers[1] == 0) {
                    threeNumber[1] = "1";
                }
                if (Objects.equals(operators[0], "-") && numbers[0] < numbers[1]) {
                    String temp = threeNumber[0];
                    threeNumber[0] = threeNumber[1];
                    threeNumber[1] = temp;
                }
                if ((Objects.equals(operators[0], "+") || Objects.equals(operators[0], "*")) && numbers[0] > numbers[1]) {
                    //交换
                    exercisesSet.add(threeNumber[1] + operators[0] + threeNumber[0]);
                } else {
                    exercisesSet.add(threeNumber[0] + operators[0] + threeNumber[1]);
                }
                if (exercisesSet.size() > count) {
                    //没有重复
                    exercises[sum] = threeNumber[0] + operators[0] + threeNumber[1];
                    sum++;
                    count++;
                }
            } else {
                //三个运算符
                //三个数
                double[] numbers = new double[3];
                for (int i = 0; i < 3; i++) {
                    if (threeNum[3 * i + 1] != -1) {
                        //分数
                        numbers[i] = (double) (threeNum[3 * i] * threeNum[3 * i + 1] + threeNum[3 * i + 2]) / threeNum[3 * i + 1];
                    } else {
                        //自然数
                        numbers[i] = threeNum[3 * i];
                    }
                }
                //是否需要括号
                int needBracket = random.nextInt(2);
                if (needBracket == 0) {
                    //不需要括号
                    //组,判断运算符优先级
                    //优先级一样,计算结果,判断是否需要取反
                    for (int i = 0; i < 2; i++) {
                        if (operators[i].equals("/") && threeNumber[i + 1].equals("0")) {
                            threeNumber[i + 1] = "1";
                        }
                    }
                    if ((operatorNumber[0] < 2 && operatorNumber[1] < 2) || (operatorNumber[0] >= 2 && operatorNumber[1] >= 2)) {
                        //优先级一样

                        if (operators[0] == "-" && operators[1] == "-" && (numbers[0] - numbers[1] < numbers[2])) {
                            operators[0] = "+";
                            operators[1] = "+";
                        } else if (operators[0] == "+" && operators[1] == "-" && (numbers[0] + numbers[1] < numbers[2])) {
                            operators[0] = "-";
                            operators[1] = "+";
                        } else if (operators[0] == "-" && operators[1] == "+" && (numbers[0] + numbers[2] < numbers[1])) {
                            operators[0] = "+";
                            operators[1] = "-";
                        }
                        //不用规范化
                        exercisesSet.add(threeNumber[0] + operators[0] + threeNumber[1] + operators[1] + threeNumber[2]);
                        if (exercisesSet.size() > count) {
                            //没有重复
                            exercises[sum] = threeNumber[0] + operators[0] + threeNumber[1] + operators[1] + threeNumber[2];
                            sum++;
                            count++;
                        }
                    } else {
                        //优先级不一样
                        //减法为负数情况分析
                        String expressionString = numbers[0] + operators[0] + numbers[1] + operators[1] + numbers[2];
                        Expression e = new ExpressionBuilder(expressionString).build();
                        double result;
                        try {
                            result = e.evaluate();
                        } catch (Exception ex) {
                            // 捕获并处理 evaluate 方法可能抛出的异常
                            continue;
                        }

                        if (result < 0) {
                            for (int i = 0; i < 2; i++) {
                                if (operators[i] == "-") {
                                    operators[i] = "+";
                                    operatorNumber[i] = 0;
                                }
                            }
                        }
                        //规范化
                        if (operatorNumber[0] >= 2) {
                            if (numbers[0] >= numbers[1]) {
                                exercisesSet.add(threeNumber[1] + operators[0] + threeNumber[0] + operators[1] + threeNumber[2]);
                            } else {
                                exercisesSet.add(threeNumber[0] + operators[0] + threeNumber[1] + operators[1] + threeNumber[2]);
                            }
                        } else {
                            if (numbers[1] >= numbers[2]) {
                                exercisesSet.add(threeNumber[2] + operators[1] + threeNumber[1] + operators[0] + threeNumber[0]);
                            } else {
                                exercisesSet.add(threeNumber[1] + operators[1] + threeNumber[2] + operators[0] + threeNumber[0]);
                            }
                        }
                        if (exercisesSet.size() > count) {
                            //没有重复
                            exercises[sum] = threeNumber[0] + operators[0] + threeNumber[1] + operators[1] + threeNumber[2];
                            sum++;
                            count++;
                        }
                    }


                } else {
                    //需要括号
                    //组,判断运算符优先级
                    //优先级一样,括号加在后面,计算结果,判断是否需要取反
                    for (int i = 0; i < 2; i++) {
                        if (operators[i].equals("/") && threeNumber[i + 1].equals("0")) {
                            threeNumber[i + 1] = "1";
                        }
                    }
                    if ((operatorNumber[0] < 2 && operatorNumber[1] < 2) || (operatorNumber[0] >= 2 && operatorNumber[1] >= 2)) {
                        //优先级一样
                        if (Objects.equals(operators[1], "/") && operators[0].equals("*") && (threeNumber[0].equals("0") || threeNumber[1].equals("0"))) {
                            threeNumber[1] = "1";
                            threeNumber[0] = "1";
                        } else if (Objects.equals(operators[0], "/") && operators[1].equals("*") && (threeNumber[1].equals("0") || threeNumber[2].equals("0"))) {
                            threeNumber[1] = "1";
                            threeNumber[2] = "1";
                        }
                        for (int i = 0; i < 2; i++) {

                            if (Objects.equals(operators[i], "/") && Objects.equals(threeNumber[i + 1], "0")) {
                                numbers[i + 1] += 1;
                                if (threeNum[3 * (i + 1) + 1] != -1) {
                                    threeNum[3 * (i + 1)] += 1;
                                    threeNumber[i + 1] = threeNum[3 * (i + 1)] + "'" + threeNum[3 * (i + 1) + 2] + "/" + threeNum[3 * (i + 1) + 1];
                                } else {
                                    numbers[i + 1] += 1;
                                    threeNum[3 * (i + 1)] += 1;
                                    threeNumber[i + 1] = String.valueOf(threeNum[3 * (i + 1)]);
                                }
                            }
                        }

                        if (operators[0] == "-" && operators[1] == "-" && (numbers[0] < numbers[1] - numbers[2])) {
                            operators[0] = "+";
                            operators[1] = "+";
                        } else if (operators[0] == "+" && operators[1] == "-" && (numbers[1] - numbers[2] + numbers[0]) < 0) {
                            //operators[0]="-";
                            operators[1] = "+";
                        } else if (operators[0] == "-" && operators[1] == "+" && (numbers[1] + numbers[2] > numbers[0])) {
                            operators[0] = "+";
                            //operators[1]="-";
                        }
                        //用规范化
                        if (numbers[1] > numbers[2]) {
                            exercisesSet.add(threeNumber[2] + operators[1] + threeNumber[1] + operators[0] + threeNumber[0]);
                        } else {
                            exercisesSet.add(threeNumber[1] + operators[1] + threeNumber[2] + operators[0] + threeNumber[0]);
                        }
                        //exercisesSet.add(threeNumber[0]+operators[0]+threeNumber[1]+operators[1]+threeNumber[2]);
                        if (exercisesSet.size() > count) {
                            //没有重复
                            exercises[sum] = threeNumber[0] + operators[0] + "(" + threeNumber[1] + operators[1] + threeNumber[2] + ")";
                            sum++;
                            count++;
                        }
                    } else {
                        //优先级不一样,括号加给优先级低的
                        //减法为负数情况分析
                        for (int i = 0; i < 2; i++) {
                            if (operators[i].equals("/") && threeNumber[i + 1].equals("0")) {
                                threeNumber[i + 1] = "1";
                            }
                        }
                        if (operators[0].equals("-") && operators[1].equals("/") && Objects.equals(threeNumber[0], threeNumber[1])) {
                            numbers[0] += 1;
                            if (threeNum[1] != -1) {
                                threeNum[0] += 1;
                                threeNumber[0] = threeNum[0] + "'" + threeNum[2] + "/" + threeNum[1];
                            } else {
                                numbers[0] += 1;
                                threeNum[0] += 1;
                                threeNumber[0] = String.valueOf(threeNum[0]);
                            }
                        } else if (operators[1].equals("-") && operators[0].equals("/") && Objects.equals(threeNumber[2], threeNumber[1])) {
                            numbers[1] += 1;
                            if (threeNum[4] != -1) {
                                threeNum[3] += 1;
                                threeNumber[1] = threeNum[3] + "'" + threeNum[5] + "/" + threeNum[4];
                            } else {
                                //numbers[1]+=1;
                                threeNum[3] += 1;
                                threeNumber[1] = String.valueOf(threeNum[3]);
                            }
                        }
                        for (int i = 0; i < 2; i++) {
                            if (operators[i] == "-" && numbers[i] < numbers[i + 1]) {
                                String temp = threeNumber[i];
                                threeNumber[i] = threeNumber[i + 1];
                                threeNumber[i + 1] = temp;
                            }
                        }
                        //规范化
                        if (operatorNumber[0] >= 2) {
                            if (numbers[1] >= numbers[2]) {
                                exercisesSet.add(threeNumber[2] + operators[1] + threeNumber[1] + operators[0] + threeNumber[0]);
                            } else {
                                exercisesSet.add(threeNumber[1] + operators[1] + threeNumber[2] + operators[0] + threeNumber[0]);
                            }
                        } else {
                            if (numbers[0] >= numbers[1]) {
                                exercisesSet.add(threeNumber[1] + operators[0] + threeNumber[0] + operators[1] + threeNumber[2]);
                            } else {
                                exercisesSet.add(threeNumber[0] + operators[0] + threeNumber[1] + operators[1] + threeNumber[2]);
                            }
                        }
                        if (exercisesSet.size() > count) {
                            //没有重复
//                            exercises[sum]=threeNumber[0]+operators[0]+threeNumber[1]+operators[1]+threeNumber[2];
                            if (operatorNumber[0] >= 2) {
                                exercises[sum] = threeNumber[0] + operators[0] + "(" + threeNumber[1] + operators[1] + threeNumber[2] + ")";
                            } else {
                                exercises[sum] = "(" + threeNumber[0] + operators[0] + threeNumber[1] + ")" + operators[1] + threeNumber[2];
                            }
                            sum++;
                            count++;
                        }


                    }

                }
            }

//

        }

        return exercises;
    }
2.计算结果算法
点击查看代码
    public String[] getAnswer(String[] exercises) {
        String[] answers = new String[exercises.length];
        // 示例:计算 "1 + 1/2"
        for (int i = 0; i < exercises.length; i++) {
            System.out.println("题目为" + exercises[i]);
            String expression = exercises[i];
            //String expression="7-2'20/27/7";
            expression = convertToImproperFraction(expression);
            String[] infixTokens = parseExpression(expression);
            String[] rpnTokens = infixToRPN(infixTokens);
            BigFraction result = calculateRPN(rpnTokens);
            System.out.println(result);
            if (result.toString().contains("/")) {
                answers[i] = convertToProperFraction(result);
                System.out.println("答案为" + convertToProperFraction(result));
            } else {
                answers[i] = result.toString();
                System.out.println("答案为" + result);
            }

        }
        return answers;
    }
    //将假分数转换为真分数
    public static String convertToProperFraction(BigFraction input) {
        int numerator = input.getNumeratorAsInt(); //分子
        int denominator = input.getDenominatorAsInt();//分母
        int num = 0;
        if (denominator == 1) {
            return String.valueOf(numerator);
        } else {
            num = numerator / denominator;
            numerator = numerator % denominator;

        }
        if (num != 0) {
            return num + "'" + numerator + "/" + denominator;
        }
        return numerator + "/" + denominator;

    }


    // 将真分数转换为假分数
    public static String convertToImproperFraction(String input) {
        // 正则表达式匹配真分数(格式为 a`b/c)
        Pattern pattern = Pattern.compile("(\\d+)'(\\d+)/(\\d+)");
        Matcher matcher = pattern.matcher(input);

        // 用于存储转换后的字符串
        StringBuffer result = new StringBuffer();

        // 遍历匹配的真分数
        while (matcher.find()) {
            int a = Integer.parseInt(matcher.group(1)); // 整数部分
            int b = Integer.parseInt(matcher.group(2)); // 分子
            int c = Integer.parseInt(matcher.group(3)); // 分母

            // 转换为假分数
            int numerator = a * c + b; // 新分子
            String improperFraction = numerator + "/" + c; // 假分数形式

            // 替换原式子中的真分数
            matcher.appendReplacement(result, improperFraction);
        }
        matcher.appendTail(result); // 添加剩余部分

        return result.toString();
    }


    // 应用运算符
    public static BigFraction applyOperation(BigFraction a, BigFraction b, String operator) {
        switch (operator) {
            case "+":
                return a.add(b);
            case "-":
                return a.subtract(b);
            case "*":
                return a.multiply(b);
            case "/":
                return a.divide(b);
            default:
                throw new IllegalArgumentException("Unknown operator: " + operator);
        }
    }


    // 判断是否为运算符
    public static boolean isOperator(String token) {
        return OPERATOR_PRECEDENCE.containsKey(token);
    }

    // 判断是否为数字
    public static boolean isNumber(String token) {
        try {
            new BigFraction(Double.parseDouble(token));
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }

    // 将输入字符串解析为 token 数组
    public static String[] parseExpression(String expression) {
        List<String> tokens = new ArrayList<>();
        StringBuilder numberBuffer = new StringBuilder();

        for (char ch : expression.toCharArray()) {
            if (Character.isDigit(ch)) {
                // 如果是数字或分数符号,添加到缓冲区
                numberBuffer.append(ch);
            } else if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '(' || ch == ')') {
                // 如果是运算符或括号,先将缓冲区的内容作为一个 token 添加
                if (numberBuffer.length() > 0) {
                    tokens.add(numberBuffer.toString());
                    numberBuffer.setLength(0); // 清空缓冲区
                }
                tokens.add(String.valueOf(ch)); // 添加运算符或括号
            } else if (!Character.isWhitespace(ch)) {
                throw new IllegalArgumentException("Invalid character: " + ch);
            }
        }

        // 添加最后一个数字
        if (numberBuffer.length() > 0) {
            tokens.add(numberBuffer.toString());
        }

        return tokens.toArray(new String[0]);
    }

    // 将中缀表达式转换为逆波兰表达式
    public static String[] infixToRPN(String[] infixTokens) {
        List<String> output = new ArrayList<>();
        Stack<String> operators = new Stack<>();

        for (String token : infixTokens) {
            if (isNumber(token)) {
                // 如果是数字,直接添加到输出
                output.add(token);
            } else if (isOperator(token)) {
                // 如果是运算符,弹出栈中优先级更高或相等的运算符
                while (!operators.isEmpty() && isOperator(operators.peek()) && OPERATOR_PRECEDENCE.get(operators.peek()) >= OPERATOR_PRECEDENCE.get(token)) {
                    output.add(operators.pop());
                }
                operators.push(token);
            } else if (token.equals("(")) {
                // 如果是左括号,压入栈
                operators.push(token);
            } else if (token.equals(")")) {
                // 如果是右括号,弹出栈中的运算符直到遇到左括号
                while (!operators.isEmpty() && !operators.peek().equals("(")) {
                    output.add(operators.pop());
                }
                if (!operators.isEmpty() && operators.peek().equals("(")) {
                    operators.pop(); // 弹出左括号
                } else {
                    throw new IllegalArgumentException("Mismatched parentheses");
                }
            } else {
                throw new IllegalArgumentException("Invalid token: " + token);
            }
        }

        // 弹出栈中剩余的运算符
        while (!operators.isEmpty()) {
            if (operators.peek().equals("(") || operators.peek().equals(")")) {
                throw new IllegalArgumentException("Mismatched parentheses");
            }
            output.add(operators.pop());
        }

        return output.toArray(new String[0]);
    }


    // 计算逆波兰表达式
    public static BigFraction calculateRPN(String[] rpnTokens) {
        // 计算逆波兰表达式

        Stack<BigFraction> stack = new Stack<>();

        for (String token : rpnTokens) {
            if (isNumber(token)) {
                stack.push(new BigFraction(Double.parseDouble(token)));
            } else if (isOperator(token)) {
                try {
                    BigFraction b = stack.pop();
                    BigFraction a = stack.pop();
                    BigFraction result = applyOperation(a, b, token);
                    stack.push(result);
                } catch (EmptyStackException e) {
                    throw new IllegalArgumentException("Invalid expression");
                }
            } else {
                throw new IllegalArgumentException("Invalid token: " + token);
            }
        }

        if (stack.size() != 1) {
            throw new IllegalArgumentException("Invalid expression");
        }

        return stack.pop();
    }

3.给定文件判断对错算法
点击查看代码
    public AnswerVO correctingExercises(String[] answers, String[] result) {
        List<Integer> correct = new ArrayList<>();
        List<Integer> error = new ArrayList<>();
        int correctNumber = 0;
        int errorNumber = 0;
        for (int i = 0; i < answers.length; i++) {
            if (answers[i].equals(result[i])) {
                correct.add(i);
                correctNumber++;
            } else {
                error.add(i);
                errorNumber++;
            }
        }
        AnswerVO answerVO = new AnswerVO(correct, correctNumber, error, errorNumber);
        return answerVO;
    }

五.单元测试展示

测试代码

点击查看代码
@SpringBootTest
@RunWith(SpringRunner.class)
public class test {
    Controller controller = new Controller();
    ExercisesServiceImpl exercisesService = new ExercisesServiceImpl();

    @Test
    public void testGetExercises() {
        // 测试生成30000条
        String[] result = controller.getExercises(10000, 10);
    }

    // 测试max参数不合法
    @Test(expected = IllegalArgumentException.class)
    public void testGetExercisesWithErrorMax() {
        String[] result = controller.getExercises(30000, -1);
    }

    // 测试num参数不合法
    @Test(expected = NegativeArraySizeException.class)
    public void testGetExercisesWithErrorNum() {
        // 测试生成30000条
        String[] result = controller.getExercises(-1, 10);
    }

    //测试给定题目和答案,进行修改
    @Test
    public void testCorrectingExercises() throws FileNotFoundException {
        controller.correctingExercises(new FileDTO("C:\\Users\\Aurora\\Desktop\\Exercises.txt", "C://Users//Aurora//Desktop//Answers.txt"));
    }

    //测试CorrectingExercises函数参数错误情况
    @Test(expected = NullPointerException.class)
    public void testCorrectingExercisesWithoutFileDTO() throws FileNotFoundException {
        controller.correctingExercises(null);

    }

    //测试convertToProperFraction函数,将假分数化为真分数
    @Test
    public void testConvertToProperFraction() {
        String s = exercisesService.convertToProperFraction(new BigFraction(7, 2));
        assert s.equals("3'1/2");
    }

    //测试convertToImproperFraction函数,将真分数化为假分数
    @Test
    public void testConvertToImproperFraction() {
        String s = exercisesService.convertToImproperFraction("3'1/2");
        assert s.equals("7/2");
    }

    //测试生成题目不重复
    @Test
    public void testGenerateExercises() {
        String[] result = controller.getExercises(1000, 10);
        Set<String> exercisesSet = new HashSet<>();
        for (String s : result) {
            exercisesSet.add(s);
        }
        assert exercisesSet.size() == result.length;
    }

    //测试将中缀表达式转换为后缀表达式
    @Test
    public void testInfixToRPN() {
        String[] result = exercisesService.parseExpression("1+2*3");
        String[] strings = exercisesService.infixToRPN(result);
        assert strings[0].equals("1");
        assert strings[1].equals("2");
        assert strings[2].equals("3");
        assert strings[3].equals("*");
        assert strings[4].equals("+");
    }

    //测试计算后缀表达式
    @Test
    public void testCalculateRPN() {
        String[] result = exercisesService.parseExpression("1+2*3");
        String[] strings = exercisesService.infixToRPN(result);
        BigFraction calculateRPN = exercisesService.calculateRPN(strings);
        assert calculateRPN.equals(new BigFraction(7));
    }


}

六.项目小结

在这次结对项目中,林梓维负责后端部分代码编写,许婉婷负责前端部分代码编写,在本次前后端分离的结对项目中,我们团队高效协作,顺利完成了任务。前端采用React框架,负责界面展示与用户交互,后端则使用SpringBoot框架,处理业务逻辑和数据存储。通过Git进行版本控制,确保代码同步。在开发过程中,我们保持密切沟通,及时解决问题,确保前后端接口匹配。项目最终实现了预期的功能,用户体验良好,响应速度快。此次合作,不仅提升了我们的技术能力,也锻炼了团队协作精神,为后续项目的顺利进行奠定了坚实基础。

posted @ 2025-03-22 20:31  baea  阅读(45)  评论(0)    收藏  举报