小学生最害怕的计算题生成器

是一个标题

211614269 林凯 211601233 张康凌

一、预估与实际

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

二、需求分析

我通过查询教学大纲及研究相关试卷的方式了解到,小学三级数学有如下的几个特点:

  • 特点1
    • 减法的差应该大于0
  • 特点2
    • 除数要不等于0
  • 特点3
    • 除法结果不应该有余数
  • 特点4
    • 减法的差应该大于0
  • 特点5
    • 运算符2-4个
  • 特点6
    • 需要括号

经过分析,我认为,这个程序应当:

  • 要保证减法时的差不为负数
  • 除法时要保证被除数不为0且计算结果没有余数
  • 随机出现合适的括号(由于实在想不到很好的方式实现,出题模块暂时没有此功能,计算的模块支持带括号式子的计算)

三、设计

1. 设计思路

1472316-20180919211016847-2053935541.png
1472316-20180926234901217-1070878996.png

  • 这个程序有两个类
    • MathExam负责生成题目
    • Calculate类专门用来计算表达式的结果
  • 算法的关键是什么?
    • 调度场算法
      • 定义两个栈,一个栈叫做保存运算符记为op,另一个栈保存最终的表达式记为rpn。
      • 数字直接入op栈
      • op栈顶若是(则无条件入栈
      • 运算符要与op栈顶比较,优先级大则入栈,小于或等于则op出栈后再入栈
    • 逆波兰式求值
      • 定义一个栈
      • 从左到右扫描逆波兰式
      • 读到一个数字时就将它压入栈中
      • 读到一个运算符时,就从栈中弹出两个数字,并将该运算符作用于这两个数字,然后将计算结果再压入栈中
      • 逆波兰式读取完毕时,栈中剩下的就是最终结果
    • 生成合适的随机数
      • (int) (min + Math.random() * (max - min + 1)) 可生成min-max范围内的数;

2. 实现方案

  • 准备工作:先在Github上创建仓库,克隆到本地
  • 技术关键点:梳理一下设计思路,可能遇到哪些技术关键点
    • 如何将调度场算法运用到该题中去
    • 随机数的使用,本程序需要大量的使用Math.random()方法
    • 全局静态变量的使用,本程序需要多个静态函数共享数据
    • ArrayList数组的使用,用该数组存储题目及答案的字符串,相比普通数组,该数组可以动态增加空间

四、编码

请说明你如何按照设计思路进行编码,并记录你在开发中遇到的问题,与解决过程

1. 调试日志

  • 在代码的什么位置,代码出现了什么问题,问题会导致什么结果,怎么解决的
    • 在使用调度场算法将题目转换成逆波兰式时出现了问题,因为题目的数字可能是个位也可能是两位,直接通过下标截取字符串的方法明显不合适。最后我决定写一个方法,将题目中的符号及数值按顺序存放至字符串数组中,使用的时候遍历数组取出即可。
    • 在出题时,有可能出现除法有余数的情况,导致题目不符合要求。我的做法是在生成除号时,将前一个被除数取出,同时随机出被除数,若不能整除,则一直循环随机出被除数,最后一定能保证不会有余数。

2. 关键代码

请展示一段程序的关键代码,并解释代码的作用

 //返回符号优先级
    public static int priority(String str) {
        switch (str) {
        case "(":
            return 0;
        case "+":
        case "-":
            return 1;
        case "*":
        case "/":
            return 2;
        default:
            return -1;
        }

    }

    // 转换成逆波兰式
    public static void reversePolishNotation() {

        for (int i = 0; i < slen; i++) {
            //scut字符串数组按顺序存放了题目的数值及符号
            if (!(scut[i].equals("+") || scut[i].equals("-") || scut[i].equals("*") || scut[i].equals("/") || scut[i].equals("(") ||  scut[i].equals(")"))) {
                srpn.push(scut[i]);
            } else {
                if (soperators.isEmpty() || scut[i].equals("(")) {
                    soperators.push(scut[i]);
                } else {
                    if (priority(scut[i]) > priority(soperators.peek())) {
                        soperators.push(scut[i]);
                    } else {
                        if(scut[i].equals(")")) {
                            while (!soperators.peek().equals("(")) {
                                srpn.push(soperators.pop());
                            }
                            soperators.pop();
                        }else {
                            while ((!soperators.isEmpty()) && (priority(soperators.peek()) >= priority(scut[i]))) {
                                srpn.push(soperators.pop());
                            }
                            soperators.push(scut[i]);
                        }
                        
                    }
                }
            }
        }
        //此时原表达式已扫描完毕,将符号栈里剩余的符号全部存至表达式栈
        while (!soperators.isEmpty()) {
            srpn.push(soperators.pop());
        }
    }
  • 该段代码将原表达式通过调度场算法转换成了逆波兰式

3. 代码规范

请给出本次实验使用的代码规范:
1472316-20180919021554599-349344594.png

  • 第一条、代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式。
  • 第二条、类名使用UpperCamelCase风格
  • 第三条、方法名、参数名、成员变量、局部变量都统一使用 lowerCamelCase 风格,必须遵循驼峰形式。
  • 第四条、方法名、参数名、成员变量、局部变量都统一使用 lowerCamelCase 风格,必须遵循驼峰形式。
  • 第五条、静态变量(static)前面加上小写s。

4. 结对过程

  • 先互相沟通,对于要求进行分析,提出合适的解决思想
  • 我先设计出Calculate类专门负责计算传入式子的结果,该类主要用到了调度场算法及逆波兰式的计算
  • 张康凌同学则写出了生成三年级题目的基本算法
  • 我则继续在出题算法上进一步修改,使其更符合题目的要求
  • 实现基本功能后则一起进行相应的测试

五、测试

请思考并记录你认为必要的测试点,并记录测试用例与测试结果

测试项目测试语句预期结果测试结果
不输入任何参数java MathExam4269输入错误输入错误
输入一个参数java MathExam4269 20输入错误输入错误
输入二个参数java MathExam4269 -n 20输入错误输入错误
输入4个参数且题数在前java MathExam4269 -n 20 -grade 2出20道二年级题目出20道二年级题目
输入4个参数且年级在前java MathExam4269 -grade 2 -n 20出20道二年级题目出20道二年级题目
输入4个参数且题数过多java MathExam4269 -grade 2 -n 1000输入错误输入错误

六、总结

  • 吸取上次个人作业的教训,开始时要先设计好相应的框架,思路

  • 编程是一件非常需要细心的事情,不仅要实现好功能,后续也要考虑对代码进行一些优化

  • 每次修改程序,都应该进行回滚测试,确保新增功能不会影响原功能的实现,调试程序时也要考虑到尽可能多的情况

  • 对于结对编程
    • 设计时应与队友一起进行,自己和队友都要理解相应的思路,这样无论谁做驾驶员时都能理解代码,避免因为没有沟通充分导致后续编程出现问题

    • 结对编程时双方都要轮流做驾驶员,另一方也需要做好领航者,没有任何一方可以偷懒

    • 结对编程的好处很多,碰到问题时可以一起讨论,观察代码的一方也容易发现编写代码者没发现的错误

1472316-20180919022216686-531816597.jpg

转载于:https://www.cnblogs.com/lk123/p/9672371.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值