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

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

需求分析

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

设计思路

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

本周达成:

①能够随机生成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;

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

运行截图:
1271410-20180423034104925-1311353271.png

码云链接

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

JUnit测试

运算的测试:
1271410-20180423042053217-1048519336.png

后缀表达式的测试:
1271410-20180501231910702-608012258.png

UML图

1271410-20180423050801950-1428080237.png

PSP

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

遇到的困难与解决方法

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

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

然后发现成功了。

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

点评伙伴

本周的合作是基于上周的基础上的。随着合作的次数增加,我和队友的配合也越来越好了,因此结队编程的效率有了不少提升,关键的一点是现在两个人如果意见上有什么不统一也比较敢于发表出来,这样很有利于我们的思考。
这次我的队友表现也很好~能和我共同学习一起进步~希望今后能够一直合作下去。

结队编程照片:
1271410-20180422205701094-1800197080.png

转载于:https://www.cnblogs.com/zhuwenyuan/p/8909465.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Sailfin Voron是一种热带淡水鱼类,也被称为天使鱼科中的“天使鱼”。它是一种美丽的鱼类,拥有华丽而多彩的外观,是鱼缸中的宠物之一。 Sailfin Voron是鱼缸爱好者中受欢迎的一种鱼类,因为它具有非常迷人的外观。它的身体侧扁,呈纺锤形,背鳍和尾鳍非常长而尖,像帆一样,因此得名“Sailfin Voron”。它的鳞片呈亮丽的金色,闪闪发光,让它成为鱼缸中的一道亮丽风景线。 Sailfin Voron主要生活在热带地区的淡水湖泊和河流中,它们喜欢水温较暖的环境。它们是杂食性动物,食物包括浮游生物、小型昆虫和水中植物。在鱼缸中,我们需要提供适合它们生活的环境,包括适宜的温度、水质和养分等。同时,Sailfin Voron也需要适当的空间来游动和活动,以保持它们的健康和快乐。 尽管Sailfin Voron是一种美丽的鱼类,但它们并不是最容易饲养的品种之一。它们对水质的要求较高,如果不注意水质的控制,可能会导致它们生病甚至死亡。另外,Sailfin Voron也需要一定的社交空间,一般建议将它们放在与其它和平相处的品种一起养殖。 总之,Sailfin Voron是一种美丽而迷人的鱼类,适合鱼缸爱好者饲养。尽管它们的饲养较为复杂,但只要我们提供适宜的环境和饲养条件,它们能够成为我们家中的迷人宠物。 ### 回答2: Sailfin Voron是一种来自非洲和亚洲的淡水鱼类,属于腔棘鱼科。它的特点是其宽大而鲜艳的背鳍,这是栖息在流动水域中的鱼类中比较罕见的特征。这种鱼的背鳍通常呈现出明亮的蓝色或绿色,具有优美的形状,因此得名“Sailfin Voron”。 Sailfin Voron的体形通常较为修长,侧扁且稍高,身体呈橢圆形。它的头部相对较小,口部较窄,适合捕食浮游生物和小型无脊椎动物。Sailfin Voron在水中游动灵活,非常迅捷,常常成群结队生活。它们寿命较长,通常可活到5-8年。 在水族馆中,Sailfin Voron是淡水鱼爱好者们非常喜欢的观赏鱼之一。它们的鲜艳背鳍和独特体形使其成为水族馆中的明星。作为观赏鱼,它们通常需要一定的鱼缸空间,以便能够自由游动及展示其美丽的背鳍。 在自然界中,Sailfin Voron主要栖息于淡水河流,湖泊和池塘等水体中。它们是杂食性鱼类,以浮游生物,植物碎屑和小型无脊椎动物为主要食物来源。在繁殖季节,雄性Sailfin Voron会展示出美丽的背鳍以吸引雌性。雌性一般会在水生植物中产卵,并由雄性受精。 尽管Sailfin Voron在野外的种群数量相对稳定,但是由于人类的过度捕捞以及水体污染等原因,它们的栖息地受到了一定程度的丧失和破坏。因此,保护Sailfin Voron和其栖息地的生态环境变得至关重要。只有通过合理科学的管理和保护措施,我们才能保护这些美丽的鱼类,同时也保护整个生物多样性。 ### 回答3: "Sailfin Voron" 是一种鱼类,属于海鲈科(Scientific name: Costa voron)。 Sailfin Voron 鱼体侧扁,背部呈蓝灰色,腹部为银白色。它们的特征之一是背鳍和臀鳍非常宽大,像帆一样般展开,因此得名“Sailfin”。体长大约在10-15厘米左右。这种鱼类主要栖息在沿岸水域,如河流和河口。它们喜欢在水下潜藏在水草或者水下的洞穴中。 Sailfin Voron 鱼类是杂食性动物,主要以浮游生物、小型底栖无脊椎动物和植物为食。它们是群居性鱼类,常常成群结队活动。在繁殖季节,雄性鱼会变得更鮮艳,以吸引雌性进行求偶。它们一般在水底崖壁或者岩石缝隙中产卵,卵孵化后雄性会负责守卫卵和幼鱼。 由于其独特的外观和行为习性,Sailfin Voron 鱼类受到了一些水族爱好者的喜爱。在一些水族馆中,你也可以看到这种鱼类。在养殖鱼类中,它们不需要过多特别的照顾,适合于养在较大的水族箱中。当然,对于购买和养殖这种鱼类,了解其适宜的水质和饲养方法是至关重要的。 总之,Sailfin Voron 是一种漂亮且有趣的鱼类,它们以其宽大的鳍以及独特的行为在水中展示出魅力,无论在自然环境还是在水族箱中都是令人赏心悦目的存在。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值