20165326 结对编程项目-四则运算 阶段总结

一、需求分析

  • 能随机生成n道四则运算题目,n由使用者输入

  • 支持整数和分数

  • 支持多运算符

  • 能够判断正误,错误时能提醒并输出正确答案

  • 能计算出正确率

  • 能多次生成题目,直到使用者选择退出

    后续拓展的可能

  • 题目去重

  • 文件:

    • 处理生成题目并输出到文件
    • 完成题目后从文件读入并判题
  • 多语言支持:简体中文, 繁體中文, English

二、设计思路(同时输出UML类图)

首先考虑生成题目。
随机生成题目,用到Random函数,生成题目应该是同时随机生成数字和四则运算符号,此处用MakeQuestions子类,新建一个空字符串用于存放生成的题目;
考虑到用户的需求设计从键盘输入来控制生成的题目数量和题目复杂度(也就是四则运算的符号数);
生成题目之后进行运算,要求用逆波兰算法来运算题目,此处参考了逆波兰算法实现四则运算,将中缀表达式变成后缀表达式,再调用计算的类进行运算,其中用RationalNumber实现真分数的计算。题目输出后就从键盘输入结果进行答题,eqauls比较录入的结果和经过运算的值,答对一题记正确题目数加一,最后用该值除以题目数得到正确率,实现判题功能。

三、实现过程中的关键代码解释

 public void conversion(String expr) {   //中缀转后缀
        String token;
        StringTokenizer tokenizer = new StringTokenizer(expr);

        while (tokenizer.hasMoreTokens()) {
            //当tokenizer有下一个值时,进行循环,并把值赋给token
            token = tokenizer.nextToken();

            if (token.equals("(")) {
                //如果是左括号,入栈
                stack.push(token);
            }else if (token.equals("+") || token.equals("-")) {
                //如果是“+”或“-”,继续判断栈是否为空
                if (!stack.empty()){
                    //如果栈非空,判断栈顶元素是什么
                    if (stack.peek().equals("(")) {
                        //如果栈顶为“(”,运算符入栈
                        stack.push(token);
                    }else{
                        //否则先把栈顶元素移除,加到列表中,再将运算符入栈
                        list.add(stack.pop());
                        stack.push(token);
                    }
                }else {
                    //若栈为空,运算符入栈
                    stack.push(token);
                }
            }else if (token.equals("*") || token.equals("÷")){
                //如果是“*”或“÷”,继续判断栈是否为空
                if (!stack.empty()) {
                    //如果栈非空,判断栈顶元素是什么
                    if (stack.peek().equals("*") || stack.peek().equals("÷")) {
                        //如果栈顶为“*”或“÷”,先把栈顶元素移除,加到列表中,再将运算符入栈
                        list.add(stack.pop());
                        stack.push(token);
                    }else {
                        //如果栈顶为其他,运算符直接入栈
                        stack.push(token);
                    }
                }else {
                    //如果栈为空,运算符直接入栈
                    stack.push(token);
                }
            } else if (token.equals(")")) {
                //如果遇到“)”,开始循环
                while (true) {
                    //先把栈顶元素移除并赋给A
                    String A = stack.pop();
                    if (!A.equals("(")) {
                        //如果A不为“(”,则加到列表
                        list.add(A);
                    } else {
                        //如果A为“(”,退出循环
                        break;
                    }
                }
            }else {
                //如果为操作数,进入列表
                list.add(token);
            }
        }
        while (!stack.empty()) {
            //将栈中元素取出,加到列表中,直到栈为空
            list.add(stack.pop());
        }
        ListIterator<String> li = list.listIterator();//返回此列表元素的列表迭代器(按适当顺序)。
        while (li.hasNext()) {
            //将迭代器中的元素依次取出,并加上空格作为分隔符
            Message += li.next() + " ";
            li.remove();
        }
        message = Message;

四、测试方法

NifixToSuffer类方法的测试

Calculator类方法的测试

五、运行过程截图

六、代码托管

码云链接

七、遇到的困难及解决方法

  • 困难1:在计算统计正确率时,输出正确率都是0%,如下图:

  • 解决方法:仔细查看代码后,我们发现,在进行小数运算的时候,没有将int型的j转换为double型,导致只要不是100%,在进行小数运算时计算结果都会是0%

八、对结对的小伙伴做出评价(重点指出需要改进的地方)

在结对编程中,我的队友是驾驶的角色,承担了大部分的工作,如代码文件的创建及配置、UML图的制作等,我主要负责在旁边搜查相关知识点的资料,我们一起讨论解决过程中遇到的问题。我觉得y团队有的时候对问题的统一会慢半拍,默契大概是慢慢磨合的,我觉得我自身也有很多需要提高的地方,希望和队友一起进步。