Hi. Here’s my version of the Bowl function.
public Action Bowl(int pins) {
if (pins < 0 || pins > 10) {
throw new UnityException("Invalid number of pins: " + pins);
}
bowls[bowl - 1] = pins;
if (bowl == 21) {
return Action.EndGame;
}
// Handle last-frame
if (bowl == 19 && pins == 10) {
bowl++;
return Action.Reset;
} else if (bowl == 20) {
bowl++;
if (Bowl21Awarded()) { // if there was a strike on 19 ball or spare on 20 - bonus ball is awarded
return Bowl20PinsLeft() // if any pins left standing after ball 20
? Action.Tidy
: Action.Reset;
} else { // no bonus, ball 20 is the second ball in 10th frame and last ball in the game
return Action.EndGame;
}
}
if (pins == 10) {
bowl += 2;
return Action.EndTurn;
}
if (bowl % 2 != 0) { // mid frame (or last frame)
bowl++;
return Action.Tidy;
} else { // end of frame
bowl++;
return Action.EndTurn;
}
throw new UnityException("WTF to do?");
}
// A Strike or a Spare on the 10th frame.
private bool Bowl21Awarded() {
return (bowls[19 - 1] + bowls[20 - 1] >= 10);
}
// A Strike on the 10th frame but no Strike on second ball.
private bool Bowl20PinsLeft() {
return (bowls[19 - 1] == 10 && bowls[20 - 1] < 10);
}
I think it’s a little bit cleaner - there are less code and condition to choose between Tidy and Reset on 20th ball is more logical. If you have pins left after 2 balls, THEN you need to tidy (that’s what tidy is for, to prepare for follow-up ball).
Also I think you don’t need bowls array because only last 2 elements are actually used…