首页 > 其他分享 >结对项目

结对项目

时间:2023-09-27 20:23:00浏览次数:53  
标签:结对 题目 String 项目 四则运算 生成 new append

软件工程 班级链接
作业要求 结对项目
github地址 Github
作业目标 实现一个自动生成小学四则运算题目的程序
姓名 学号
邓梓荣 3121005121
蔡嘉睿 3121005159

一、PSP表格

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 30 30
Estimate 估计这个任务需要多少时间 30 30
Development 开发 300 360
Analysis 需求分析 (包括学习新技术) 60 30
Design Spec 生成设计文档 60 30
Design Review 设计复审 60 60
Coding Standard 代码规范 (为目前的开发制定合适的规范) 60 90
Design 具体设计 60 90
Coding 具体编码 240 200
Code Review 代码复审 60 80
Test 测试(自我测试,修改代码,提交修改) 120 140
Reporting 报告 30 30
Test Repor 测试报告 60 80
Size Measurement 计算工作量 30 30
Postmortem & Process Improvement Plan 事后总结, 并提出过程改进计划 60 30
合计 1160 1210

二、需求分析

1.使用 -n 参数控制生成题目的个数,例如:Myapp.exe -n 10,将生成10个题目。

2.使用 -r 参数控制题目中数值(自然数、真分数和真分数分母)的范围,例如:Myapp.exe -r 10, 将生成10以内(不包括10)的四则运算题目。该参数可以设置为1或其他自然数。该参数必须给定,否则程序报错并给出帮助信息。

3.生成的题目中计算过程不能产生负数,也就是说算术表达式中如果存在形如e1− e2的子表达式,那么e1≥ e2。

4.生成的题目中如果存在形如e1÷ e2的子表达式,那么其结果应是真分数

5.每道题目中出现的运算符个数不超过3个。

6.程序一次运行生成的题目不能重复,即任何两道题目不能通过有限次交换+和×左右的算术表达式变换为同一道题目。例如,23 + 45 = 和45 + 23 = 是重复的题目,6 × 8 = 和8 × 6 = 也是重复的题目。3+(2+1)和1+2+3这两个题目是重复的,由于+是左结合的,1+2+3等价于(1+2)+3,也就是3+(1+2),也就是3+(2+1)。但是1+2+3和3+2+1是不重复的两道题,因为1+2+3等价于(1+2)+3,而3+2+1等价于(3+2)+1,它们之间不能通过有限次交换变成同一个题目。

三、性能分析

性能分析图:

四、设计实现过程

项目架构:

类和方法

1.ArithmeticUtil

描述:四则运算算法的生成和检测。

方法:buildArithmetic

描述:生成小学四则运算题目并写入Exercises.txt文件。

方法:checkExercise

描述:检查小学四则运算题目答案并将结果写入Grade.txt文件。

2.DataGenerator

描述:封装了生成随机数据的方法。

3.Fraction

描述:分数类,含有分数的约分,加减乘除等方法。

4.RPN

描述:使用逆波兰算法计算中缀表达式的值。

方法:calculateInfixExpression

描述:传入一个中缀表达式,返回计算结果。

流程图

五、代码说明

生成四则运算式子

/**
     * 生成小学四则运算题目并写入Exercises.txt文件
     *
     * @param exerciseNumber 生成个数
     * @param numberRange    题目中数值(自然数、真分数和真分数分母)的范围
     */
    public static void buildArithmetic(int exerciseNumber, int numberRange) {
        Random random = new Random();
        List<String> arithmeticList = new LinkedList<>();
        DataGenerator dataGenerator = new DataGenerator();
        for (int i = 1; i <= exerciseNumber; i++) {
            //限制每道题目中出现的运算符个数不超过3个
            int operatorNumber = random.nextInt(3)+1;
            StringBuilder arithmetic = new StringBuilder();
            switch (operatorNumber) {
                case 1:
                    // 9 + 5 arithmetic.append(dataGenerator.generateNumber(numberRange))
                            .append(dataGenerator.randomOperator())
                            .append(dataGenerator.generateNumber(numberRange))
                            .append(" =");
                    break;
                case 2:
                    //5 × 3 -2
                    arithmetic.append(dataGenerator.generateLeftParenthesis(1))
                            .append(dataGenerator.generateNumber(numberRange))
                            .append(dataGenerator.randomOperator())
                            .append(dataGenerator.generateLeftParenthesis(3))
                            .append(dataGenerator.generateNumber(numberRange))
                            .append(dataGenerator.generateRightParenthesis(4, 6))
                            .append(dataGenerator.randomOperator())
                            .append(dataGenerator.generateNumber(numberRange))
                            .append(dataGenerator.generateRightParenthesis(6, 6))
                            .append(" =");
                    break;
                case 3:
                    // 5 × 3 -2 ÷ 8
                    arithmetic.append(dataGenerator.generateLeftParenthesis(1))
                            .append(dataGenerator.generateNumber(numberRange))
                            .append(dataGenerator.randomOperator())
                            .append(dataGenerator.generateLeftParenthesis(3))
                            .append(dataGenerator.generateNumber(numberRange))
                            .append(dataGenerator.generateRightParenthesis(4, 8))
                            .append(dataGenerator.randomOperator())
                            .append(dataGenerator.generateLeftParenthesis(5))
                            .append(dataGenerator.generateNumber(numberRange))
                            .append(dataGenerator.generateRightParenthesis(6, 8))
                            .append(dataGenerator.randomOperator())
                            .append(dataGenerator.generateNumber(numberRange))
                            .append(dataGenerator.generateRightParenthesis(8, 8))
                            .append(" =");
                    break;
                default:
                    break;
            }
            try {
                RPN.calculateInfixExpression(arithmetic.toString());
                arithmeticList.add(i + ". " + arithmetic);
            } catch (Exception e) {
                i--;
            }
        }

        FileUtil.writeLines(arithmeticList,SubmissionParams.GENERATE_EXERCISE_FILE_NAME,"utf-8");
    }

这里使用了链式结构,不断往四则运算中添加符号,括号和数字,并对生成的结果进行验证,排除负数的情况,dataGenerator中封装了各种生成随机数据的方法,如下面生成真分数的方法:

    /**
     * 生成真分数 (真分数:1/2, 1/3, 2/3, 1/4, 1’1/2, …)
     *
     * @param numberRange
     * @return
     */
    public String randProperFraction(int numberRange) {
        int denominator = random.nextInt(numberRange - 1) + 1;
        int molecule = random.nextInt(numberRange * denominator - 1) + 1;
        if (molecule >= denominator) {
            int N = molecule / denominator;
            molecule %= denominator;
            return molecule == 0 ? String.valueOf(N) : N + "’" + molecule + "/" + denominator;
        }
        return molecule + "/" + denominator;
    }

最后把生成的四则运算写入到文件中。

计算四则运算式子并校对答案

 /**
     * 检查小学四则运算题目答案并将结果写入Grade.txt文件
     *
     * @param exerciseFileName 待检测题目文件名
     * @param answerFileName   待检测题目答案文件名
     */
    public static void checkExercise(String exerciseFileName, String answerFileName) {
        List<String> exercises = FileUtil.readLines(exerciseFileName, StandardCharsets.UTF_8);
        Map<String, String> answerMap = new HashMap<>();
        List<String> answers = FileUtil.readLines(answerFileName, StandardCharsets.UTF_8);
        String pattern = "(^[0-9]+). (.*)";
        Pattern r = Pattern.compile(pattern);
        answers.forEach(a -> {
            Matcher m = r.matcher(a);
            if (m.find()) {
                answerMap.put(m.group(1), m.group(2));
            }
        });
        List<String> trueExercise = new LinkedList<>();
        List<String> wrongExercise = new LinkedList<>();
        for (int i = 0; i < exercises.size(); i++) {
            Matcher m = r.matcher(exercises.get(i));
            if (m.find()) {
                String index = m.group(1);
                String arithmetic = m.group(2);
                String answer = RPN.calculateInfixExpression(arithmetic);
                if (answer.equals(answerMap.get(index))) {
                    trueExercise.add(index);
                } else {
                    wrongExercise.add(index);
                }
            }
        }
        StringBuilder fileContent = new StringBuilder().append("Correct: ").append(trueExercise.size()).append(" (");
        for (int i = 0; i < trueExercise.size(); i++) {
            fileContent.append(trueExercise.get(i)).append(i == trueExercise.size() - 1 ? "" : ",");
        }
        fileContent.append(")\n");
        fileContent.append("Wrong: ").append(wrongExercise.size()).append(" (");
        for (int i = 0; i < wrongExercise.size(); i++) {
            fileContent.append(wrongExercise.get(i)).append(i == wrongExercise.size() - 1 ? "" : ",");
        }
        fileContent.append(")");
        FileUtil.writeString(fileContent.toString(), SubmissionParams.CHECK_RESULT_FILE_NAME, "utf-8");
    }

读取文件获得四则运算式子和答案后,通过正则表达式获取真正的数据(序列号和式子/答案),然后通过逆波兰表达式计算出结果,并进行字符串对比,如果则计入trueExercise,否则计入wrongExercise,逆波兰计算后缀表达式过程如下:

 private static String calculate(List<String> ls) {
        // 创建一个栈,只需要一个栈即可
        Stack<String> stack = new Stack<>();
        // 遍历 ls
        for (String item : ls) {
            if (isNumber(item)) {
                stack.push(item);
            } else {
                // pop 出两个数并运算,在入栈
                String num2 = stack.pop();
                String num1 = stack.pop();
                String res;
                Fraction fraction1 = new Fraction(num1);
                Fraction fraction2 = new Fraction(num2);
                if ("+".equals(item)) {
                    res = fraction1.add(fraction2).toString();
                } else if ("-".equals(item)) {
                    res = fraction1.subtract(fraction2).toString();
                } else if ("×".equals(item)) {
                    res = fraction1.multiply(fraction2).toString();
                } else if ("÷".equals(item)) {
                    res = fraction1.divide(fraction2).toString();
                } else {
                    throw new RuntimeException("符号有问题");
                }
                stack.push(res);
            }
        }
        // 最后留在stack的数据是运算结果
        return stack.pop();
    }

六、测试运行

对程序进行测试生成至少10个测试用例:

判断答案对错:

七、项目小结

在这个四则运算编程项目中,我与我的合作伙伴先共同明确了项目的目标和要求,并进行了详细的讨论和规划。我们讨论了任务的分工和时间表,并确保每个人都理解自己的角色和责任。建立良好的沟通渠道是重中之重,我们一起讨论项目进展、及时解决遇到的问题,并共享想法和建议。我们互相支持,共同解决遇到的技术问题和挑战。我们充分利用了彼此的技能和专长,共同努力克服困难。通过此次项目我们学会了更好地协调和合作,提高了沟通和解决问题的能力,相互学习和成长。

标签:结对,题目,String,项目,四则运算,生成,new,append
From: https://www.cnblogs.com/zrDeng/p/17734244.html

相关文章

  • 结对项目壹(曾宇帆、陈年)
    -1作业概述|这个作业属于哪个课程|《软件工程》||----|----||这个作业要求在哪里|结对项目-作业-计科21级34班-班级博客-博客园(cnblogs.com)||这个作业的目标|实现一个自动生成小学四则运算题目的命令行程序||GitHub链接|https://github.com/guiwuwu/homework-3.git|......
  • pipreqs:Python导出项目依赖包
    许多教程使用的是pipfreeze>requirements.txt指令,但是这个指令只能检索当前虚拟环境中安装的包。要想自动检索项目文件中的依赖包要使用pipreqs,使用方法如下:首先安装pipreqspipinstallpipreqs使用在项目根目录下执行命令pipreqs./#生成requirements.txtpip......
  • SpringBoot学习3(01整合案例项目数据层、业务层、表现层)
    1.整合第三方技术1.整合JUnittarget测试类和引导类为什么要有对应关系,如果没有相似的包结构导致出现的问题原因如下:基础篇-24-整合JUnit——classes属性_哔哩哔哩_bilibili2.整合MyBatis创建的时候选上mybatis和sql驱动 创建之后,进入setting修改信息,打开pom.xml修改信息,如......
  • vue3项目结合antdesignvue封装form表单及校验
    效果图 完整代码1<scriptsetup>2import{defineProps,onMounted,reactive,ref,defineEmits}from'vue'3import{Card,Input,Select,DatePicker,FormItem,Form,Button}from'ant-design-vue'4import{useRuleChe......
  • linux上如何使用docker部署前后端分离项目(含部署多个前端页面的方法)
    (目录)前言使用前一段时间写的前后端分离开发的简单小项目,确保本地可以启动部署所需镜像汇总mysql镜像2.后端工程自定义镜像3.nginx镜像<fontcolor=red>下面介绍部署过程</font>一、mysql镜像(1)拉取mysql镜像选择使用的mysql版本,我用的是8.0.33dockerpullmysql......
  • vue3项目table表格动态表头生成+行数据合并
    这两处地方是动态的,由后端数据返回思路流程  1,后端返回数据二次处理  2,根据后端数据生成动态表头  3,利用antd的customRender与rowSpan设置行合并 完整代码<template><Table:data-source="dataSource":columns="columns":pagination="......
  • 项目管理中常见的十个问题
    项目开发过程中会遇到很多问题,今天分享十个常见问题及应对思路。问题一,线上出bug了,是先找责任人,还是先处理问题?不是每一个问题都值得被追责的,指责也不能修复bug。发现问题后,关键是解决问题。问题解决后,再作复盘。复盘的目的也不是追责,而是为了防止问题再次发生。一个重大的错误应该......
  • 【精选视频免费看】当项目进展缓慢时,如何写一份领导满意的汇报?
    今天是9.27星期三请查收您的今日看点看看都有哪些值得我们IT人关注的技术干货吧。(点击下方标题跳转观看) 【网络运维】弱电老司机6分钟教你设计视频监控系统网络工程师入门,如何配置静态路由、浮动路由?韩立刚老师微课堂:4分钟搞定VMWare添加本地存储为什么说微服务是把双刃剑【行业......
  • vue3项目封装支持搜索,选中不可选,选中的数据项支持上下移动,删除的上下穿梭的树状穿梭框
     1,vue3代码1//这个是返回的所有的数据2constsourceItems=ref([])3//这是穿梭到下面的数据4consttargetItems=ref([])5//这是搜索字段6constsearchName=ref('')7//这两个要是后端返回,可不写8constex......
  • 结对项目-四则运算题目生成
    前言这个作业属于哪个课程21计科三班这个作业要求在哪里结对项目这个作业的目标结对完成一个四则运算生成器及判题器,体验并熟悉结对编程的流程开发者黄锐智(3121005262)岑坤涛(3121005077)项目地址https://github.com/Taoika/Arithmetic已实现功能点使......