March 20, 2007 - Spare!

I am impatient to be done now, so I'll try to get through the code for spares quite quickly so that I can review my findings.

According to the rules:

      // 2.1.6 A spare is scored when pins left standing after the first delivery are knocked down with the
      // second delivery in that frame. It is marked by a (/) in the small square in the upper righthand
      // corner of the frame. The count for a spare is 10 plus the number of pins knocked
      // down by the player’s next delivery.}
    

From now on, I'll just show tests alternating with code unless I come across something that I want to draw attention to.

I need an isSpare() method:


    @Test
    public void allPinsDownWithSecondBallIsSpare(){
      frame.addBall(6);
      frame.addBall(4);

      assertThat(frame.isSpare(), is(true));
    }

    @Test
    public void ninePinsDownIsNotASpare(){
      frame.addBall(6);
      frame.addBall(3);

      assertThat(frame.isSpare(), is(false));
    }

    @Test
    public void aStrikeIsNotASpare(){
      frame.addBall(10);
      assertThat(frame.isSpare(), is(false));
    }


    public boolean isSpare() {
      return ballCount >= 2
          && balls[0] + balls[1] == PINS_IN_FRAME
          && !isStrike();
    }
    

Spares are marked with a '/':


    @Test
    public void aSpareIsMarkedBySlash(){
      frame.addBall(9);
      frame.addBall(1);

      assertThat(frame.getFirstBall(), is("9"));
      assertThat(frame.getSecondBall(), is("/"));
    }

    public String getSecondBall() {
      if(isStrike() && ! lastFrame){
        return "";
      }
      if(isSpare()){
        return "/";
      }
      return formatBall(balls[1]);
    }
    

A spare needs one bonus ball:


    @Test
    public void aSpareNeedsOneBonusBall(){
      frame.addBall(9);
      frame.addBall(1);

      assertThat(frame.needsMoreBalls(), is(true));
    }

    public boolean needsMoreBalls() {
      return (isStrike() || isSpare()) && ballCount <3
          || ballCount < 2;
    }


    @Test
    public void spareShouldScoreTenPlusNextDelivery() {
      frame.addBall(6);
      frame.addBall(4);
      frame.addBall(5);

      assertThat(frame.getCumulativeScore(), is(15));
    }

    public void addBall(int pins) {
      if(pins > PINS_IN_FRAME || pins < 0) {
        throw new IllegalArgumentException("Invalid pin count - " + pins);
      }

      if(! isStrike()){
        if(ballCount == 1 && balls[0] + pins > PINS_IN_FRAME) {
          throw new IllegalArgumentException("Total pin count invalid");
        }
      }

      balls[ballCount++] = new Integer(pins);
    }
    

And that's it. Even the acceptance tests passed first time.

On previous attempts at implementing bowling scoring, I remember lots of moving strike logic and spare logic around trying to eliminate duplication. That just didn't happen this time. The strike logic was straightforward and the spare logic was trivially easy.

I have linked the final versions of all the code here...

...and I'll do one final run of the characterization tests (in another post) before I draw my conclusions.


Posted by Kevin Lawrence at March 20, 2007 07:07 PM


Trackback Pings

TrackBack URL for this entry:


Comments

I'm a little confused with the direction the Frame object has taken. The only time that a frame would conceivably have three balls is on the tenth frame:

"In the tenth frame, a player delivers three balls if a strike or spare is scored."

On the first nine frames, you don't get an extra ball in the case of a spare or strike, you just defer scoring that frame until the next frame is bowled. The sentence immediately before the one quoted above specifies two balls, unless a strike is scored. Did you interpret that as "if a strike is scored, the player delivers more balls"? In that case, the error may be in the story and might be appended:

"A player delivers two balls in each of the first nine frames unless a strike is scored, in which case the frame is ended immediately."

Or something like that. It looks like the "SingleGameScoring" tests need to be updated too.
[As an aside, it's annoying that the comments sanitize all html -- I had italics and breaks in the comment that were removed on preview]

Posted by: Rob Heiser on March 21, 2007 10:12 AM

What you probably missed is that balls can be allocated to more than one frame. I should see if I can make that clearer.

Whether the frame stores two or three balls is an implementation detail - all the matters is what the user sees.

Which reminds me that I need to update the UI to deal with three balls in the last frame. (maybe then I'll 'discover' that other bug that s carefully hidden in the Frame class ;-)

Posted by: Kevin Lawrence [TypeKey Profile Page] on March 22, 2007 03:34 PM

Post a comment




Remember Me?