I found this exercise easier to solve using a switch statement rather than if else. Here is my code for ActionMaster.cs (refactored) it seems to pass all the tests:
Would there be any downside to using this technique instead?
using UnityEngine;
using System.Linq;
public class ActionMaster
{
public enum Action { Tidy, Reset, EndTurn, EndGame };
private int[] _bowlScores = Enumerable.Repeat(0, 21).ToArray(); // 21 elements initilised to 0
private int _currentBowl = 1;
public Action Bowl (int pins)
{
// Guard
if (pins < 0 || pins > 10) throw new UnityException("Can not accept more than 10 or less than 0 pins in ActionMaster.Bowl()");
// Record pins down for current bowl
_bowlScores[_currentBowl - 1] = pins;
// Last frame special cases
//
// [19] [20] [21]
// 0 - tidy 0 - end
// 5 - tidy 1 - end
// 5 - tidy 5 - reset x
// 10 - reset 0 - tidy x
// 10 - reset 5 - tidy x
// 10 - reset 10 - reset x
switch(_currentBowl)
{
case 19:
_currentBowl++;
if (pins != 10) return Action.Tidy;
else return Action.Reset;
case 20:
_currentBowl++;
var previousScore = _bowlScores[19 - 1];
if (previousScore != 10 && previousScore + pins != 10) return Action.EndGame;
if (previousScore != 10 && previousScore + pins == 10) return Action.Reset;
if (previousScore == 10 && pins != 10) return Action.Tidy;
else return Action.Reset;
case 21:
return Action.EndGame;
}
// Otherwise if you bowl a stike you end the turn and increment the current bowl by 2
if (pins == 10)
{
_currentBowl += 2;
return Action.EndTurn;
}
// All other cases need the current bowl incremented by 1 after the conditional test
// Tidy if odd number tidy, other wise end turn
if (_currentBowl++ % 2 != 0) return Action.Tidy;
else return Action.EndTurn;
// Failed to resolve
throw new UnityException("No Action.type returned from ActionMaster.Bowl()");
}
}