总结:从保龄球计分程序中,我对重构有了一点小小的认知,即:把复杂的程序简洁化,把一个具有多个功能的函数拆分成多个函数(如果可以的话,尽可能的拆分一个具有明显功能的类出来),而且为了保障代码的可行性,每进一步对程序功能的添加都需要进行功能的全方位测试,避免到最后程序出现一些不可控的错误。
实验过程:
保龄球计分程序的需求:
1:首先调用一个函数(add()),来记录击倒的保龄球个数。
2:再次调用一个函数(itsCurrentFrame(第几局)),表明我查看第几局的分数。
3:最后查看总分数,调用(score())函数。
保龄球计分程序的实现:
1:根据保龄球的特点可以把程序分为两个类:
1.1,计算当前所在的轮数。
1,首先用户传过来一个参数(需要编写一个add(int pins)的函数),这时需要进行判断(传过来的pins是否为10,因为一轮投掷两次,为了方便计数,引入变量firstThrow,默认true,如果为false,证明这是第二次,该轮结束;)
代码:
public void add(int pins){
itsScorer.addThrow(pins); //调用另一个类的函数(Scorer)来进行计分
adjustCurrentFrame(pins)(); //把判断的任务交给adjustCurrentFrame函数去操作。
}
public void addjustCurrentFrame(int pins){
//lastBallInFrame作用是判断投掷的是第几次(有两种可能,1:firstThrow=true且pins==10 2:firstThrow=false),如果满足其中的任意一项,则当前轮+ 1,且最大值为10,
if (lastBallInFrame(pins)){
advanceFrame(); //表示当前轮+1
}else{
firstThrow=false;
}
}
public boolean lastBallInFrame(int pins){
return (strike(pins) || !firstThrow); //strike()表示firstThrow=true且pins==10,这句话的意思是但凡有一个对,返回true
}
public boolean strike(int pins){
return (firstThrow && pins==10) //这俩都要满足,否则返回false
}
这时需要一个过渡函数来连接计算积分的类(Scorer),需要创建Scorer对象 aprivate Scorer itsScorer
public int score(){
return scoreForFrame(itsCurrentFrame); //当用户调用该函数时(不带参),他将返回最后一轮的积分(总积分)
}
public int scoreForFrame(int theFrame){
return itsScorer.scoreForFrame(theFrame); //这时候就需要计分类闪亮登场啦!! 在登场之前,还需要添加一个函数,因为你只传过去一个当前轮可不行,还得传击倒的保龄球数,不然怎么计算全中,补中,还有不中呢?对吧 ^~^,因此,故在第一个函数add()增添另一个函数。
}
变量有:private int itsCurrentFrame=0; private boolean firstThrow=true; private Scorer itsScorer;
整体代码为:
1.2,计算每一局的比分(Scorer)
此时传过来的值有两个,分别为击倒的保龄球数和需要查询的当前轮,这个类需要实现的东西为:每一轮加上投掷所击倒的分数+上一轮所得分数
1:因此我们可以主要定义为两个主要接收参数的函数即:addThrow()和scoreForFrame(),添加每轮击倒的保龄球数会涉及到投掷的次数,我们按最大的投掷次数来计算即:21次
代码:
定义变量:private int[] itsThrows=new int[21]; private int ball=0; private int itsCurrentThrow=0;
public int addThrow(int pins){
itsThrows[itsCurrentThrow++]=pins; //给每一轮添加所击倒的保龄球数,进而让scoreForFrame函数判断是全中,补中,还是不中
}
public int scoreForFrame(int theFrame){
int ball=0; int score=0;
for (int itsCurrentFrame=0;itsCurrentFrame<theFrame){
if (strike()){ //strike()表示判断当前传过来的值是否是10,
score+=10+nextTwoBallsForStrike(); //nextTwoBallsForStrike()表示加上下两次击倒的保龄球数
ball++; //表示增加一次投掷,
}else if (spare()){ //spare()表示的是两次投掷超过击倒10个保龄球
score+=10+nextBallForSpare(); //表示加上下一个击倒的保龄球数(即:第三次)
ball+=2; //补中,增加两次投掷
}else{
score+=twoBalls(); //表示两次投掷都没有超过击倒10个保龄球
ball+=2; //不中,增加两次投掷
}
}
return score;
}
public boolean strike(){
return (itsThrows[ball]==10); //判断传过来的pins是否为10
}
public int nextTwoBallsForStrike(){
return itsThrows[ball+1]+itsThrows[ball+2]; //表示全中则加上下一次和再下一次的击倒的保龄球数
}
public boolean spare(){
return (itsThrows[ball]+itsThrows[ball+1]>=10); //如果两次投掷相加大于等于10则断定为补中
}
public int nextBallForSpare(){ //补中则加上下一次的,也即是第三个值
return itsThrows[ball+2];
}
public int twoBalls(){
return itsThrows[ball]+itsThrows[ball+1]; //不中的情况则是两个值相加就是所得分数
}
整体代码:
还有最重要的一点:不要忘记写测试,每进行一个步骤都要进行测试
标签:10,ball,计分,int,程序,pins,保龄球,public From: https://www.cnblogs.com/zygdxjz/p/17278696.html