JAVA结对编程--阶段总结

一、需求分析

1.基本需求

  • 随机生成n道题目
  • 支持整数、分数,支持多运算符
  • 能判断正误,错误时给出正确答案
  • 能计算出正确率

2.扩展需求

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

二、设计思路

在开始编程之前,我们一起仔细地阅读了项目的需求、各种具体细节,以及算法,进行了深入的讨论,总结了这次编程的主体内容,以及可能遇到的难点、问题。

1.主体内容

  • 随机数、随机公式、随机括号(随机生成括号)的生成(用抽象类实现,重写方法getRandom)
  • 将以上随机符号拼接成随机公式
  • 中缀表达式转后缀表达式
  • 后缀表达式转结果
  • 主函数(整体拼接)

2.难点、问题

  • 随机数、随机符号的组合方式
  • 随机括号的插入
  • 栈的知识、语法在中缀、后缀出结果的过程中的运用

3.类图

三、艰难的编程过程

1.随机公式生成阶段

  • 随机数的生成
    上网查了使用公式(int)(Math.random()*x)可生成0-x的随机数

  • 随机符号的生成
    经小伙伴的提醒,可使用每个数字对应每个符号

  • 随机括号插入
    • 我刚开始想的是用小伙伴的方法,利用随机数,一个数对应在相应的位置插入括号,另一个对应不插入,成功插入括号,但发现左右括号不相等
    • 为了解决左右括号不相等的问题,我决定加入控制条件flag2,记录插入的左括号个数,在最后添加缺少的右括号,成功解决了上面的问题,但又出现了左右括号扩住一个数字的问题
    • 于是我又添加了flag4,控制不连续插入左右括号,成功解决了所有问题~!!
  • (左)括号代码:

  • 测试成功截图:

2.中缀转后缀阶段

  • 首先的困难是栈的理解,刚开始我们看了好多资料都不太懂,直到看到这张图,我一下子就懂了,也立即给我的小伙伴也讲懂了

  • 然后就是java中有关栈的语法,上网查阅了资料
    Stack<变量名> 栈名=new Stack<变量名>()表示新建一个栈。
    栈名.pop()表示将栈顶元素弹出
    栈名.push(x)表示将x压入栈中
  • 中缀转后缀就要将公式中的元素一个一个遍历,我刚开始用了charAt方法,后来出现了算数一直算不对的情况,通过debug发现charAt方法会将两位数或多位数拆成个位数,当我又一次陷入困境时,我的小伙伴又给我提供了思路,可以用字符串名.split(" "),将每个字符存储起来。
    错误测试:

  • 但修正了上述错误之后,系统又开始一直报错,最后发现是字符串的判定要用待比较的字符串.equals(要比较的字符串)
    报错提示:

  • 改正了上述错误之后,结果还是不对,我通过一遍一遍艰难的debug,发现了我的后缀表达式结尾竟然是数字,我又检查了一遍代码,发现是我忘记将栈中最后的元素弹出...
    debug过程:

    忘加的出栈过程:

3.后缀转结果阶段

  • 在这里我又想到了小伙伴给我提供的思路,可以用split语句将后缀表达式依次遍历,利用栈,遇到符号就将栈顶的连个元素弹出栈,并进行计算。
  • 进行测试时遇到了字符串忘记转整型的问题,小伙伴上网查询了字符串转整型的方法Integer.valueOf(字符串),测试成功!!

4.最终拼接阶段

  • 这一部分比较简单,就出现了正确率计算错误的问题,最后发现正确率应该这样子加double括号

5.最后的最后

  • 测试成功~~~~~~~~

6.后续发现的bug

  • 除法计算时会向下取整,而且会出现分母为0的情况,而且程序还有待优化、不够简洁,下周会进行修复

四、核心代码解释

  • 生成随机数代码:
import java.util.*;
import java.lang.*;
public class getRandom {
String s;
String str[]=new String[100];
char a,b; //a:插入的数字,b:插入的符号
int x; //x:插入符号的个数
char flag1,flag3;   //flag1:左括号,flag3:右括号
int flag2=0,flag4=0; //flag2:插入左括号的个数,flag4:控制不连续插入左右括号
public void storeRandom(int n) {
    for(int i=1;i<=n;i++) {     //存储随机生成的的每个公式
        s="";
        x=(int)(Math.random()*6)+3;
        Random r3=new RandomZuo();
        flag1=r3.getRandom();
        for(int j=1;j<=x;j++) {    //依次插入数字、公式
            Random r1=new RandomNum();
            a=r1.getRandom();
            s=s+(int)a+" ";
            if(flag2>0&&flag4==0) {
                Random r6=new RandomYou();
                flag3=r6.getRandom();
                if(flag3==')') {
                    s=s+flag3+" ";
                    flag2--;
                }
            }
            flag4=0;
            Random r2=new RandomChar();
            b=r2.getRandom();
            s=s+b+" ";
            Random r4=new RandomZuo();
            flag1=r4.getRandom();
            if(flag1=='('&&j<x-1) {
                s=s+flag1+" ";
                flag2++;
                flag4=1;
            }
        }
        Random r5=new RandomNum();
        s=s+(int)r5.getRandom()+" ";
        while(flag2!=0) {
            s=s+")"+" ";
            flag2--;
        }
        str[i]=s;
    }
}
public String[] retRandom() {
    return str;
}   //返回随机生成的公式
}
  • 中缀转后缀代码:
import java.util.*;
public class ZhongzhuiToHouzhui {
    public String result(String s) {
        Stack<String> sta = new Stack<String>();   //新建栈
        String str = "";
        String[] s1=s.split(" ");
        int length = s1.length;
        for (int i = 1; i <= length; i++) {    //依次遍历元素,转为后缀表达式
            String temp;
            String c = s1[i-1];
            if (c.equals(" "))
                break;
            else if (c.equals("+") || c.equals("-")) {   //遇到优先级最低的“+”、“-”,弹出“(”之前的所有元素
                while (sta.size() != 0) {
                    temp = sta.pop();
                    if (temp.equals("(")) {
                        sta.push("(");
                        break;
                    }
                    str = str + temp + " ";
                }
                sta.push(c);
            } else if (c.equals("*")|| c.equals("/")) {   //遇到优先级高的“*”、“/”,弹出“(”之前的“*”、“/”
                while (sta.size() != 0) {
                    temp = sta.pop();
                    if (temp.equals("(") || temp.equals("+") || temp.equals("-")) {
                        sta.push(temp);
                        break;
                    } else
                        str = str + temp + " ";
                }
                sta.push(c);
            } else if (c.equals("(")) {     //遇到“(”直接入栈
                sta.push(c);
            } else if (c.equals(")")) {     //遇到“)”,弹出“(”之前的所有元素
                while (sta.size() != 0) {
                    temp = sta.pop();
                    if (temp.equals("("))
                        break;
                    else
                        str = str + temp + " ";  //遇到数字,直接存入数组
                }
            } else
                str = str + c + " ";
        }
        while (sta.size()!=0){     //弹出栈中剩余的元素
            str=str+sta.pop()+" ";
        }
        return str;
    }
}
  • 后缀转结果代码
import java.util.*;
import java.lang.*;
public class getResult {
public int getResult(String s){
    Stack<Integer> stack=new Stack<Integer>();   //新建栈(Integer类型)
    String[] str=s.split(" ");
    int n=str.length;
    int a=0,b=0;
    for (int i=1;i<=n;i++){     //依次遍历元素,计算结果
        String c=str[i-1];
        if (c.equals("+") || c.equals("-") || c.equals("*") || c.equals("/")){    //遇到符号,弹出栈顶两个元素,并计算结果
            a=stack.pop();
            b=stack.pop();
            stack.push(jisuan(b,a,c));      //将计算后的结果重新压入栈中
        }
        else {       //遇到数字,直接入栈
            stack.push(Integer.valueOf(c));
        }
    }
    return stack.pop();
}
public int jisuan(int a,int b,String c){    //计算结果
    if (c.equals("+")){
        return a+b;
    }
    else if (c.equals("-")){
        return a-b;
    }
    else if (c.equals("*")){
        return a*b;
    }
    else if (c.equals("/")){
        if (b==0){
            System.out.println("生成的公式出现分母为0的情况,错误!");
            System.exit(1);
            return 1;
        }
        else
            return a/b;
    }
    else{
        System.out.println("Error!");
        return 0;
    }
}
}

五、运行结果截图


六、代码托管地址

七、对结对的小伙伴进行评价

  • 我在本次结对任务中扮演领航员的角色,在对方遇到问题时给提供解决思路。我的小伙伴在本次结对中扮演领航员的角色,负责编写代码。

八、总结

  • 这次的结对编程是对我们的挑战,也是对我分析、解决问题已经编程能力的挑战。合作完成任务提高了彼此的积极性,也为我们的学习提供了一个新的方式。在不断完善代码的过程中,也增强了自身对程序的进一步理解。有所收获但也有许多不足之处。分工、配合、效率……仍然是我们接下来的学习中的一大挑战,我们会在接下来的任务中逐渐磨合,将问题逐一攻破。

    九、预估与实际

Planning 计划 预估耗时(分钟) 实际耗时
Estimate 预估这个任务需要多长时间 1110 1580
Development 开发
Analysis 需求分析(包括学习新技术) 40 90
Design Spec 生成设计文档 30 30
Design Review 设计复审 60 60
Coding Standard 代码规范(为目前的开发制定合适的规范) 40 40
Design 具体设计 70 70
Coding 具体编码 700 1100
Code Review 代码复审 60 60
Test 测试(自我测试、修改代码、提交修改) 40 60
Reporting 报告
Test Report 测试报告 20 20
Size Measurement 计算工作量 10 10
Postmortem&Process Improvement Plan 事后总结并提出改进计划 40 40
合计 1110 1580

十、参考

猜你喜欢

转载自www.cnblogs.com/ln-0407/p/10652954.html