The bowling game jest kolejną propozycją ćwiczenia, która zostało mocno spopularyzowana przez Wujka Boba. Związana jest ona z grą w kręgle. W tym ćwiczeniu bardzo ciekawym elementem jest system naliczania punktów. W bardzo dobry sposób sprawdza tok algorytmicznego myślenia.
Jak napisałem we wstępie, ćwiczenie to dotyczy gry w kręgle (ang. bowling game). Od klienta dostajemy kilka wymagań:
- Jeśli wszystkie twoje rzuty (ang. roll/throw) były chybione to wynik końcowy wynosi zero
- W każdym rzucie został strącony tylko jeden kręgiel (ang. pin). Wynik końcowy wynosi 20.
- W pierwszej turze (ang. frame) został trafiony spare, następnie zostały strącone trzy kręgle. Wynik końcowy wynosi 16.
- W pierwszej turze został trafiony strike, następnie zostały strącone trzy i cztery kręgle. Reszta rzutów była chybiona. Wynik końcowy wynosi 24.
- Wszystkie rzuty to strikes. Wynik końcowy wynosi 300.
Podczas gry w kręgle obowiązują pewne zasady:
- Jest dziesięć tur
- Jest dziesięć kręgli
- W każdej turze możemy wykonać dwa rzuty
- Jeśli w jednej turze w wyników dwóch rzutów osiągniemy wynik 10 to do tej tury zostanie doliczony wynik kolejnego rzutu - spare
- Jeśli w jednej turze w jednym rzucie osiągniemy wynik 10 to do tej tury zostanie doliczony wynik kolejnych dwóch rzutów - strike
Moja propozycja Javowa:
public class BowlingGameTest {
BowlingGame game = new BowlingGame();
//Should return zero as a score when all rolls are missed
@Test
public void shouldReturnZeroWhenAllRollsAreMissed() throws Exception {
// When
IntStream.range(0,20).forEach(roll->game.roll(0));
int score = game.getScore();
// Then
assertThat(score).isEqualTo(0);
}
//Should return 20 as a score when you knock down one pin per roll
@Test
public void shouldReturnTwentyWhenKnockDownOnePinPerRoll() throws Exception {
// When
IntStream.range(0,20).forEach(roll->game.roll(1));
int score = game.getScore();
// Then
assertThat(score).isEqualTo(20);
}
//Should return 16 as a score when you knock down spare in first frame followed by three
@Test
public void shouldReturnSixTeenWhenSpareIsKnockDown() throws Exception {
// When
game.roll(5);
game.roll(5);
game.roll(3);
IntStream.range(0,17).forEach(roll->game.roll(0));
int score = game.getScore();
// Then
assertThat(score).isEqualTo(16);
}
//Should return 24 as a score when you knock down strike in first frame followed by three and four
@Test
public void shouldReturnTwentyFourWhenStrikeIsKnockDown() throws Exception {
// When
game.roll(10);
game.roll(3);
game.roll(4);
IntStream.range(0,17).forEach(roll->game.roll(0));
int score = game.getScore();
// Then
assertThat(score).isEqualTo(24);
}
//Should return 300 as a score when you knock down all strikes
@Test
public void shouldReturnThreeHundredsWhenAllStrikesAreKnockDown() throws Exception {
// When
IntStream.range(0,20).forEach(roll->game.roll(10));
int score = game.getScore();
// Then
assertThat(score).isEqualTo(300);
}
private class BowlingGame {
int\[\] rolls = new int\[21\];
int roll = 0;
int index = 0;
int getScore() {
int score = 0;
for(int frame = 0; frame<10; frame++){
if(isStrike()) {
score += 10 + rolls\[index+1\] + rolls\[index+2\];
index++;
}
else if(isSpare()){
score += 10 + rolls\[index+2\];
index+=2;
} else{
score+=rolls\[index\] + rolls\[index+1\];
index+=2;
}
}
return score;
}
private boolean isSpare() {
return rolls\[index\] + rolls\[index+1\] == 10;
}
private boolean isStrike() {
return rolls\[index\] == 10;
}
void roll(int pins) {
rolls\[roll++\] = pins;
}
}
Kod jak zawsze w całości na GitHubie.
