zoukankan      html  css  js  c++  java
  • 第四周-四则运算试题生成

    作业具体要求链接:https://edu.cnblogs.com/campus/nenu/SWE2017FALL/homework/997

    具体实现功能如下:

    功能1:支持出题4个数的四则运算题目,所有题目要求作者有能力正确回答。(+10)

    功能2:在功能1的基础上,支持括号。(+15)

    功能3:限定题目数量,“精美”打印输出,且要避免重复,最好能输出到.txt文件中。且对输入题目数进行限定,题目数量必须是正整数。(+10)

    功能4:支持分数出题和运算。(不完成此题不倒扣分数)

    功能5:可把程序改成GUI版/web版/移植为android,ios版。

    此次作业完成是以“结对编程”的形式完成,我的伙伴是刘淑霞,她的博客地址为:http://www.cnblogs.com/liusx0303/

    这篇博客主要由如下几个方面讲述:

    1.每个功能的重点,难点。

    2.如何解决重点难点以及收获

    3.运行截图

    4.结对编程体会。

    5.合作过程。

    6.版本控制。

    一,每个功能的重点,难点

          (1)功能一的重点难点

               重点难点1:应该选择什么样的输入,操作数和运算符随机产生还是用户自己输入,如果随机产生要如何操作,如果用户自己输入要以什么样的形式输入
               重点难点2:如何处理四则运算算式。
               重点难点3:将输入的结果与正确结果比较,然后按照要求输出。
         (2)功能二的重点难点
               功能二的要求:在功能一要求的基础上加上有括号的运算。
               重点难点:加上有括号的运算,我们当初分析的时候是用括号匹配的方法,括号优先级最高,优先算括号里面的算式。
         (3)功能三的重点难点
                功能三的要求:输入题目道数,然后输出四则运算算式以及结果到.txt文件中,注意输出结果右对齐,与算式有一定的距离。
                重点难点:将输出放到.txt文件中。
         (4)  功能四的重点难点
                功能四的要求:支持分数运算,不加括号,输出也是用分数的形式输出,例如1/2 + 2/3 +1+1=3 1/6。
                重点难点:支持分数运算,通过通分来进行运算,结果是最简分数(几又几分之几)。

    二,合作中如何解决重点难点以及收获

             (1)功能一:

               因为要支持出题4个数的四则运算题目,针对的用户是初中生,所以题目难度不能太过于简单,也不能过于困难。如果题目随机生成,有太大的随机性,且容易产生重复,用随机数自动生成四个数的四则运算也会比较麻烦,考虑的情况会比较繁多。开始,我们用random生成两个数加减乘除的运算,运行成功,实现支持4个数的四则运算的时候,因为要考虑的情况太过于复杂,写完就400多行代码了,且题目易重复。想想功能一实现就这样艰难。于是想通过自己输入出题,然后让人做的形式实现,且自己出题可以避免重复。题以字符串的出现,然后对字符串进行处理,然后对题进行计算。

    对字符串进行处理,判断表达式格式是否正确的代码实现如下:

    //检查表达式格式是否正确
         public static boolean checkFormat(String str)
         {
                // 校验是否以“=”结尾
                if ('=' != str.charAt(str.length() - 1))
                {
                    return false;
                }
                // 校验开头是否为数字或者“(”
                if (!(isCharNum(str.charAt(0)) || str.charAt(0) == '('))
                {
                    return false;
                }
                char c;
                // 校验
                for (int i = 1; i < str.length() - 1; i++) 
                {
                    c = str.charAt(i);
                    if (!isCorrectChar(c))
                    {// 字符不合法
                        return false;
                    }
                    if (!(isCharNum(c))) {
                        if (c == '-' || c == '+' || c == '*' || c == '/') {
                            if (c == '-' && str.charAt(i - 1) == '(')
                            {// 1*(-2+3)的情况
                                continue;
                            }
                            if (!(isCharNum(str.charAt(i - 1)) || str.charAt(i - 1) == ')')) 
                            {// 若符号前一个不是数字或者“)”时
                                return false;
                            }
                        }
                        if (c == '.') 
                        {
                            if (!isCharNum(str.charAt(i - 1)) || !isCharNum(str.charAt(i + 1))) 
                            {// 校验“.”的前后是否位数字
                                return false;
                            }
                        }
                    }
                }
                return isBracketCouple(str);// 校验括号是否配对
            }

             (2)功能二:

               对于在功能一的基础上,实现括号。我们是利用栈实现括号匹配算法。并且使用了map对运算符进行了优先级处理。

    符号的优先级处理代码如下:

    public static final Map<Character, Integer> symLvMap = new HashMap<Character, Integer>();// 符号优先级map
        static 
        {
                symLvMap.put('=', 0);
                symLvMap.put('-', 1);
                symLvMap.put('+', 1);
                symLvMap.put('*', 2);
                symLvMap.put('/', 2);
                symLvMap.put('(', 3);
                symLvMap.put(')', 1);
         }

    括号匹配的代码如下:

    //校验括号是否配对
         public static boolean isBracketCouple(String str) 
         {
                LinkedList<Character> stack = new LinkedList<Character>();
                for (char c : str.toCharArray()) 
                {
                    if (c == '(') 
                    {
                        stack.add(c);
                    } else if (c == ')') 
                    {
                        if (stack.isEmpty()) 
                        {
                            return false;
                        }
                        stack.removeLast();
                    }
                }
                if (stack.isEmpty()) 
                {
                    return true;
                } else 
                {
                    return false;
                }
            }

             (3)功能三:

              1.对于输入题目道数是正整数的判断,不能是英文(test),负数(-100),浮点数(3.5)。开始是定义了一个int型的变量,然后对变量进行正整数判断,把负整数去掉。

    但是当输入英文,负数和浮点数的时候,运行的时候报错了。后来采用字符串的格式进行输入,然后对字符串的进行在数值范围的判断。

    判断输入题目道数是正整数的代码如下:

    //判断输入的题目数是否为正整数
         public boolean judgeInput(String str)
         {
            boolean flag=true;
            for(int j=0;j<str.length();j++)
             {
                 if(!(str.charAt(j)>=48&&str.charAt(j)<=57))
                 {
                 System.out.println("题目数量必须是 正整数。");
                 flag=true;
                 break;
                 }
                 else 
                 {
                     flag=false;
                 }
             }
            return flag;
            
         }

               2.将题目和答案输出到.txt文件中

    实现代码如下:

     //将表达式写入文件answer.txt
                 try 
                 {
                      if (!file.exists()) 
                      {
                            file.createNewFile();
                      }
                      FileWriter writer = new FileWriter(file,true);
                      if(true)
                      {
                            results = System.getProperty("line.separator")+results;
                      }
                      writer.write(results);
                      writer.flush();
                      writer.close();
                 } 
                 catch (IOException ex)
                 {
                      ex.printStackTrace();
                 }

             (4)功能四:

             方法是先求出两个分数分母的最小公倍数,通分后,再对两个分子的加减乘除,最后约简结果分数的分子和分母,即用分子分母的最大公约数分别除分子和分母。再按顺序输入分子和分母,在控制台上输出其运算结果。

    求最大公约数的代码如下:

     static int gcd(int m,int n)
    {
    int t,r;//辗转相除法 if(m < n) { t = m; m = n; n = t; } while(n != 0) { r = m%n; m = n; n = r; } return m; }

    求最小公倍数代码如下:

    static int lcm(int m,int n)
    {
    int i = gcd( m,n); int j = (m/i)*(n/i)*i; return j; }

    收获:

    1.在制定代码规范的时候,因为我们都有自己的习惯,所以在制定规则时讨论了较长时间,但是彼此为对方考虑,都各自让步,最终制定了两个人都能接受的代码风格规范。这告诉我们,要多为对方考虑一点,这样才能使合作更愉快,后面实现的过程中也证明了这一点。

    2.在考虑实现出题的时候,我和霞都不约而同的用随机数生成出题。觉得可简单了,认为一两个小时就能完成功能一,开始实现起来两个数的加减乘除很快就完成了,然后按照老师要求要完成四个数的加减乘除,实现起来情况就很复杂了,我们完成一个demo的时候就差不多500行代码了,花费了3个多小时,并且有出题重复的情况。后来就一起讨论用自己出题的方式解决,可以避免重复,并且可以控制难度。实现的过程,我们让结果返回double,因为除法肯定会有小数的出现。在一起讨论实现的过程中,知道了不要把一个问题看得太简单,不然容易眼高手低,要明白需求,再开始做事。

    3.在对输入题目以字符串的形式写表达式时,要对输入的表达式做各种判断,不然表达式会出错,操作数是不是数字,操作数是不是“+,-,*,/”,最后是不是以等号结尾。一个人总是会疏忽很多小细节,幸运的是,我和霞结对编程,总能考虑到对方疏忽的一些小问题。

    4.在结对编程的过程中,一个人在编,另外一个人在旁边盯着,总是能够及时提醒对方触犯的代码规范和犯的语法错误,相互批评,指导,和交流,比一个人编程好玩多了,编程速度虽然没有一个人快,但是两个人编程的质量更高,错误更少。

    5.功能3将结果输出到.txt文件中,运行输入表达式的时候,打开.txt文件一看结果都在,以为自己成功了,但是可开心了,然后霞察觉文件的表达式很多,且有重复,我们恍然大悟,知道自己原始数据没有清空,然后两个人寻找解决对策,后来决定在输入题目语句后面将.txt赋空值,两个人一起发现和解决问题的过程真是很nice。

    三,运行截图

    功能1,2截图

    功能3截图:

     

    四,结对编程体会

    结对编程之前,我并没有发现结对编程的好处,但在共同完成作业的时候,切身感受到结对编程的好处。两人合作的过程,是一段“美好且痛苦又幸福”的体验。

    在四个功能的实现过程中,我们遇见了很多没有想到的困难。在遇见一个难点的时候,或者运行时出错的时候,两个人一起想办法解决,两个人虽然都有不一样的想法,但是都是为了解决同一个问题,当谁的办法能够解决问题的时候,我们都特别开心。完成作业的同时,我获得了知识,也从对方的身上学到了很多,学习能力和思维方式都得到了进步,发现结对编程会使两个人加在一起,会达到1+1>2的效果。

    五,合作过程

    我们结对编程是在软件所220完成,附上我们两人结对编程的照片。

    六,版本控制

    git地址:https://coding.net/u/huyr000/p/FourArithmetic/git

     

  • 相关阅读:
    2017中国大学生程序设计竞赛
    2017中国大学生程序设计竞赛
    2017中国大学生程序设计竞赛
    2017中国大学生程序设计竞赛
    计算几何之凸包模板
    计算几何之凸包模板
    Kafka知识点汇总
    python 爬虫1 開始,先拿新浪微博開始
    iOS 7的手势滑动返回
    Ctrl+Enter 选中文本提交
  • 原文地址:https://www.cnblogs.com/huyourongmonkey/p/7637721.html
Copyright © 2011-2022 走看看