Thursday, September 29, 2011

The Bowling Game Kata in PHP

I did the famous Bowling Game Kata and converted it from Java to PHP, and used PHPUnit for unit tests, and thought I'd share my code for anyone who wants to see it.

If you run the tests like:
 $ phpunit --testdox BowlingTest.php
you should see the tests all pass like:

    Bowling
       [x] Should roll gutter game
       [x] Should roll all ones
       [x] Should roll one spare
       [x] Should roll one strike
       [x] Should roll perfect game
 <?php 
      
 class Game
 { 
   private $rolls = array();
  
   public function roll($pins) {
     $this->rolls[] = $pins;
   } 
  
   public function score() {
     $score = 0;
     $rollsMax = count($this->rolls);
     $firstInFrame = 0;
  
     for ($frame = 0; $frame < 10; $frame++) {
       if ($this->isStrike($firstInFrame)) {
         $score += 10 + $this->nextTwoBallsForStrike($firstInFrame);
         $firstInFrame++;
       } else if ($this->isSpare($firstInFrame)) {
           $score += 10 + $this->nextBallForSpare($firstInFrame);
           $firstInFrame += 2;
       } else {
         $score += $this->twoBallsInFrame($firstInFrame);
         $firstInFrame += 2;
       }
     }
  
     return $score; 
   } 
  
   public function nextTwoBallsForStrike($firstInFrame) {
     return $this->rolls[$firstInFrame + 1] + $this->rolls[$firstInFrame + 2];
   }

   public function nextBallForSpare($firstInFrame) {
     return $this->rolls[$firstInFrame + 2];
   } 
  
   public function twoBallsInFrame($firstInFrame) {
     return $this->rolls[$firstInFrame] + $this->rolls[$firstInFrame + 1];
   }

  
   public function isStrike($firstInFrame) {
     return $this->rolls[$firstInFrame] == 10;
   }

   public function isSpare($firstInFrame) {
     return $this->rolls[$firstInFrame] + $this->rolls[$firstInFrame+1] == 10;
   }

   public function rollSpare() {
     $this->roll(5);
     $this->roll(5);
   }
 }


 class BowlingTest extends PHPUnit_Framework_TestCase {
   private $g;

   public function setUp() {
     $this->g = new Game;
   }

   /**
    * @test
    */
   public function Should_roll_gutter_game() {
     $this->rollMany(20, 0);
     $this->assertEquals(0, $this->g->score());
   }

   /**
    * @test
    */
   public function Should_roll_all_ones() {
     $this->rollMany(20, 1);
     $this->assertEquals(20, $this->g->score());
   }

   /**
    * @test
    */
   public function Should_roll_one_spare() {
     $this->g->rollSpare();
     $this->g->roll(3);
     $this->rollMany(17, 0);
     $this->assertEquals(16, $this->g->score());
   }

   /**
     * @test
    **/
   public function Should_roll_one_strike() {
     $this->rollStrike();
     $this->g->roll(3);
     $this->g->roll(4);
     $this->rollMany(16, 0);
     $this->assertEquals(24, $this->g->score());
   }

   /**
    * @test
    **/
   public function Should_roll_perfect_game() {
      $this->rollMany(12, 10);
      $this->assertEquals(300, $this->g->score());
   }

   public function rollMany($n, $pins) {
     for ($i = 0; $i < $n; $i++) {
         $this->g->roll($pins);
     }
   }

   public function rollStrike() {
     $this->g->roll(10);
   }
 }
 

1 comment:

  1. Is there an error here because your test for spare is trying to assert 16 but I figure 13. This is because a spare is 10, plus the next roll which is a 3. This totals 13.

    ReplyDelete

Followers