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);
}
}