保龄球计分程序

发布时间 2023-04-01 15:45:15作者: 章鱼哥的小舅子

  总结:从保龄球计分程序中,我对重构有了一点小小的认知,即:把复杂的程序简洁化,把一个具有多个功能的函数拆分成多个函数(如果可以的话,尽可能的拆分一个具有明显功能的类出来),而且为了保障代码的可行性,每进一步对程序功能的添加都需要进行功能的全方位测试,避免到最后程序出现一些不可控的错误。

实验过程:

保龄球计分程序的需求:

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];      //不中的情况则是两个值相加就是所得分数

}

整体代码:

 

还有最重要的一点:不要忘记写测试,每进行一个步骤都要进行测试