[CodeKata][Java] Bowling Game - Pajace/CodeKata GitHub Wiki

Production code

public class Game {

    private int currentRoll = 0;
    private int[] rolls = new int[21];

    public void rollManyBall(int... pingsDown) {
        for (int pins : pingsDown) {
            rolls[currentRoll++] = pins;
        }
    }


    public int getScore() {
        int score = 0;
        int currentFrameIndex = 0;
        for (int frame = 0; frame < 10; frame++) {
            BowlingStrategy bs = createBowlingStrategy(currentFrameIndex);
            score += bs.calculateScore(rolls, currentFrameIndex);
            currentFrameIndex += bs.getIncreasedIndex();
        }

        return score;
    }

    private boolean isStrike(int frameIndex) {
        return rolls[frameIndex] == 10;
    }

    private boolean isSpare(int frameIndex) {
        return rolls[frameIndex] + rolls[frameIndex + 1] == 10;
    }

    public BowlingStrategy createBowlingStrategy(int currentIndex) {
        if (isStrike(currentIndex))
            return new StrikeBowling();
        else if (isSpare(currentIndex))
            return new SpareBowling();
        else
            return new NormalBowling();
    }

    interface BowlingStrategy {
        int calculateScore(int rolls[], int currentIndex);

        int getIncreasedIndex();
    }

    class StrikeBowling implements BowlingStrategy {
        @Override
        public int calculateScore(int[] rolls, int currentIndex) {
            return 10 + rolls[currentIndex + 1] + rolls[currentIndex + 2];
        }

        @Override
        public int getIncreasedIndex() {
            return 1;
        }
    }

    class SpareBowling implements BowlingStrategy {
        @Override
        public int calculateScore(int[] rolls, int currentIndex) {
            return 10 + rolls[currentIndex + 2];
        }

        @Override
        public int getIncreasedIndex() {
            return 2;
        }
    }

    class NormalBowling implements BowlingStrategy {
        @Override
        public int calculateScore(int[] rolls, int currentIndex) {
            return rolls[currentIndex] + rolls[currentIndex + 1];
        }

        @Override
        public int getIncreasedIndex() {
            return 2;
        }
    }
}

Test Case

import org.junit.Before;
import org.junit.Test;

import static com.google.common.truth.Truth.assertThat;

public class GameTest {

    private Game game = null;

    @Before
    public void setUp() throws Exception {
        game = new Game();
    }

    @Test
    public void roll_all_1_and_score_should_be_20() {
        int expected = 20;

        game.rollManyBall(1, 1,
                1, 1,
                1, 1,
                1, 1,
                1, 1,
                1, 1,
                1, 1,
                1, 1,
                1, 1,
                1, 1);
        int actual = game.getScore();

        assertThat(actual).isEqualTo(expected);
    }

    @Test
    public void roll_all_0_and_score_should_be_0() {
        int expected = 0;

        game.rollManyBall(0, 0,
                0, 0,
                0, 0,
                0, 0,
                0, 0,
                0, 0,
                0, 0,
                0, 0,
                0, 0,
                0, 0);
        int actual = game.getScore();

        assertThat(actual).isEqualTo(expected);
    }

    @Test
    public void roll_spare_and_followed_by_7() {
        int expected = (10 + 7) + 7;

        game.rollManyBall(4, 6,
                7, 0,
                0, 0,
                0, 0,
                0, 0,
                0, 0,
                0, 0,
                0, 0,
                0, 0,
                0, 0);
        int actual = game.getScore();

        assertThat(actual).isEqualTo(expected);
    }

    @Test
    public void roll_strike_and_followed_by_3_and_4() {
        int expected = (10 + 3 + 4) + 3 + 4;

        game.rollManyBall(10,
                3, 4,
                0, 0,
                0, 0,
                0, 0,
                0, 0,
                0, 0,
                0, 0,
                0, 0,
                0, 0);
        int actual = game.getScore();

        assertThat(actual).isEqualTo(expected);
    }

    @Test
    public void roll_perfect_game_and_score_should_be_300() {
        int expected = 300;

        game.rollManyBall(10,
                10,
                10,
                10,
                10,
                10,
                10,
                10,
                10,
                10, 10, 10);
        int actual = game.getScore();

        assertThat(actual).isEqualTo(expected);
    }
}