Refactored code

Here is my refactored code. I tried to make it as readable/English as possible. Hope it is easy to follow.
Please let me know if it can be improved.

One area of improvement is the design of the code. To add a new level, I would need to go to many places in the code and add adjustments. Without classes, it is harder to do this. I have also thought about mimicking classes using parallel arrays.

public class Hacker : MonoBehaviour
{
    enum Access
    {
        None = -1,
        Library = 0,
        Bank = 1,
        PoliceStation = 2,
        NASA = 3
    }
    Access access;

    const int PASSWORD_INDEX = 0;
    const int PASSWORD_HINT_INDEX = 1;
    // passwords is a table of Access passwords.  Access passwords are password/hint pairs
    // passwords[0]-->{ {password0, hint0}, ... , {passwordN, hintN} }
    // :
    // passwords[M]-->{ {password0, hint0}, ... , {passwordN, hintN} }
    //string[][,] passwords = new string[System.Enum.GetValues(typeof(Access)).Length - 1][,];
    string[][,] passwords;

    string accessPassword;
    string accessPasswordHint;
    bool accessPasswordHintDisplayed;
    bool accessPasswordAnagramDisplayed;

    readonly string[] artMap = {
// Library art: index 0 = Access.Library
@"
   ______
  /     //
 /     //
(_____(/
"
,
// Bank art: index 1 = Access.Bank
@"
   ____________
   )           )
  /  $$$$$$$  /
 / $$$$$$$$  /
(___________(
"
,
// Police Station art: index 2 = Access.PoliceStation
@"
  ____ 
 /    \_________
|  (O  ==w_w=w_/
 \____/   
"
,
// NASA art: index 3 = Access.NASA
@"
       ^  
     /   \
    /|   |\
     |   |
     |   |
    /| | |\
  /  | | | \
 |   | | |  |
 ------------
"
};

    // Game state
    string terminalInput;

    enum State
    {
        Initialized,
        MainMenu,
        Password,
        Win
    };
    State state;

    enum Event
    {
        Start,
        TerminalInput,
        Menu
    }

    // Start is called before the first frame update
    void Start()
    {
        InitializePasswordTable();

        RestartGame();
    }

    private void PickPasswordFromTable()
    {
        // Because passwords[x] is an array of 2 dimensional arrays,
        // the number of entries/pairs for passwords[x] is actually passwords[x].Length / 2
        int maxIndex = passwords[(int) access].Length / 2;
        int passwordChoice = Random.Range(0, maxIndex);
        accessPassword = passwords[(int) access][passwordChoice, PASSWORD_INDEX];
        accessPasswordHint = passwords[(int) access][passwordChoice, PASSWORD_HINT_INDEX];
    }

    private void InitializePasswordTable()
    {
        passwords = new string[System.Enum.GetValues(typeof(Access)).Length - 1][,];

        passwords[(int) Access.Library] = new string[,] { 
            { "dog", "Has a wet nose"}
            , { "cat", "Chases mice"} 
            , { "bat", "Has a partner, Robin" } 
        };
        passwords[(int) Access.Bank] = new string[,] { 
            { "planes", "Wright brothers made these." }
            , { "trains", "Amtrack has these" }
            , { "automobiles", "Henry Ford made these" } 
        };
        passwords[(int) Access.PoliceStation] = new string[,] { 
            { "detective", "Sherlock Holmes" }
            , { "assault", "? and battery" }
            , { "misdemeanor", "A trifle offense" } 
        };
        passwords[(int) Access.NASA] = new string[,] { 
            { "mercury", "thermometers" }
            , { "venus", "Bananarama" }
            , { "jupiter", "Roman God" } 
        };
    }

    void OnUserInput(string input)
    {
        Event ev;
        if (input == "menu")
        {
            ev = Event.Menu;
        }
        else
        {
            ev = Event.TerminalInput;
            terminalInput = input;
        }

        RunGame(ev);
    }

    void RunGame(Event ev)
    {
 
        switch (state)
        {
            case State.Initialized:
                if (ev != Event.Start)
                {
                    // Unexpected event
                    // Report the error
                    ReportError("Current state: " + state + ".  Received unexpected event: " + ev);
                }
                ShowMainMenu();
                break;
            case State.MainMenu:
                if (ev == Event.Start)
                {
                    // Unexpected event
                    // Report the error
                    ReportError("Current state: " + state + ".  Received unexpected event: " + ev);
                }
                else if (ev == Event.TerminalInput)
                {
                    if (isValidMenuItem(this.terminalInput))
                    {
                        PickPasswordFromTable();
                        GetPassword();
                    }
                    else
                    {
                        // Prompt the user again
                        // Stay in the same state: State.MainMenu
                        InvalidMenuInput();
                    }
                }
                else if (ev == Event.Menu)
                {
                    RestartGame();
                }
                else
                {
                    // Unexpected event
                    // Report the error
                    ReportError("Current state: " + state + ".  Received unexpected event: " + ev);
                }
                break;
            case State.Password:
                if (ev == Event.Start)
                {
                    // Unexpected event
                    // Report the error
                    ReportError("Current state: " + state + ".  Received unexpected event: " + ev);
                }
                else if (ev == Event.TerminalInput)
                {
                    // validate the password that was entered
                    if (isValidPassword(this.terminalInput))
                    {
                        Win();
                    }
                    else
                    {
                        InvalidPassword();
                        GetPassword();
                    }
                }
                else if (ev == Event.Menu)
                {
                    RestartGame();
                }
                else
                {
                    // Unexpected event
                    // Report the error
                    ReportError("Current state: " + state + ".  Received unexpected event: " + ev);
                }
                break;
            case State.Win:
                if (ev == Event.Start)
                {
                    // Unexpected event
                    // Report the error
                    ReportError("Current state: " + state + ".  Received unexpected event: " + ev);
                }
                else if (ev == Event.TerminalInput || ev == Event.Menu)
                {
                    RestartGame();
                }
                else
                {
                    // Unexpected event
                    // Report the error
                    ReportError("Current state: " + state + ".  Received unexpected event: " + ev);
                }
                break;
            default:
                // Unexpected state
                // Report the error
                ReportError("Current state: " + state + ".  Received unexpected event: " + ev);
                break;
        }
    }

    private void RestartGame()
    {
        // Initialize game state
        ResetGame();
        // Start the game
        RunGame(Event.Start);
    }

    void ShowMainMenu()
    {
        state = State.MainMenu;
        Terminal.ClearScreen();
        Terminal.WriteLine("Welcome, Hacker.");
        Terminal.WriteLine("Which system would you like to access?");
        Terminal.WriteLine("");
        Terminal.WriteLine("1 ) Library");
        Terminal.WriteLine("2 ) Bank");
        Terminal.WriteLine("3 ) Police Station");
        Terminal.WriteLine("4 ) NASA");
        Terminal.WriteLine("");
        Terminal.WriteLine("Enter 'menu' any time to return to main menu.");
        PromptChoices();
    }

    private void PromptChoices()
    {
        Terminal.WriteLine("Enter selection [1, 2, 3, 4, or menu]:");
    }

    private void GetPassword()
    {
        state = State.Password;
        Terminal.WriteLine("Enter password:");
    }

    private void Win()
    {
        state = State.Win;
        Terminal.ClearScreen();

        // Get the art to display
        string art = GetArt();
        // Display the art
        Terminal.WriteLine("Successfully entered!");
        Terminal.WriteLine(art);
        Terminal.WriteLine("Press enter to access a different area");
    }

    private string GetArt()
    {
        string art = artMap[(int) access];
        return art;
    }

    private void InvalidMenuInput()
    {
        Terminal.WriteLine("Invalid menu option.  Try again.");
        PromptChoices();
    }

    private void InvalidPassword()
    {
        Terminal.WriteLine("Invalid password.  Please try again.");
        if (!accessPasswordHintDisplayed)
        {
            Terminal.WriteLine("Hint: " + accessPasswordHint);
            accessPasswordHintDisplayed = true;
        }
        else if (!accessPasswordAnagramDisplayed)
        {
            Terminal.WriteLine("Hint: " + accessPassword.Anagram());
            accessPasswordAnagramDisplayed = true;
        }
    }

    private bool isValidPassword(string password)
    {
        return accessPassword == password;
    }

    private bool isValidMenuItem(string input)
    {
        bool isValid = true;

        switch (input)
        {
            case "1":
                access = Access.Library;
                break;
            case "2":
                access = Access.Bank;
                break;
            case "3":
                access = Access.PoliceStation;
                break;
            case "4":
                access = Access.NASA;
                break;
            default:
                isValid = false;
                break;
        }

        return isValid;
    }

    void ResetGame()
    {
        Terminal.ClearScreen();
        access = Access.None;
        state = State.Initialized;
        accessPassword = null;
        accessPasswordHint = null;
        accessPasswordHintDisplayed = false;
        accessPasswordAnagramDisplayed = false;
    }
    private void ReportError(string error)
    {
        Debug.LogError(error);
    }

}

Privacy & Terms