Advertisement
  1. Code
  2. ActionScript
Code

AS3 101: Arrays - Basix

by
Difficulty:IntermediateLanguages:
This post is part of a series called AS3 101.
AS3 101: Branching - Basix
AS3 101: Loops - Basix

In this installment of AS3 101, we'll spend the entire tutorial exploring a single type of data available to most programming languages: the Array.

Arrays are ways to keep lists of values. Arrays are useful to keep an arbitrary number of related items grouped together, and can represent complex data structures though nesting. In ActionScript, Arrays have quite a bit of flexibility and functionality, as we'll see. After the usual abstract introduction, we'll apply what we've learned (whilst also learning some more along the way) by building a rather simple puzzle game.

Step 1: So What's an Array?

It's a bit hackneyed to start things out with a "the New Oxford American Dictionary defines Array as..." but I'm going to do it anyway.

As you can see, the general gist is that an array is a collection of things, usually the same types of things: the array of literature, the array of troops, the array of jurors.

Wikipedia's page on arrays in general showcases some interesting uses of the term in all kind of industries. The article specific to computer science discusses some of the conceptual and lower-level ideas that go into an array.

My favorite non-programming use of the word array is the Very Large Array, the set of 27 antennae that form a radio observatory in New Mexico. If you've seen the movie Contact, you know what this is. From the VLA's official website:

The VLA is an interferometer; this means that it operates by multiplying the data from each pair of telescopes together to form interference patterns. The structure of those interference patterns, and how they change with time as the earth rotates, reflect the structure of radio sources on the sky: we can take these patterns and use a mathematical technique called the Fourier transform to make maps.

An interesting fact about the VLA is that the dishes can be moved around into several different configurations, to better focus on different parts of the sky. Each individual antenna is capable of being moved, and situating itself so that it is pointing at a certain location. However, moving and situating a single antenna by itself doesn't have nearly the impact that it would if the antenna were being moved and situated while keeping the other antennae in mind. That is, while each antenna is independent and fully functional on its own, it is the antenna's membership to the group that allows the VLA to be as powerful as it is.

Image courtesy of NRAO/AUI

In computer science, an array is a collection of data, or in other words, a list of values. Put another way, an array is a single variable that holds many values. Well, technically the variable holds a single value: the array itself. Then the array actually holds several values. And as the name implies, the values stored within the array are typically of similar types, although often there is no rule on this. The key point to know, though, is that an array is a group of values, each with their own individual values and identities, but also with a higher, societal identity, as a member of the array.

Step 2: Creating Your Very First Array

Go ahead, print out a certificate, for this is a special moment! If this is your first Array, then welcome to the wonderful world of data management!

There are actually two ways to create Arrays, and both of those ways allow you to create them with elements in them or not. The first way, which one might consider the official way, looks like this:

We're simply creating a variable called ary, of type Array, and setting its value to a new, empty Array. The new keyword in ActionScript is one of which you'll see a lot; as you might infer it creates a free-standing something-or-another, depending on what follows it. In this case, we follow it with the type Array, so we get a new Array.

While this is a perfectly sufficient technique for creating an Array, let's quickly look at other ways to create an Array.

Step 3: Alternate Methods of Creating Arrays

The other main flavor of Array creation is the square bracket, also known as the array literal. In effect, it's just a shortcut to exactly what we did in the last step. It looks like this (if you like, open up a new AS3 Flash document and then open the Actions panel and follow along):

This line of code is functionally identical to the line of code from the last step, only you might see it as shorter and cleaner, or as more cryptic. In all but one case, they are identical to use, so which you use is largely a matter of preference. I recommend trying both out for a while, then settling on a style and remaining consistent.

There aren't any other syntactical variations for creating Arrays, but we do have the option of creating non-empty Arrays. That is, we can create the Array and populate it with values all in the same step. Both the new method and the literal notation support this. To create a new Array with three Strings in it using the new keyword:

To do the same thing using the Array literal:

Note that the number of items doesn't matter, you just need to separate them with commas. And the type doesn't matter, either. We used Strings. You could use Numbers, MovieClips, even other Arrays (we'll get to that in a few steps). They don't need to be the same type, either. The following is perfectly valid:

…although there is little method to that madness. Generally, Arrays are best suited to keeping lists of similar items, not grouping together dissimilar items.

There is one gotcha to be aware of while creating Arrays with data at the same time. I mentioned a little earlier that the new version and the literal version were the same, except for one case. That case is this: If you try to create a new Array with a single item in it, and that item happens to be an integer (whether it's an int or simply a Number that happens to be an integer), you will not get a single-item Array. If you write:

you will get a ten-item Array, with all of the items set to null. However, if you write:

you will get a single-item array, and that one item is the number 10.

It is for this slight discrepancy that I choose the square bracket notation when creating Arrays. It's all too easy to forget that one case where the behavior is different. I have never found a need for creating a multi-item, all null Array, and so I've never intentionally used that feature. Your mileage may vary, but that's how I consider it.

After any of these examples, you can test the value of the Array you created with the following line:

You will see something such as:

which is Flash's best attempt at representing the list of values as textual output. Sometimes it works, like the above, other times it's less useful.

Step 4: The Array Index

To keep track of all of our items in the Array, each item is assigned a numeric index. It's an "id" of sorts that not only uniquely identifies that position (and the value held therein), but it also indicates the position of that item within the list.

But before we go any further, we must make sure it's clear that ActionScript is a zero-based language, meaning that the first item in an Array has an index of 0 (zero). The second item has an index of 1. The last item in the Array will have an index of number-of-items-in-Array minus 1 (think about it...that'll make sense if it didn't at first).

It's a common mistake to think of Arrays as one-based, especially when beginning your programming career, which leads to something called an off-by-one error. This kind of logical error can be difficult to track down, but when you start seeing things like one-too-many or one-too-few results, check to make sure you started at 0.

Step 5: Adding Items to an Array

Keeping in mind that Arrays identify their members by a numeric, zero-based index, let's look at the most straightforward way to get items into an Array after it has been created:

After creating an Array with three String in it, the second line takes that Array adds another String into the fourth position (that is, the position with an index of 3). Using square brackets immediately after a reference to an Array lets us access an individual position within the Array, as determined by the numeric value between the square brackets. This is called array access notation.

Let's see what that did to the Array:

Run the program, and you should see this in the Output panel:

You can now see that your Array has four items in it.

The preceding method is easiest to grasp, and perfect if you know exactly where you want the item to go. Sometimes, however, you don't know or don't care, and just want to put a value into the Array at the end. The push method becomes invaluable in these times:

This takes the value between the parentheses and tacks it on the list at the end. The nice thing is you don't have to worry about how long the Array is at that moment. You just use push and trust it ended up and the end.

trace out ary again and you'll see it has five elements now.

push has a little extra horsepower that most people don't seem to know about, though. You can use it to add multiple items at once. For example:

It may not be readily apparent in the Output panel, but you've added three individual items to the list, growing its length from 6 to 9. You can add as many items as you like in the push method.

unshift is push's little brother. It works identically, save for the small fact that it adds items to the beginning of the list, rather than the end. Note that if you do this:

We have not replaced any items in the Array, we've just added one. The previous item that was at index 0 is slid down to index 1, bumping each one down, until we reach the end. In other words, we're inserting values rather than overwriting values.

Go ahead and trace the Array again to see this in action.

Step 6: Accessing Items in an Array

Now that we have some data in our Array, we'll probably want to, at some point, get it back out. There is a handful of ways to do this, but we'll focus on just three, which mirror the methods of getting items into the Array we discussed in the last step.

Array access notation can be used to get data out just as easily as getting it in. Assuming we still have the "ary" variable still available to us, and that it has 9 items in it, form "zero" to "eight," The following:

will result in:

You might think of array access notation as being very similar to a single variable, only instead of having 9 variables with these Strings in them, we have a single variable ("ary") that is capable of holding 9 values by itself, and to use any one of them as a variable, we use the square brackets.

This is probably the most common way by far to access data in an Array, but two other techniques are common as well. The pop method is like the cousin, or possibly evil twin, of push. It works in reverse. If removes the last item of the Array. But while it's changing the Array, it returns that last item back to you. Consider the following:

You'll see something like this in your Output panel:

In the first line, we see the current 9-item Array.

Then in the second line, we pop the last item off the end of the Array. We can trace this value out, and see that it is in fact the value that was at the end.

In the third line, we trace the whole Array again, and verify that it is actually missing the last item now.

shift is to pop what unshift is to push. It removes the first item and returns it, sliding the remaining items down one index to close the gap. We can try a similar exercise as we did with pop:

The results will hopefully be clear at this point.

Step 7: How Many Items?

It's very common to want to know how many items are in an Array. We can ask the Array itself for its length. For example:

Assuming we have followed along with all of the added items and popping and shifting, we should see

It's important to remember that while the indices of the Array are zero-based, the length is actually one-based. This isn't contradictory; it's a statement of fact. We're asking the Array, "how many items do you have?" not, "What is the index of your last item?" Even if Arrays were 42-based, as long as there were 7 items in the Array (indices 42 through 48), the length would still be 7. This is often a point of confusion amongst those new to Arrays, so try to remember the subtle distinction between the zero-based index of the last item and the length of the Array.

Note that an Array does not require there to be actual values in its indices to count towards the length. Consider:

Will yield "43," even though 42 of those 43 items aren't defined. But we defined an item at 42, implicitly creating empty slots in everything up to that index, thus contributing to the length. In computer science this illustrates a sparse array, meaning that ActionScript Arrays don't require that all values be "tightly packed" with no null values taking up space. Some languages have dense arrays which are just that, but not ActionScript.

Step 8: Manipulating an Array

There are a number of other useful methods you might want to do to your Array. Refer to the documentation for a complete list, but here are some highlights:

join takes the Array and builds a String representation of it. You can (and probably should) specify the delimiter (that is, the String to use in between each element). By default it is a comma, but using a newline character can be useful when tracing Arrays:

Give that a shot and see what happens.

Tangentially related is the complement String method, split. Taking a String, splitting it into an Array, then joining it back into a String is a quick and dirty way to perform a simple find-and-replace:

reverse does just what you'd think it would do. Go ahead and try it:

Hopefully the results didn't surprise you too much.

sort is a flexible function for sorting the contents of the Array. By itself, it works by sorting according to standard alphabetization rules. Again, go ahead and try it to see:

But the sort method can be told how and on what to sort. See the docs for a full description, but to sum up it's possible to sort numerically (by default numbers are sorted alphabetically, so that "10" comes before "9"), case insensitively (by default "Zoo" comes before "abacus"), ascending or descending, and with other options.

Additionally, sort can use a compare function, which lets you completely customize the sorting logic, and can be extremely useful when you have unique sorting needs. Again, see the docs for more information, but it's useful enough to warrant mention here.

splice is an Array method that lets you remove and/or insert items from/to the Array. It's a rather sophisticated method, allowing to remove and insert at the same time. Let's start with this basic Array:

To remove an item from the Array, we need to use splice with two parameters: the first being the index at which we want to start the operation, and the second being the number of items to remove from the start point. So to remove the item "four" (at index 3), we'd write:

We can also use splice to insert an item. To insert the element "four-point-two" in between the items "four" and "five," we can do the following

This starts with item 4 (the value "five"), deletes nothing (that's what the 0 is for), and then inserts the String given, pushing everything down by one to make room.

indexOf is a simple method that gives you the index of the specified item. For example:

This gives you the number (or, specifically, int) 2. This is the index of the first item matching the supplied value. This is a quick way to search through an Array for a known value, or even to check to see if an Array contains the value, by comparing the result of indexOf to see if it's greater than -1 (indexOf returns -1 if the value is not found in the Array).

There is plenty more to be done with the Array, and even the methods listed here are often capable of more than what my brief description suggests. The documentation for the Array lists all available methods and properties, with at least basic descriptions.

Note that in "traditional" programming, Arrays tend to actually be immutable. That is, once they've been created with a certain set of values, they cannot be (easily) changed. The reasons for this involve memory allocation and lower-level topics that you deal with in languages like C. But in ActionScript, and most scripting languages, much of this has been abstracted away, and we are left with Arrays that are mutable, or Arrays that can be changed at will. There's quite a bit going on under the hood when you call reverse or splice, but don't ask, just be glad you've been saved a bunch of time.

Step 9: Nested Arrays

Array items can be of any type. Arrays can contain, in fact, other Arrays. These "Arrays of Arrays" are called nested arrays or multi-dimensional arrays. They can then be use to store complex data structures. The most common of these is a two-dimensional Array, which is a single Array in which every item is another Array. Each of those "sub Arrays" contains a more primitive value.

Imagine a spreadsheet, with rows and columns full of numbers. This could easily be represented by a two-dimensional Array. The index of the main Array (that is, the first dimension) equates to, say, the row of the spreadsheet. The index of the sub Array designated by that first index equates to the column.

ActionScript itself uses two-dimensional Arrays for a few operations, known as Matrix math. The same idea applies; numbers are stored in a grid (the matrix) and the relationships of those numbers have a sum effect. We won't be looking at them in detail in this tutorial.

We'll take a practical look at a two-dimensional Array in just a few steps, but let's look at how these are set up right now.

We can build up such an Array bit-by-bit:

Doing it like this makes for a rather obvious illustration of what's happening. There is a single Array, called "spreadsheet," and initially empty. We place another empty Array as the first element. Then we start filling in that Array, which is akin to the first row of a spreadsheet. Then we repeat the process, for the second and third rows.

This process is somewhat tedious, but it does illustrate the need to be sure that your "rows" are created as Arrays before you attempt to use them. For example, the following would lead to run time errors:

While at first glance it appears that it should work, notice that spreadsheet[0] was ever defined as being an Array, so trying to access indices off of that would cause problems.

If you'll be doing this kind of set up, you may be interested in a more concise way of writing the exact same data structure:

This approach takes advantage of Array literals and the ability to populate data at the time of creation. Both approaches have their merits, but it usually boils down to personal preference.

For further reading on multi-dimensional Arrays, Wikipedia's entry on Array's has a section on multi-dimensional Arrays, and for a mathematical grounding, visit the entry on matrices for some light reading. ActionScript 3 using matrices in the flash.geom.Matrix object.

Step 10: Vectors

The Vector is a new datatype introduced with Flash Player 10 that is almost identical to an Array. The major difference is that a Vector is set up to only ever allow a certain type of value to be contained by it. For example, if you're tracking positions, you might want a Vector that contains only Numbers. Of course, and Array might contain only Numbers, but a Vector allows you to enforce it. The best way to illustrate this is by example.

We'll create an Array and have it hold a bunch of Strings.

Now, we'll get the second element out.

So far so good. However, notice the datatype on the var "item." This is really only because I know that I've put nothing but Strings into the Array. What happens if I screwed up, and put an int in there, instead?

Trying to get ary[1] out and putting it into a String-typed variable will cause problems. There may be a runtime error, but you don't get the compiler warning you about this. Go ahead and publish the above script. The SWF will compile without errors, but the output won't be what you expect:

The Sprite object got turned into a String upon retrieval from the Array.

A Vector, however, is guaranteed to only have one type of object in it. The set up looks a little odd compared to the rest of ActionScript:

This create a new Vector that is only ever expecting Strings. The dont and the angle brackets are just the syntax for this. The full datatype is "Vector.<Sprite>", where "Sprite" could technically be any other datatype that you want to store.

Now moving on through our data setup, we can try this:

But try to publish this; you'll see that we get a runtime error saying that we tried to put a number into a Vector that was expecting Sprites.

If we fix that, but then try to get data out of it like so:

Then we get a similar error but this one should happen at compile time. We can't put anything other than Sprites into this Vector, and we can't get anything out of it other than Sprites.

Why use Vectors over Arrays? The main reason is for type safety. Most of the time you only have a single datatype within your Array, so you may as well make it official. On top of that, though, Vectors are supposed to be faster than Arrays, especially for large Vectors containing primitive types like Numbers. My feeling is that you can't really go wrong with a Vector, so if you're using Flash Player 10, go ahead and use Vectors. If you're concerned about compatibility with Flash 9, however, you should use Arrays (for instance, in a code library that doesn't otherwise depend on Flash 10 features). Because FlashTuts+ isn't ready to lockout Flash 9, for the remainder of this tutorial we'll be using Arrays.

Step 11: Grids

It's about time to start putting all of this book-learnin' into some street wisdom. We are going to make a simple puzzle game, which will be largely impossible to control without the aid of Arrays. You've probably seen this type of puzzle before. It's a grid of buttons, each in either an on or off state. When you press a button, it toggles its state. But not just its own state; the four buttons that are immediate neighbors to the pressed button will also toggle. The goal is to turn off (or on, depending on how you look at it) all buttons. It's easier to just play it yourself rather than explain in with words:

To see this demo piece, you must have Flash Player 9 or higher installed, and JavaScript turned on.

For convenience, a download is available that provides a starer FLA, with artwork and other basic needs taken care of, so that we can get right to the ActionScript. The next four steps detail what goes into this FLA should you want to start from scratch, or if you're just curious about what's already there (which you should be).

Step 12: Create the FLA

Create a new ActionScript 3 Flash document. Be sure to save it, and set the stage dimensions to 600 x 400. I set up a background layer with a rectangle in it with a brown gradient fill.

Step 13: Create a Grid Button

On a new layer, draw a square 99 pixels wide by 99 pixels high. Use a color that will contrast well with the background (I used an orange gradient fill). Select this artwork and press F8 to create an new MovieClip symbol out it.

Step 14: Create the Button Transition

Double-click on your newly-created MovieClip to enter its timeline. Extend the timeline to 9 frames. Depending on what sort of transition you want, and which version of Flash you're using, you'll have a different approach to creating the actual animation. I leave it up to the reader to sort this out – in my case I created a shape tween and animated the gradient. However it actually happens, the goal is that on frames 1 and 9 we'll have a "normal" state and on frame 5 we'll have an "off" state, with a short and sweet transition between those two states.

On a new layer, place a "traditional" keyframe on frames 1 and 5, and place a simple "stop()" script on those frames. The idea is that we'll control the animation from endlessly looping. It should start on frame 1 and wait, and when we write some more logic, we'll tell the clip to play, which will let the animation play until it hits frame 5, and again on the way back.

Step 15: Layout the Stage

Now for the tedious part (which is why you hopefully downloaded the starter FLA). Back out on the main timeline, duplicate this MovieClip so that there are 24 instances of it on the stage. Arrange them so that they form a grid of 6 columns and 4 rows.

Start at the top left square and give it an instance name of "s1." Click on the next square to the right and name it "s2," and continue similarly until you get to the top right square, with a name of "s6." Start back on the left side, advancing to the second row, and the name "s7." Continue in this fashion until you end up in the lower right, with the name "s24."

Note that included in the download is a JSFL script called "nameGrid.jsfl." If you simply select all 24 squares, then double-click that script, it will run, and name the squares for you (hopefully).

Step 16: Set Up the Script

Now that we have our visuals set up, we can start writing the script. We'll start by creating a new layer on which the code will reside, click on its frame, and pressing F9 (Windows) / Opt-F9 (Mac).

We'll get things rolling by defining some variables. Actually, the first two can be constants:

Then we're going to set up two Arrays, both of which will store references to the MovieClips making up the grid. We'll create a two-dimensional Array called "grid," which we'll the populate through a clever process later. We'll also create a flat list Array called "list," which we'll go ahead an populate with the MovieClips now:

A flat list is just a term for the concept of a one-dimensional Array (in other word, a "normal" Array). The implication, however, is that this data is normally best thought of with a multi-dimensional structure, but for one reason or another we are presenting it now as a single-dimension list.

Step 17: Set up Each Square

This would be a terribly tedious script if we had to set up the mouse event handlers and everything else on all 24 squares individually. Thankfully, the Array provides us with a handy forEach method which will iterate over the Array for us, and performing the specified actions on each in turn.

Please note that the more common approach to this situation is to use a looping structure. I am deliberately using this lesser-known and lesser-used technique for two reasons. One, we will cover loops in the next AS3 101 tutorial and I don't want to have to delve into them prematurely. Two, this allows another opportunity to further explore the Array.

What's happening here? The forEach method takes a function reference as a parameter (much like the addEventListener method). When forEach is called, the Array goes through every item it contains and calls the specified function once for each item. The function will get passed:

  1. The item in the Array
  2. The index of that item
  3. The Array itself

We will come back to this function and flesh it out more thoroughly, but for now, let's just write that onSquareClick function and test the movie:

If you test the movie now, you should be able to click on each square and see the square's name show up in the Output panel. Hopefully you can appreciate the amount of work we've saved ourselves by using the forEach method as opposed to adding 24 event listeners individually.

Step 18: Toggle the Clicked Square

OK, we can finally get to something a little more interesting. Let's trigger the visual effect you'll see when you click a square.

First, let's write a function to handle the toggling of a square (that is, turn it "off" when the square is "on," and vice versa).

Here's what's going on:

First, we check to make sure that a value was actually passed to this function. If not, we simply return and don't do anything else. This will become important a little later.

Then we check to see if the square "isOn." If it is, we make sure "isOn" is false, and we tell the square clip to play its timeline from frame 2 (so that it transitions to the "off" state at frame 5). If it is not, we set "isOn" to true and play the timline from frame 6 (which will play back to the "on" state at frame 9 and then loop back to frame 1, where it will stop again).

But wait, where is this "isOn" coming from? We have to add it. We're just dynamically adding a property to the MovieClip that is the square and letting each square track its own state. To set this up initially, hop back to the setupSquare function and add this line:

We'll work with this later, but for now we just want to make sure the variable is declared and has an accurate value (since we're initiating the board with an "all on" state, we need to make sure the "isOn" variable is true).

One last bit here: in onSquareClick, remove the trace and add this:

Go ahead and test this; you should now have a clickable grid of toggling squares!

Step 19: Set up the Multi-Dimensional Array

Now things get really interesting. We are going to set up the multi-dimensional Array by figuring out the row and column of each square with a little math. Then we'll use that Array to toggle not only the square you clicked on, but also the squares on each side.

First, we need to determine the row and column. Here, we'll be relying on the fact that our clips were set up in the "list" Array in a left-to-right, top-down order. In setUpSquare, add these lines:

What we're doing is using "index" as a way to figure out which row and column we're at. I won't get too into the math, but this is a great trick to squirrel away and use when needed. I'll offer up an explanation for the % symbol in the code: It's the modulo operator, which gives us the remainder of the division operation of the two numbers (10 % 3 gives us 1, because 10 divided by 3 is 3 with a remainder of 1). As an exercise for the confused reader, I leave it to you to go through each index, one-by-one, and work out the math for for yourself (using paper, not the computer). You'll quickly see the pattern, and you'll save me a few paragraphs of typing.

Now, use those values to set up the multidimensional Array:

We first need to make sure that grid[col] is an Array. If it doesn't exist, then we need to set it up as a new Array. Then we can treat grid as a two-dimensional Array and pop in the MovieClip at the appropriate row/column position.

Step 20: Toggle the Neighbors

With our two-dimensional Array set up, we can add this code to the onSquareClick function:

This is a fair amount of code, but really comes down to just toggling four squares. First, we use the Array method indexOf to find the flat list index of the square that was clicked. Then we do the same math as before to turn that index into a row and column.

Finally, we just call toggleSquare on the squares that are neighbors to the clicked square. We determine these by adding or subtracting one from the clicked column or row.

Now, there's a chance that there won't actually be a square at the neighbor position. When you click in the top left corner, for instance, there are no top or left neighbors. Clicking anywhere in the bottom row means no bottom neighbor.

To safeguard against this, we already added the "if there is no actual square passed, don't do anything" check to toggleSquare. But in the case of the edge columns, the problems is actually a matter of the entire column not existing. Imagine this: You click in the left column. The column is determined to be at position 0. To find the left neighbor, you subtract one from the column position. This gives us a column of -1. However, accessing the grid Array with an index of -1 results in no value; there isn't anything with a value of -1! So, we do two checks on the value of the column, to make sure it's within bounds before attempting to toggle the square with that neighbor column index.

If you try it out now, you should have a nearly functioning game.

Step 21: Check for a Win

In order to see if we've won the game, we need to check for a win basically every time something happens that could potentially result in a win. In this simple game's case, a win might occur any time the user clicks a square. So, we are going to add code to the onSquareClick function that will check through each square's "isOn" variable and decide if there is a win or not depending on if any square's "isOn" variable is false. Add this code to the end of the "onSquareClick" function:

The Array's every method is similar in concept to the forEach method, although it's a way of check for a yes/no situation within the Array. Basically, the function we supply to the every method need to return either true or false. The method itself will return true if every item in the Array resulted in a true return from the supplied function, or false if at least one item caused a false return. We'll write a "checkWin" function that returns true is a given square in the Array is "on," and false if "off." Put this function anywhere that makes sense, outside of any other function:

Like the forEach method, this function will receive the item in the Array (the MovieClip), along with the index and the Array itself. We're only interested in the MovieClip, specifically the "isOn" variable contained therein. However, unlike the forEach method, we need to return a Boolean value. We'll simply return the value of the "isOn" variable itself. If any one of the squares is off, it's "isOn" variable will be false, and the every method will return false, meaning we don't win. If all are on, however, we'll get true from the every method, and therefore we'll see the win message.

Why are we using every instead of forEach? Well, for one, it's more apt to what we're trying to do. We could accomplish this with forEach, but it would involve more steps. However, another benefit is efficiency. At the first false returned to every, every will stop iterating and simply return false. So, if the first square is off, then we know it's not a win, and we don't need to iterate over the remaining 23 squares.

Go ahead and try this out. Since the game starts out with all squares on, it should be pretty easy to test: just click any square, then click it again, and you should see the trace. To give it a more robust test, try clicking a few different squares, then click them again to get back to the win state.

Step 22: Randomize the Start

Well, it's pretty easy to win when you start in the win state, isn't it? To make this a game worthy of a challenge, let's create a random board, with some squares on and some off, that we can win.

The idea will be to automatically do what you did manually in the last step when testing. We don't want to just randomly turn some squares on and some squares off, because there's a solid chance that that board won't be able to be solved. We can be sure of creating a game that can be won by starting in the win state, and then having the computer pick some squares and random, stepping them through the entire toggle process (that is, toggling the neighbors as well), one at a time. At the very least, the game can be won by clicking on all of the randomly chosen squares.

However, we need to make sure the entire board is set up before we attempt to toggle any of the squares. So the easiest approach will be to set up another forEach call after the forEach call that sets up the squares. Add this line right below the list.forEach(setupSquare); line:

And then find a good spot to write a new function (it makes sense to put it after the "setupSquare" function, but it really doesn't matter. Organize your code in a way that makes sense to you):

This means that statistically, about 40% of the squares will be instructed to toggle into the off state. It's an interesting technique, but we can "fake" a click event by telling the square to dispatch a faux MouseEvent. This in turn triggers the "onSquareClick" function, as if the user has clicked the square, toggling it and its neighbors. In this case, though, several squares get toggled in the blink of an eye, setting the board for a winnable game.

Test this movie now, and you should have a relatively difficult board ready for playing. You can change the difficulty by increasing the number on the right side of the comparison. Don't set it to 0 or 1, but the closer to 0, the easier it is; the closer to 1, the harder it is (generally speaking).

Conclusion

You should be a certified Array Master at this point. You've used Arrays in ways that even some seasoned ActionScripters don't know about (go ahead, ask a seasoned ActionScripter if he or she knows what the every method does). Arrays are instrumental in virtually every application. You will quickly learn that Arrays coupled with iteration can save you all kinds of time. When set up intelligently and with an eye towards future expansion, if you simply change the Array, the program itself will handle the rest. For example, to create a board with more squares, all we need to do is make the visual alterations and update the "list" Array. After that, the iteration functions elegantly handle the Arrays regardless of how many items are in them.

Next time, we'll talk about looping structures, which complement Arrays the way peas complement carrots. We've actually avoided loops specifically in this tutorial, but we'll take a nice long look at them in just a few short weeks.

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.