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.
itemFound
items are inside rooms with a matching
fixWith
.
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.
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.
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.
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.
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.
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.