The Room Adventure: Additional Features

Make sure items are not found in the rooms they're needed in

Difficulty: ★★☆☆☆

Requirement: randomizeItems function

When randomizing items, it's possible for the computer to put fixWith items inside the room that needs it for its brokenThing. This isn't much fun, and it happens more often the fewer rooms you have.

Let's make some tweaks to the randomizeItems function to keep this from happening.

We're going to use a brute force method to fix this problem. The computer's going to keep shuffling the items over and over until everything is scattered properly. Unless you have thousands of rooms, or few rooms with lots of repeat items, this should work just fine.

What we need to do

  • Create a loop for the computer to check if any itemFound items are inside rooms with a matching fixWith.
  • If so, that's no good.
  • Repeat the loop and randomize the locations again if needed.

Step 1: Go inside the randomizeItems functions

All of our work will be inside the randomizeItems function, so go there.

We have two for...in loops, one that makes a list of items and then one that shuffles them. Find the space between these loops.

Note: If you added the feature that allows you to keep certain items from being shuffled, then you already have another loop where I'm telling you to look. The new code you're adding here would go below that.

Step 2: Initializing the variables

We need to create two variables in order for this to work. We're declaring them outside the loop so they're recreated over and over.

These go in the spot noted in the code above.

Step 3: Begin the loop

We don't know how many times the shuffling will have to happen, so a while loop makes the most sense here. However, we want to make sure the items get shuffled at least once. For this, we're using a variation, the do...while loop.

We're going to be wrapping our randomizing part of the function in the loop.

Right under the variable declarations you just created, add these lines.

First, we need to make a copy of the items array. We may need to be changing it over and over, so we have to keep the original copy intact. Because we have the items array referred to several times in the loop below, we're making things easier on ourselves. We're making a copy of the original items array and we'll restore it every time so we don't have to update all the items uses to itemsCopy.

We will also need a flag variable for our loop. We're going to first assume that everything is shuffled perfectly. But during the loop, we're going to check to see if there's a problem, and if so, then we're going to change that flag so it randomizes everything again.

We use items.slice() to make a shallow copy of an array. We only have strings in there so it's no problem. If we had objects inside, we'd have to do this differently. The slice method does not change the original array, so items stays just the way it is.

This isn't the only use of slice, just a convenient one. For more info on slice, check out the JavaScript tutorial.

As for our stillShuffling flag, it says, "Nope, we are not still shuffling, so move on!" But... when we're checking items, if we find that something is where it doesn't belong, then this will change and say, "Oh, yeah, we have to shuffle again!" Ok, ok, it doesn't literally say those things, but that's how it works.

We are resetting these two variables each time the loop runs, so it's a fresh start.

Step 4: See if the itemFound matches the fixWith for the room.

When an item is randomly picked for a room, if it's the item needed for that room, then let's reshuffle everything.

Why don't we just pick another item randomly instead of reshuffling everything? As items get placed, there are fewer to choose from. What if the last item to pick belongs to the last room that needs an item? We'd end in an infinite loop scenario. Shuffling from the beginning will help prevent this.

This part goes inside the for loop that's already there, right after the random index is chosen. Look for this line and then add the others.

Can you make sense of the if statement? It's a little heavy, isn't it? First we're finding the item we're looking at from items[index]. Each time through the loop, a new room is picked, so the item is compared to that room's fixWith item. If they match, then we have a problem. We'd be putting batteries, let's say, in the room that needs the batteries. If this happens, we flip our stillShuffling switch to tell the computer we need to shuffle again.

We're using the break command to exit the for loop because there's no need to set all the other items if we have one that's already messed up.

Want to test it?

By the way, if you want to see if it's working, you can have the computer report to the console (or a popup) to let you know. To do this, just add a line like this right before the break statement.

If you use the console, you'll need to open developer tools when you run the program. (Try pressing F12.) It may shuffle perfectly on the first try, so you might not see your warning until you run it a couple times.

Step 5: Closing the loop

All that's left is to close the do...while loop. Go down to the very bottom of the function, right before the very last brace. You may have three braces in a row down there, so this goes between the last two.

Now you won't find what you need inside the room you need it in.

Now, where did I leave my keys...?

—Dr. Wolf