Another approach to Action Master, break it with a test!

For the previous video’s challenge, when I did most of the testing cases, the code was starting to become enormous, so I ended up refactoring the whole thing, and it became a completely different approach from that of Ben’s code.

Here’s the code, what do you think?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ActionMaster   // We don't need to inherit functions from Monobehaviour here
{
    public enum Action {Tidy, Reset, EndTurn, EndGame};
    
    private int frame = 1;  // To count the frames from 1-10
    private int bowl = 1;   // For each bowl inside frames
    private int pinHitsInFrame = 0;  // For adding up last frame 1st and 2nd bawl

    public Action Bowl(int pins)
    {
        if      (pins < 0 || pins > 10) { throw new UnityException("Invalid pin count!"); }
        else if (frame < 10)            { return HandleFrameOneToNine(pins); }
        else if (frame == 10)           { return HandleLastFrame(pins); }
        throw new UnityException("Not sure what action to return!");
    }
    private Action HandleFrameOneToNine(int pins)
    {
        // First bowl will only return EndTurn, if it's a strike.
        // Second bowl will always return EndTurn.
        if (bowl == 1 && pins < 10)
        {
            bowl++;
            return Action.Tidy;
        }
        frame++;
        bowl = 1;
        return Action.EndTurn;
    }
    
    private Action HandleLastFrame (int pins)
    {
        // We only Reset if 1st bawl is a strike.
        // We also have to store the pins we hit in the 1st bawl.
        if (bowl == 1)
        {
            if (pins < 10)
            {
                pinHitsInFrame = pins;
                bowl++;
                return Action.Tidy;
            }
            pinHitsInFrame = pins;
            bowl++;
            return Action.Reset;
        } else if (bowl == 2) {
            // If the sum of the 1st and 2nd bawl is less than 10,
            // then it's an EndGame.
            if (pinHitsInFrame + pins < 10) { return Action.EndGame; }
            // If it's a gutter ball or the sum of the 1st and 2nd 
            // bawl is in between 10 and 20, we Tidy. 
            // With the second condition, the 1st bawl is always a strike.
            // Otherwise it can only be a spare, so we Reset.
            else if (pins == 0 || (pinHitsInFrame + pins > 10 && pinHitsInFrame + pins < 20))
            {
                bowl++;
                return Action.Tidy;
            }
            bowl++;
            return Action.Reset;
        }
        // Third bawl will always return EndGame.
        return Action.EndGame;
    }
}

Privacy & Terms