I'm stuck at section 2 - Anagram


#1

my messed up file

Nearly at the end of section 2, when I try to add the anagram statement into my script, it wont work and even though I can enter password screen when hit 1, but then no password appear and when I hit anything again, the same enter level msg reappear. Then I carefully read the whole script again and tried to find out which step gone wrong, I couldn’t…

Before I added the anagram statement into the script, everything works fine and I can enter password, go to win screen and loop with no trouble. So I really dunno what missing to have this problem occured >_<


#2

Hi Tommy,

When I run your game, after making a selection from the main menu an error message is thrown.

NullReferenceException: Object reference not set to an instance of an object
StringExtension.Shuffle (System.String str) (at Assets/Scenes/WM2000/Utility.cs:16)
StringExtension.Anagram (System.String str) (at Assets/Scenes/WM2000/Utility.cs:5)
Hacker.askforpassword () (at Assets/Scenes/Hacker.cs:118)
Hacker.RunGameMenu (System.String input) (at Assets/Scenes/Hacker.cs:77)
Hacker.basicinput (System.String input) (at Assets/Scenes/Hacker.cs:59)
Hacker.OnUserInput (System.String input) (at Assets/Scenes/Hacker.cs:47)

These can often seem a little daunting but if we follow this from the bottom upwards we can see the first file that is mentioned is your Hacker.cs script, and that the issue relates to line 47. Let’s start there…

Line 47 is this;

basicinput(input);

so we follow that method call which takes us to line 51, determines which screen you are on, this condition is true;

else if (currentScreen == Screen.MainMenu)

So this statement executes, note this is line 59 which was the next line up in the error detail above;

RunGameMenu(input);

Now let’s look at that method, this one is handling what you have selected as an option, I chose “1” on my attempt which threw the error, so that takes us to line 77, the third line up in the error message above, and this statement;

askforpassword();

If we now look at that method we can see that this line is 118, which is the fourth line up from the bottom in the error detail above;

Terminal.WriteLine("password hint:" + password.Anagram());

As you are getting a NullReferenceException error an object in this statement must be null. The error is thrown when you try to access a member of that object, in this specific case you are trying to access the Anagram method of the password object, and password is null.

We can both test and prove this by adding this line to the beginning of the asforpassword method;

Debug.Log(password);

When you run the game and make the same choice (option 1) now, you’ll see the word “null” output to the console. So the issue here is that a password has not been selected.

If we look at what else your code in the askforpassword method does we can see that you do in fact attempt to set the password, but after you have tried to use it, so, to resolve this issue, move these line;

Terminal.WriteLine("password hint:" + password.Anagram());

to be after the switch statement, e.g.

void askforpassword()
{
	currentScreen = Screen.Password;
	Terminal.WriteLine("you are entering level " + level);

	switch (level)
	{
		case 1:
			password = level1passwords[Random.Range(1, level1passwords.Length)];
			break;

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

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

		default:
			Debug.LogError("invalid level no.");
			break;

	}

	Terminal.WriteLine("password hint:" + password.Anagram());
}

With the above, you now determine what the password should be, based upon the level selection, you initialise the password object, and then afterwards, you access it’s method, Anagram.

Run the game now and you’ll find the NullReferenceException error is not thrown and your password is displayed.

A couple of other minor points, it would be best to follow a standard naming convention in your code, typically class names, properties and methods would use PascalCase and variables would use camelCase. This can make it a lot easier to tell, by glancing at the code, what’s what. As an example, your method askforpassword would be AskForPassword, basicinput would be BasicInput, at the moment you have quite a mix of different conventions going on and this will only make it more challenging for yourself and anyone else who looks at your code. It would be worth spending a few minutes to clear up these now before it becomes a habit.

In the AskForPassword method, I’d probably move both lines which display a message to the user to be together also, whilst I suggest above about only moving the one, that was merely to remove the error, it would make more sense that the statements which display output to the user are together, that would look like this;

void AskForPassword()
{
	currentScreen = Screen.Password;

	switch (level)
	{
		case 1:
			password = level1passwords[Random.Range(1, level1passwords.Length)];
			break;

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

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

		default:
			Debug.LogError("invalid level no.");
			break;
	}

	Terminal.WriteLine("you are entering level " + level);
	Terminal.WriteLine("password hint:" + password.Anagram());
}

Hope this helps :slight_smile:


See also;


#5

oh, i want to ask something. Does the order of the code within the bracket determines when the computer reads it? so if I put a line of statement behind another statement within a bracket, it will be read by the computer and be executed earlier?

You mean i did in fact attempt to set the password but after i have tried to use it, is it about the order of the code?

btw thankyou for your help!! you really helped me into knowing the concept better!


#6

Your statements are typically read sequentially, so for example;

private void Example()
{
    Debug.Log("First statement executed");
    Debug.Log("Second statement executed");
    Debug.Log("Third statement executed");
}

If the above method was called, you would expect to see this in the console;

First statement executed
Second statement executed
Third statement executed

Each statement was executed in order, each statement was executed before moving to the next.

The first statement would be executed first, again, to give you an example;

private void Example()
{
    Debug.Log("Starting my work - sigh");

    for(i = 0; i < 3; i++)
    {
        Debug.Log("Working on item number " + i);
    }

    Debug.Log("Finished my work - home time!");
}

The above would output the following to the console;

Starting my work - sigh
Working on item number 1
Working on item number 2
Working on item number 3
Finished my work - home time!

As you can see, each iteration of the for loop executed before the final Debug.Log statement.

That’s correct, so where you tried to use it (before initialising it) it was null, then you initialised it afterwards, but that code didn’t get to execute because the error was thrown on the line where you tried to call the Anagram method, so all of the code execution stopped at that point.

You’re very welcome. Let me know if the above makes sense :slight_smile:


closed #7