20165214 结队编程项目-四则运算(第二周)

20165214 第一次结队编程项目——四则运算第二周

需求分析

本周的结队编程想要实现一个四则运算系统,它能够自动生成n个计算题(本周不包括分数),其中n由咱们输入。每输出一道题目,运行程序的人须要输入相应的答案,直到最后一道题作完。最后,统计正确率。而后,在这个基础上能够进行相应的功能扩展,好比语言支持等。html

设计思路

我须要在上周的基础上对程序进行补充。我以为这个程序关键就分红两大部分,第一部分是题目的随机生成,第二部分是算式的运算。其余的各类扩展在这两个步骤完成后再来添加便可。
因而咱们开始先着手于随机生成,而后着手算式运算,接着把他们拼在一块儿,而后再进行各类扩展项目的补充。这是咱们设计的总思路。
随机生成题目时,咱们的想法是,利用随机数random,根据随机数生成的数来对应符号与数字,从而造成算式。
运算算式时,咱们参娄老师的博客2016-2017-2 《Java 程序设计》课堂实践项目——数据结构应用中的栈的思想来解决,真分数的运算参考课本中第四章的例子22。git

本周达成:

①可以随机生成n道题目,n由咱们输入,最大长度可直接在程序里面修改;
②支持真分数运算,支持多运算符;
③可以计算正确率而且按照百分比形式输出,取到小数点后一位。
④支持简体中文、繁体中文、英语;
⑤可以选择参与运算的数字的最大值;
⑥可以查重到级别0(看两个问题序列是否相等,因为有的生产的算式很长,不知道怎么查重比较好);
⑦将生成的算式都写入文档中。正则表达式

关键代码解释

因为生成随机算式的代码是我我的的一些想法,,因此可能会比较很差理解,因而特别提出编程

File file=new File("Question.txt");
    GetNumber GN = new GetNumber();
    GetOperation GO = new GetOperation();
    GetBracket GB = new GetBracket();
    Random random = new Random();
    PraticeSystem ps=new PraticeSystem();
    int language;
    Scanner scanner=new Scanner(System.in);
    int range;
    GetQuestion(int language){
        switch (language) {
            case 0:
                System.out.println("选择运算数最大为:");
                range=scanner.nextInt();//得到四则运算中数字的上限。
                break;
            case 1:
                System.out.println("Choose The maximum number of operands is");
                range=scanner.nextInt();//得到四则运算中数字的上限。
                break;
            case 2:
                System.out.println("選擇運算數最大為");
                range=scanner.nextInt();//得到四则运算中数字的上限。
                break;
        }
    }
    public String get(){
        int flag=0,flag2=0;
        String Question="";
        for (int j = 0; j < (random.nextInt(7) + 2) * 2 - 1; j++) {  //这样可以保证长度在必定范围内随机,而且长度>=3
            if (j % 2 == 0) {
                int choose=random.nextInt(2);//括号和整数只能在奇数位,除非是括号内的整数才能在偶数位
                if(choose==0){                          //这里使得生成括号和整数都是随机的
                    Question = Question + GN.A(range);  //生成整数链接在问题的后面
                }
                else{
                    if(flag==0){  //这里flag做为标记,由于括号要按顺序来,一旦产生左括号,后面在产生括号时必定要产生右括号。
                        Question = Question + GB.A(flag); //左括号的右边必定紧跟数字
                        Question = Question + GN.A(range);
                        flag=1; //以后再产生括号就产生右括号
                    }
                    else if(flag==1){
                        Question = Question + GN.A(range);//右括号的左边必定紧跟数字
                        Question = Question + GB.A(flag);
                        flag=0;
                    }
                }
            }
            else if (j % 2 == 1){
                char c=GO.A(flag2);
                Question = Question + c;
                if(c=='/'){  //这里是由于不产生歧义,由于在数学表达式中,若是有a/b/c,那么到底是a除以b/c仍是a/b除以c?
                    //而÷不会产生这个问题。
                    flag2=1;
                }
                else{
                    flag2=0;
                }
            }
        }
        int len = Question.length();
        char a = Question.charAt(len - 1);
        if (a == '+' || a == '-' || a == '*'|| a == '/'|| a == '÷') { //若是最后一个字符是运算符,那么舍弃这个运算符。
            Question = Question.substring(0, len - 1);
        }
        len = Question.length();
        a = Question.charAt(len - 1);
        if (flag==1) {
            Question = Question+')'; //若是到最后都没有产生右括号,而在以前已经产生了左括号,那么要补上右括号
            flag=0;
        }
        len = Question.length();
        a = Question.charAt(len - 1);
        char b=Question.charAt(0);
        int count=0;
        for(int h=0;h<len;h++){
            char c=Question.charAt(h);//若是一个算式只有一个左括号和一个右括号且这两个括号分别在算式的两边,则舍弃。
            if(c=='('||c==')'){
                count++;
            }
        }
        if(count==2){
            if(a==')'&&b=='('){
                Question = Question.substring(1, len - 1);
            }
        }
        Question = Question.replaceAll("\\([0-9]+\\)",Integer.toString(random.nextInt(10)+1));
        //利用正则表达式替换在字符串中像(1)这样的状况。

        try{
            FileWriter tofile=new FileWriter(file,true);
            BufferedWriter out= new BufferedWriter(tofile);
            out.write(Question);
            out.newLine();
            out.close();
        }
        catch (IOException e){}
        return  Question;

真分数(题目生成/题目运算判题)

运行截图:
数据结构

码云连接

其中关键代码的解释咱们注释在代码中,码云里有体现~dom

JUnit测试

运算的测试:
学习

后缀表达式的测试:
测试

UML图

PSP

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 120 100
· Estimate · 估计这个任务须要多少时间 600 580
Development 开发 60 60
· Analysis · 需求分析 (包括学习新技术) 5 5
· Design Spec · 生成设计文档 30 30
· Design Review · 设计复审 (和同事审核设计文档) 30 40
· Coding Standard · 代码规范 (为目前的开发制定合适的规范) 30 60
· Design · 具体设计 30 35
· Coding · 具体编码 120 120
· Code Review · 代码复审 10 30
· Test · 测试(自我测试,修改代码,提交修改) 120 100
Reporting 报告 30 40
· Test Report · 测试报告 10 5
· Size Measurement · 计算工做量 20 10
· Postmortem & Process Improvement Plan · 过后总结, 并提出过程改进计划 20 10
合计 1235 1145

遇到的困难与解决方法

在编程时遇到的一些关于类的方法的问题我都用API解决了,这里总结一下其余的问题~编码

  • 问题一:在随机生成题目时,会出现单个数字字符可是有括号的现象,如"(1)",这时候我想用正则表达式,使用String类的repalceAll()方法来覆盖这种状况。可是,我发现要用正则表达式来匹配"([0-9]+)"总是失败,程序直接把引号里面的字符串做为匹配的对象,而没有发挥[]和+的做用。
  • 问题一解决方案:在不断地摸索之下,我突然想到,会不会是由于在正则表达式内使用括号须要用转义符号来表示呢?因而我尝试着在括号的前面加上了\,如图:

而后发现成功了。设计

  • 问题二:在测试运算的时候,若是有两个等级相等的操做符连着使用的时候,会先算左边的再算右边的。这是不符合咱们平常生活中的计算的。
  • 问题二解决方案:仔细检查了代码事后发现是在压栈这一步骤中,对运算符的优先级比较出现了错误。遇到运算符时,当比栈顶的运算符优先级小时,压栈。我写成了小于等于,出现了这个问题。

点评伙伴

本周的合做是基于上周的基础上的。随着合做的次数增长,我和队友的配合也愈来愈好了,所以结队编程的效率有了很多提高,关键的一点是如今两我的若是意见上有什么不统一也比较勇于发表出来,这样颇有利于咱们的思考。
此次个人队友表现也很好~能和我共同窗习一块儿进步~但愿从此可以一直合做下去。

结队编程照片:

相关文章
相关标签/搜索