个人项目总结

个人项目的大部分设计都在上一篇博客中描述的比较清楚。

下面描述一下个人项目最终版本和上次描述的不同。

一、分数除零不再作为一个异常,而是融入到控制流中区判断。原因是随机生成的表达式中除0并不是稀有事件,为了更好的用户体验,最终的分数类为:

public class Fraction {
    private int numer;    //    numerator
    private int denom;    //    denominator
    public Fraction(int numer,int denom){
        this.numer=numer;
        this.denom=denom;
    }
    public Fraction(int numer){
        this.numer=numer;
                this.denom=1;
    }    
    public int getNumer(){
        return numer;
    }
    public int getDenom(){
        return denom;
    }
    public void setNumer(int numer){
        this.numer=numer;
    } 
    public void setDenom(int denom){
        this.denom=denom;
    }
    public String toString(){
                simplfy();
                if(denom==1) return numer+"";
                else{
                    if(denom<0){
                        denom*=-1;
                        numer*=-1;
                    }
                   
                return numer+"/"+denom;}
    }
    public int gcd(int a,int b){
        while(a%b!=0){
            int temp=a%b;
            a=b;
            b=temp;
        }
        return b;
    }
    public int lcm(int a,int b){
        return a*b/gcd(a,b);
    }
    public void simplfy(){
        int a=gcd(numer,denom);
        numer/=a;
        denom/=a;
    }
    public Fraction add(Fraction op2){
        int newdenom=lcm(denom,op2.denom);
        int newnumer=numer*newdenom/denom+op2.numer*newdenom/op2.denom;
        Fraction f=new Fraction(newnumer,newdenom);
        f.simplfy();
        return f;
    }
    public Fraction minus(Fraction op2){
        int newdenom=lcm(denom,op2.denom);
        int newnumer=numer*newdenom/denom-op2.numer*newdenom/op2.denom;
        Fraction f=new Fraction(newnumer,newdenom);
        f.simplfy();
        return f;
    }
    public Fraction multi(Fraction op2){
        Fraction f=new Fraction(numer*op2.numer,denom*op2.denom);
        f.simplfy();
        return f;
    }
    public Fraction divide(Fraction op2)
                {
        Fraction f=new Fraction(numer*op2.denom,denom*op2.numer);
        f.simplfy();
        return f;
    }

    
    
    public static void main(String[] args){
        Fraction f=new Fraction(-4,6);
        f.simplfy();
        System.out.println(f);
    }
}
View Code

二、生成表达式的流程稍有改变。现在生成的表达式不会出现1+(3)这类含有无用括号的表达式,而且不会出现过多的连续左括号(以及其附带的结尾的过多连续右括号)

 流程变为: 

1.随机生成表达式所含数字个数,标志布尔变量置为false
2.如果当前要生成的数字不是最后一个要生成的数字,则随机决定是否生成左括号;如果生成了左括号则将标志布尔变量置为true
3.随机生成数字
4.随机生成运算符
5.如果标志布尔变量不为true,且当前左括号数大于右括号数则随机决定是否生成右括号
6.将标志布尔变量置为false
7.重复2到6直至最后一个数
8.补齐右括号
 
    public static String generateExpression(int t){
        String result="";
        Random rand=new Random(System.currentTimeMillis()+t);
        int num=rand.nextInt(100);
        int time=rand.nextInt(10);
        int paircount=0;
        int a=rand.nextInt(2);
        //while(a==0) 开启则会有自由奔放的多重左括号
        if(a==0) {
            result+='(';
            paircount++;
            a=rand.nextInt(2);
        }
        result+=Integer.toString(num);
        boolean ll=false;
        for(int i=0;i<time+2;i++){
            int op=rand.nextInt(4);
            if(op==0)result+='+';
            else if(op==1)result+='-';
            else if(op==2)result+='*';
            else result+='/';
            //while(a==0)
            if(a==0 && i<time+1){
                result+='(';
                paircount++;
                a=rand.nextInt(2);
                ll=true;
            }
            num=rand.nextInt(100);
            result+=Integer.toString(num);
            while(a!=0 && paircount>0 && !ll){
                result+=')';
                paircount--;
                a=rand.nextInt(2);
            }
            ll=false;
        }
        for(int i=paircount;i>0;i--)
            result+=')'; 
        result+='=';
        return result;
    }
View Code

三、其他部分基本不变。增加了读写文件使生成的题目得以保存,增加了正确率统计,增加了一个简单的用户界面,更方便使用。

总结起来,在这个个人项目中,我收获的经验就是做好模块设计、逐步实现完善。

项目的时间分配上应该多花时间在设计和学习工具上。先设计好,才会有好的实现。而如果此时工具还没掌握就会效率低下,所以这方面的准备也要尽早完成。

 

 

结对编程初探

结对编程。我的理念是先结♂对,再编程。

我和我的partner现在还处在懵懂的合作状态。虽然我们之前就已经有过无数次的一起工作,但是归根结底还是分工的时候多,合作的内容少。

 

在和他一起工作的最开始阶段,我们首先深刻地结对分析问题。

在此次的结对编程中,我们首先遭遇的问题是实现语言的不同,我用了JAVA,他则是用了C++风格的C。最终我们agree on C++

之后的问题包括需求的较大幅度变化,包括从新引入了小数和负数,这使得我的用正则判别变得更加复杂甚至冗余,而且为了简化操作引入的分数类则需要大改,作为数这个基类的派生类来重新写。

好消息是我们的工程化思想和面向对象思想从来没有到过这个地步,现在是得到锻炼的好机会。

我认为结对编程要发挥出1+1>2的效果实现精简可靠的软件的过程中,每个人需要沉浸其中,合力又独立地完成任务,而不是做吹毛求疵者和拼写查错者。