实践题目:保龄球比赛计分
保龄球比赛一般分十局,每局最多可扔两个球,如果第一个球将所有的瓶子打倒了,就没必要打第二个球。但每局的计分可能会依赖后面的扔球得分,即如果这局扔第一个球得了10分,我们称全中,那个这局的得分=10分+后面扔的两球的得分,如果这局扔两球共得10分,我们称补中,那个这局的得分=10分+后面扔的一球的得分。
如下为敏捷培训时教练画的图:
答案有很多种,如下是我个人的做法,具体过程就不展示了。直接附上代码:
BowlingGameTest.java
package com.bijian.study.bowling.test;
import org.junit.Assert;
import org.junit.Test;
import com.bijian.study.bowling.Game;
public class BowlingGameTest {
@Test
public void normal_roll_should_return_sum_of_tow_rolls() {
Game game = new Game(20);
game.roll(4);
game.roll(5);
Assert.assertEquals(4+5, game.getFrameScore(1));
Assert.assertEquals(4+5, game.getTotalScore());
}
@Test
public void spare_roll_should_return_sum_contain_next_roll() {
Game game = new Game(20);
game.roll(5);
game.roll(5);
game.roll(4);
game.roll(5);
Assert.assertEquals(5+5+4, game.getFrameScore(1));
Assert.assertEquals(4+5, game.getFrameScore(2));
Assert.assertEquals((5+5+4)+(4+5), game.getTotalScore());
}
@Test
public void strike_roll_should_return_sum_contain_next_two_rolls() {
Game game = new Game(20);
game.roll(10);
game.roll(5);
game.roll(4);
Assert.assertEquals(10+5+4, game.getFrameScore(1));
Assert.assertEquals(5+4, game.getFrameScore(2));
Assert.assertEquals((10+5+4)+(5+4), game.getTotalScore());
}
@Test
public void last_normal_roll_should_return_last_frame() {
Game game = new Game(20);
game.roll(10);
game.roll(5);
game.roll(4);
game.roll(3);
game.roll(4);
game.roll(10);
game.roll(3);
game.roll(3);
game.roll(0);
game.roll(3);
game.roll(2);
game.roll(8);
game.roll(10);
game.roll(10);
game.roll(2);
game.roll(3);
Assert.assertEquals(10+5+4, game.getFrameScore(1));
Assert.assertEquals(5+4, game.getFrameScore(2));
Assert.assertEquals(3+4, game.getFrameScore(3));
Assert.assertEquals(10+3+3, game.getFrameScore(4));
Assert.assertEquals(3+3, game.getFrameScore(5));
Assert.assertEquals(0+3, game.getFrameScore(6));
Assert.assertEquals(2+8+10, game.getFrameScore(7));
Assert.assertEquals(10+10+2, game.getFrameScore(8));
Assert.assertEquals(10+2+3, game.getFrameScore(9));
Assert.assertEquals(2+3, game.getFrameScore(10));
Assert.assertEquals((10+5+4)+(5+4)+(3+4)+(10+3+3)+(3+3)+(0+3)+(2+8+10)+(10+10+2)+(10+2+3)+(2+3), game.getTotalScore());
}
@Test
public void last_spare_roll_should_return_last_frame_with_add_one_roll() {
Game game = new Game(20);
game.roll(10);
game.roll(5);
game.roll(4);
game.roll(10);
game.roll(5);
game.roll(4);
game.roll(0);
game.roll(0);
game.roll(10);
game.roll(5);
game.roll(4);
game.roll(10);
game.roll(10);
game.roll(2);
game.roll(8);
game.roll(9);
Assert.assertEquals(2+8+9, game.getFrameScore(10));
Assert.assertEquals((10+5+4)+(5+4)+(10+5+4)+(5+4)+(0+0)+(10+5+4)+(5+4)+(10+10+2)+(10+2+8)+(2+8+9), game.getTotalScore());
}
@Test
public void last_strike_roll_should_return_last_frame_with_add_two_roll() {
Game game = new Game(20);
game.roll(10);
game.roll(5);
game.roll(4);
game.roll(10);
game.roll(10);
game.roll(10);
game.roll(10);
game.roll(5);
game.roll(4);
game.roll(10);
game.roll(10);
game.roll(10);
game.roll(8);
game.roll(2);
//多投算无效球
game.roll(3);
Assert.assertEquals(10+5+4, game.getFrameScore(1));
Assert.assertEquals(5+4, game.getFrameScore(2));
Assert.assertEquals(10+10+10, game.getFrameScore(3));
Assert.assertEquals(10+10+10, game.getFrameScore(4));
Assert.assertEquals(10+10+5, game.getFrameScore(5));
Assert.assertEquals(10+5+4, game.getFrameScore(6));
Assert.assertEquals(5+4, game.getFrameScore(7));
Assert.assertEquals(10+10+10, game.getFrameScore(8));
Assert.assertEquals(10+10+8, game.getFrameScore(9));
Assert.assertEquals(10+8+2, game.getFrameScore(10));
//只有10局
Assert.assertEquals(0, game.getFrameScore(11));
Assert.assertEquals((10+5+4)+(5+4)+(10+10+10)+(10+10+10)+(10+10+5)+(10+5+4)+(5+4)+(10+10+10)+(10+10+8)+(10+8+2), game.getTotalScore());
}
@Test
public void last_strike_roll_should_return_last_frame_with_add_two_max_score_roll() {
Game game = new Game(20);
game.roll(0);
game.roll(0);
game.roll(0);
game.roll(0);
game.roll(0);
game.roll(0);
game.roll(5);
game.roll(5);
game.roll(5);
game.roll(4);
game.roll(10);
game.roll(5);
game.roll(4);
game.roll(10);
game.roll(10);
game.roll(10);
game.roll(10);
//多投无效球
game.roll(10);
Assert.assertEquals(0+0, game.getFrameScore(1));
Assert.assertEquals(0+0, game.getFrameScore(2));
Assert.assertEquals(0+0, game.getFrameScore(3));
Assert.assertEquals(5+5+5, game.getFrameScore(4));
Assert.assertEquals(5+4, game.getFrameScore(5));
Assert.assertEquals(10+5+4, game.getFrameScore(6));
Assert.assertEquals(5+4, game.getFrameScore(7));
Assert.assertEquals(10+10+10, game.getFrameScore(8));
Assert.assertEquals(10+10+10, game.getFrameScore(9));
Assert.assertEquals(10+10, game.getFrameScore(10));
Assert.assertEquals((0+0)+(0+0)+(0+0)+(5+5+5)+(5+4)+(10+5+4)+(5+4)+(10+10+10)+(10+10+10)+(10+10), game.getTotalScore());
}
@Test
public void all_strike_roll_should_return_all_roll_with_last_two_max_score() {
Game game = new Game(20);
game.roll(10);
game.roll(10);
game.roll(10);
game.roll(10);
game.roll(10);
game.roll(10);
game.roll(10);
game.roll(10);
game.roll(10);
game.roll(10);
game.roll(10);
//多投算无效球
game.roll(5);
Assert.assertEquals(10+10+10, game.getFrameScore(1));
Assert.assertEquals(10+10+10, game.getFrameScore(2));
Assert.assertEquals(10+10+10, game.getFrameScore(3));
Assert.assertEquals(10+10+10, game.getFrameScore(4));
Assert.assertEquals(10+10+10, game.getFrameScore(6));
Assert.assertEquals(10+10+10, game.getFrameScore(7));
Assert.assertEquals(10+10+10, game.getFrameScore(8));
Assert.assertEquals(10+10+10, game.getFrameScore(9));
Assert.assertEquals(10+10, game.getFrameScore(10));
Assert.assertEquals((10+10+10)+(10+10+10)+(10+10+10)+(10+10+10)+(10+10+10)+(10+10+10)+(10+10+10)+(10+10+10)+(10+10+10)+(10+10), game.getTotalScore());
}
@Test
public void all_zero_roll_should_return_zero_score() {
Game game = new Game(20);
game.roll(0);
game.roll(0);
game.roll(0);
game.roll(0);
game.roll(0);
game.roll(0);
game.roll(0);
game.roll(0);
game.roll(0);
game.roll(0);
game.roll(0);
game.roll(0);
game.roll(0);
game.roll(0);
game.roll(0);
game.roll(0);
game.roll(0);
game.roll(0);
game.roll(0);
game.roll(0);
Assert.assertEquals(0+0+0, game.getFrameScore(1));//0
Assert.assertEquals(0+0+0, game.getFrameScore(2));//0
Assert.assertEquals(0+0+0, game.getFrameScore(3));//0
Assert.assertEquals(0+0+0, game.getFrameScore(4));//0
Assert.assertEquals(0+0+0, game.getFrameScore(5));//0
Assert.assertEquals(0+0+0, game.getFrameScore(6));//0
Assert.assertEquals(0+0+0, game.getFrameScore(7));//0
Assert.assertEquals(0+0+0, game.getFrameScore(8));//0
Assert.assertEquals(0+0+0, game.getFrameScore(9));//0
Assert.assertEquals(0+0+0, game.getFrameScore(10));//0
Assert.assertEquals((0+0+0) + (0+0+0) + (0+0+0) + (0+0+0) + (0+0+0) + (0+0+0) + (0+0+0) + (0+0+0) + (0+0+0) + (0+0+0), game.getTotalScore());
}
}
Game.java
package com.bijian.study.bowling;
/**
* 保龄球比赛,计算每局分数及总分
* 实现方法:
* 采用rollScore数组记录比赛每次投球的分数,如果在一局当中,第一个球为满分的话,第二个球无需投,但在此数组中将其设置为0
* 采用rollScoreState数组记录rollScore对应的下标是真实的分数还是免投设置的值
*
* @author BIJIAN
*/
public class Game {
//满分值
public static int MAX_SCORE = 10;
//记录比赛每次投球的分数,如果在一局当中,第一个球为满分的话,第二个球无需投,但在此数组中将其设置为0
private int[] rollScore;
//rollScoreState记录rollScore对应的下标是真实的分数还是免投设置的值
private boolean[] rollScoreState;
//num为2*实际比赛的局数
private int num;
//投球的下标记数器
private int currentRoll;
/*
* 构造方法
*/
public Game(int num) {
this.num = num;
rollScore = new int[num+4];
rollScoreState = new boolean[num+2];
this.currentRoll = 0;
}
/*
* 投球
*/
public void roll(int pin) {
if(currentRoll >= num + 2) {
return;
}
if(currentRoll > num && rollScore[currentRoll-1] == MAX_SCORE) {
return;
}
rollScore[currentRoll++] = pin;
if(pin == MAX_SCORE && currentRoll < num) {
rollScore[currentRoll] = 0;
rollScoreState[currentRoll++] = true;
}
}
/*
* 获取指定局次的分数
*/
public int getFrameScore(int frame) {
if(frame > num /2) {
return 0;
}
int res = rollScore[(frame-1)*2] + rollScore[(frame-1)*2 + 1];
if(rollScore[(frame-1)*2] == MAX_SCORE) {
res += rollScore[frame*2] + rollScore[frame*2 + 1];
if(rollScore[frame*2] == MAX_SCORE && rollScoreState[(frame-1)*2 + 1]) {
res += rollScore[(frame+1)*2];
}
}else if(res == MAX_SCORE) {
res += rollScore[frame*2];
}
return res;
}
/*
* 获取比赛总分
*/
public int getTotalScore() {
int totalScore = 0;
for(int i=1;i<=currentRoll/2;i++) {
if(i <= this.num/2) {
totalScore += getFrameScore(i);
}
}
return totalScore;
}
}