SOLVED: Password.Anagram issues

Hi guys,

Whenever I add the ‘Passwords.Anagram()’ method to my code, I keep getting an ‘Object not set to an instance of an object’ error.

I was wondering if anyone else had the same issues? I read that someone else had the issue when they were missing their Utility.cs file, but I have mine there in the Assets folder.

using UnityEngine;

public class Hacker : MonoBehaviour {

    //Game configuration data
    string[] level1Passwords = { "password1", "password2", "password3", "password4", "password5", "password6" };
    string[] level2Passwords = { "password 7", "password8", "password9", "password10", "password11", "password12" };
    
    //Game state (where we put all of our member/global variables). an enum is a variable type that we create ourselves (like int/float etc but one we make up), and give it a list of possible states
    int level;
    enum Screen { MainMenu, Password, Win };
    Screen currentScreen;
    string password;

	// Use this for initialization
	void Start () {
        ShowMainMenu("Good morning Sophie,");
    }
	

    void OnUserInput(string input)
    {
        if (input == "menu")
        {
            ShowMainMenu("Good morning Sophie");
        }

        else if (currentScreen == Screen.MainMenu)
        {
            RunMainMenu(input);
        }

        else if (currentScreen == Screen.Password)
        {
            CheckPassword(input);
        }
    }



    

//have declared functions down here



    void ShowMainMenu(string greeting)
    {
        currentScreen = Screen.MainMenu;
        Terminal.ClearScreen();
        Terminal.WriteLine(greeting);
        Terminal.WriteLine("Please select from the below:");
        Terminal.WriteLine("Press 1 for Library");
        Terminal.WriteLine("Press 2 for Law");
        Terminal.WriteLine("Press 3 for IT");
        Terminal.WriteLine("Enter your selection:");
    }


    void RunMainMenu(string input)
    {
        //check if the level number is valid, and if it is, convert it to integer
        bool isValidLevelNumber = (input == "1" || input == "2");
        if (isValidLevelNumber)
        {
            level = int.Parse(input);
            StartGame(); 
        }


        else
        {
            Terminal.WriteLine("Invalid choice. Please try again");
        }
    }

    void StartGame()
    {
        currentScreen = Screen.Password;
        Terminal.ClearScreen();
        Terminal.WriteLine("You have chosen level " + level);
        RunGame();

        //use switch if we're comparing two values, rather than if (although if/else does the same). in the case that level = 1, do this..etc. default is the else clause
        switch (level)
        {
            case 1:
                //select random number between 0 and the number of items in the level1Passwords array. don't have to store in a separate variable
                password = level1Passwords[Random.Range(0, level1Passwords.Length)];
                break;

            case 2:
                password = level2Passwords[Random.Range(0, level2Passwords.Length)];
                break;

            default:
                Debug.LogError("Invalid level choice");
                break;
        }
    } 

    void RunGame()
    {
        
        currentScreen = Screen.Password;
        Terminal.WriteLine("Enter password: hint " + password.Anagram());
    }

    void CheckPassword(string input)
    {
        if (input == password)
        {
            DisplayWinScreen();
        }

        else
        {
            Terminal.WriteLine("Password incorrect. Please try again: ");
        }


    }

    void DisplayWinScreen()
    {
        currentScreen = Screen.Win;
        Terminal.WriteLine("You guessed correctly!");
        ShowLevelReward();
    }

    void ShowLevelReward()
    {
        switch (level)
        {
            case 1:
                Terminal.WriteLine("Here's a book. Yay!");
                Terminal.WriteLine(@"
      _____________
     /                     / /
    /   story          / /
   /                    / /
  /__________/ /
 (__________( / 
                                 ");
                break;
            case 2:
                Terminal.WriteLine("Uh oh. You're going to jail!");
                Terminal.WriteLine(@"
  ______          ______
//            \\      //            \\
||       ||88888||              ||
\\______ //     \\______//

                                  ");
                break;
            default:
                Terminal.WriteLine("Invalid choice");
                break;

        }

    }

    void Update()
    {

    }
}

When I run the above, I get the attached screenshot. I lose my ‘enter your password’ text and get the object not set to an instance of an object error.

When I remove the passwords.Anagram() method, I get my ‘enter your password’ text back!

Now I’m hoping I’m being really stupid and missing something obvious; can anyone advise at all?

Thanks for your time,

Sophie

PS, I should mention that I’ve tried reimporting the .Unity file to no avail.

1 Like

Hi Sophie,

Can you provide the full details of the error message, this will include the line number.

Hi, thanks for your response. Here’s what displays in the Unity console:

NullReferenceException: Object reference not set to an instance of an object
StringExtension.Shuffle (System.String str) (at Assets/Utility.cs:16)
StringExtension.Anagram (System.String str) (at Assets/Utility.cs:5)
Hacker.RunGame () (at Assets/WM2000/Hacker.cs:106)
Hacker.StartGame () (at Assets/WM2000/Hacker.cs:82)
Hacker.RunMainMenu (System.String input) (at Assets/WM2000/Hacker.cs:67)
Hacker.OnUserInput (System.String input) (at Assets/WM2000/Hacker.cs:30)
System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Reflection/MonoMethod.cs:222)
Rethrow as TargetInvocationException: Exception has been thrown by the target of an invocation.
System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Reflection/MonoMethod.cs:232)
System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Reflection/MethodBase.cs:115)
Terminal.NotifyCommandHandlers (System.String input) (at Assets/WM2000/Terminal/Terminal.cs:50)
InputBuffer.SendCommand (System.String command) (at Assets/WM2000/Terminal/InputBuffer.cs:52)
InputBuffer.UpdateCurrentInputLine (Char c) (at Assets/WM2000/Terminal/InputBuffer.cs:30)
InputBuffer.ReceiveFrameInput (System.String input) (at Assets/WM2000/Terminal/InputBuffer.cs:12)
Terminal.ReceiveFrameInput (System.String input) (at Assets/WM2000/Terminal/Terminal.cs:26)
Keyboard.Update () (at Assets/WM2000/Keyboard/Keyboard.cs:37)

Hope this helps - it doesn’t really mean anything to me!

Sophie

1 Like

Hi Sophie,

Thank you. It would seem that your password is null, e.g. hasn’t been set, so when you then try to call the Anagram method, it’s failing because it has nothing to work with.

Could you zip your project files for me and share them so I can take a quick look?

The forum will allow uploads of up to 10MB, if your project files (zipped) are larger than that you would need to use a service such as Google Drive or Dropbox, and then share the URL.

Hi Rob,

Thanks again for your response, apologies for the delay. See attached (with library folder removed to save space) 2_TerminalHacker.zip (5.6 MB)

I look forward to your feedback.

Sophie

Hi Sophie,

I don’t think the copy of your project you’ve given me includes the line of code you were using which was causing your error, however, I think I have pieced together your problem.

Within Hacker.cs you have a method called RunGame, your error message output above indicates and issue with line 106, which I believe would have been this;

Terminal.WriteLine("Enter password: hint ");

I suspect at some point you had the password.Anagram() in that statement also, but took it back out before zipping the project files.

Assuming so, the problem is because you are calling RunGame from the StartGame method before you have executed the code within the switch statements. This is where the password actually gets set.

{
    currentScreen = Screen.Password;
    Terminal.ClearScreen();
    Terminal.WriteLine("You have chosen level " + level);
    RunGame();  // <--- this is the problem

    //use switch if we're comparing two values, rather than if (although if/else does the same). in the case that level = 1, do this..etc. default is the else clause
    switch (level)
    {
        case 1:
            //select random number between 0 and the number of items in the level1Passwords array. don't have to store in a separate variable
            password = level1Passwords[Random.Range(0, level1Passwords.Length)];
            break;

        case 2:
            password = level2Passwords[Random.Range(0, level2Passwords.Length)];
            break;

        default:
            Debug.LogError("Invalid level choice");
            break;
    }
}

Consider calling the RunGame method after the rest of the code in that method, e.g. after the switch statements;

{
    currentScreen = Screen.Password;
    Terminal.ClearScreen();
    Terminal.WriteLine("You have chosen level " + level);

    //use switch if we're comparing two values, rather than if (although if/else does the same). in the case that level = 1, do this..etc. default is the else clause
    switch (level)
    {
        case 1:
            //select random number between 0 and the number of items in the level1Passwords array. don't have to store in a separate variable
            password = level1Passwords[Random.Range(0, level1Passwords.Length)];
            break;

        case 2:
            password = level2Passwords[Random.Range(0, level2Passwords.Length)];
            break;

        default:
            Debug.LogError("Invalid level choice");
            break;
    }

    RunGame();
}

By doing so, the password will be set and you shouldn’t see the error you were receiving before.

Hope this helps :slight_smile:

Thank you for this - I got it working!

I used what you said above to help tidy up my code and as a result got it working - see below:

using UnityEngine;

public class Hacker : MonoBehaviour {

    //Game configuration data (const never changes, i.e. constant)
    const string menuHint = "You may type menu at any time";
    string[] level1Passwords = { "password1", "password2", "password3", "password4", "password5", "password6" };
    string[] level2Passwords = { "password7", "password8", "password9", "password10", "password11", "password12" };
    string[] level3Passwords = { "password 13", "password14", "password15", "password16", "password17" };
    
    //Game state (where we put all of our member/global variables). an enum is a variable type that we create ourselves (like int/float etc but one we make up), and give it a list of possible states
    int level;
    enum Screen { MainMenu, Password, Win };
    Screen currentScreen;
    string password;

	// Use this for initialization
	void Start () {
        ShowMainMenu("Good morning Sophie,");
    }
	

    void OnUserInput(string input)
    {
        if (input == "menu")
        {
            ShowMainMenu("Good morning Sophie");
        }

        else if (currentScreen == Screen.MainMenu)
        {
            RunMainMenu(input);
        }

        else if (currentScreen == Screen.Password)
        {
            CheckPassword(input);
        }
    }



    

//have declared functions down here



    void ShowMainMenu(string greeting)
    {
        currentScreen = Screen.MainMenu;
        Terminal.ClearScreen();
        Terminal.WriteLine(greeting);
        Terminal.WriteLine("Please select from the below:");
        Terminal.WriteLine("Press 1 for Library");
        Terminal.WriteLine("Press 2 for Law");
        Terminal.WriteLine("Press 3 for IT");
        Terminal.WriteLine("Enter your selection:");
    }


    void RunMainMenu(string input)
    {
        //check if the level number is valid, and if it is, convert it to integer
        bool isValidLevelNumber = (input == "1" || input == "2" || input == "3");
        if (isValidLevelNumber)
        {
            level = int.Parse(input);
            Terminal.ClearScreen();
            Terminal.WriteLine("You have chosen level " + level);
            StartGame();
        }


        else
        {
            Terminal.WriteLine("Invalid choice. Please try again");
            Terminal.WriteLine(menuHint);
        }
    }


   void SetRandomPassword()
    {
        //use switch if we're comparing two values, rather than if (although if/else does the same). in the case that level = 1, do this..etc. default is the else clause
        switch (level)
        {
            case 1:
                //select random number between 0 and the number of items in the level1Passwords array. don't have to store in a separate variable. min inclusive max exclusive (so 1-6 gives 12345)
                password = level1Passwords[Random.Range(0, level1Passwords.Length)];
                break;

            case 2:
                password = level2Passwords[Random.Range(0, level2Passwords.Length)];
                break;

            case 3:
                password = level3Passwords[Random.Range(0, level3Passwords.Length)];
                break;

            default:
                Debug.LogError("Invalid level choice");
                break;
        }

        
    }

    void StartGame()
    {
        currentScreen = Screen.Password;
        SetRandomPassword();
        AskforPassword();

    }


    void AskforPassword()
    {
        
        currentScreen = Screen.Password;
        Terminal.WriteLine("Enter password: hint " + password.Anagram());
    }

    void CheckPassword(string input)
    {
        if (input == password)
        {
            DisplayWinScreen();
        }

        else
        {
            Terminal.WriteLine("Password incorrect. Please try again: ");
            Terminal.WriteLine(menuHint);
            StartGame();
        }


    }

    void DisplayWinScreen()
    {
        currentScreen = Screen.Win;
        Terminal.ClearScreen();
        Terminal.WriteLine("You guessed correctly!");
        ShowLevelReward();
        Terminal.WriteLine(menuHint);
    }

    void ShowLevelReward()
    {
        switch (level)
        {
            case 1:
                Terminal.WriteLine("Here's a book. Yay!");
                Terminal.WriteLine(@"
      _____________
     /          / /
    /   story  / /
   /          / /
  /__________/ /
 (__________( / 
                                 ");
                break;
            case 2:
                Terminal.WriteLine("Uh oh. You're going to jail!");
                Terminal.WriteLine(@"
  ______          ______
//      \\      //      \\
||       ||88888||      ||
\\______ //     \\______//

                                  ");
                break;
            case 3:
                Terminal.WriteLine("Elite hax0r!");
                Terminal.WriteLine(@"
  __________________
 |                 |
 |     SYSTEM      |
 |     ACCESS!     |
 |_________________|
  _____|     |______
 |__________________|

                                    ");
                break;


            default:
                Terminal.WriteLine("Invalid choice");
                break;

        }

    }

    void Update()
    {

    }
}

Thanks again for your help :grin:

1 Like

You’re very welcome, I’m glad you can move forward with the course again :slight_smile:

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms