This is a tutorial on how to make a simple maze game that demonstrates the usefulness of arrays.
The Basic Structure of the Maze
The maze will consist of many individual "cells." Each cell is like a block in the maze, and each cell has four walls (north, east, south, and west). In the making of the maze, some walls will be knocked down to form a path, so each of the walls must be its own seperate movie clip, contained within the cell movie clip. Also, each wall must consist of two frames, for the two possible states -- standing up and knocked down.
Now, to actually make a cell. Hit Ctrl + F8, give the movie clip the name "cell," and check the box that says "export for ActionScript." Next, draw a 25 * 25 square, and give it an x-coordinate of 0 and a y-coordinate of 0. Then, make its sides into movie clips (top side should be called "north", right side should be called "east", bottom side should be called "south", and left side should be called "west"). Make sure you not only give them names, but instance names. Each of those movie clips should have two frames. On the first frame, write:
stop();
Then, insert a blank keyframe for the second frame, and write the same thing for it. Do this for each of the four walls. Once you're done with that, go to the main timeline. Now we'll need a function that makes a grid of these cells.
The Basic Structure of the First Function
Basically, we want the function to cycle through each of the rows in the maze, and then each of the spaces with those rows. For each of those spaces, we want a cell to be added. To differentiate between the cells, we'll call them "cell0", "cell1", "cell2", etc. Also, we'll make an array. Each item in the array will represent a seperate row in the grid. In addition, we'll have a variable called "carved," which will be false only if all four walls of a cell are standing.
Pseudo-Code for the First Function
Create Array Representing Grid
Set Variable that Contains Current Cell Number
For each of the rows:
Create Array Representing Row
For each of the Cells Within the Row:
Attach Cell to Grid
Set Carved for Current Cell to False
Append Cell to Array
Increment Current Cell Number (+1)
End for
Append Array Representing Row to Array Representing Grid
End for
Now for the real code:
Actual Code
function createGrid()
{
currentCell = 0;
arrayOfCells = [];
for (i = 0; i < 16; i++)
{
thisRow = [];
for (j = 0; j < 22; j++)
{
newCell = attachMovie("cell", "cell" + currentCell, this.getNextHighestDepth());
newCell._x = j * 25;
newCell._y = i * 25;
newCell.carved = false;
currentCell++;
thisRow.push(newCell);
}
arrayOfCells.push(thisRow);
}
}
Place this code in the actions for the main timeline.
The Basic Structure of the Second Function
Now for building the actual maze. The algorithm is quite simple. At each cell, you can go to any neighboring cell that is uncarved (all its walls are standing up). You can pick a random one. If you have nowhere to go, you go back to the last place where you had two or more choices of where to go (you go down one path, you run into a dead end, then you go down the other). When you don't have any more places where you had two choices and you're stuck, the maze is done.
Pseudo-Code for the Second Function
Current Row = Last Row
Current Cell = Last Cell in Row
Create Array for Places with 2+ Choices
Until the Maze is Done, Do:
Set Current Cell to "carved"
Set Array of Choices to []
Add All Neighboring Cells that are not Carved to the Array
If you have no Choices:
If the Array of Places with 2+ Choices is Empty:
the Maze is Done
Otherwise:
Go to the Last Item in the Array of Places With 2+ Choices
Delete that Last Item of that Array
Pick Random Item from Array
Current Row = new Current Row
Current Cell = new Current Cell
Actual Code
function carveMaze()
{
row = 15;
item = 21;
stack = [];
while (true)
{
arrayOfCells[row][item].carved = true;
choices = [];
if (arrayOfCells[row][item + 1].carved == false)
{
choices.push("EAST");
}
if (arrayOfCells[row][item - 1].carved == false)
{
choices.push("WEST");
}
if (arrayOfCells[row + 1][item].carved == false)
{
choices.push("SOUTH");
}
if (arrayOfCells[row - 1][item].carved == false)
{
choices.push("NORTH");
}
if (choices.length == 0)
{
if (stack.length == 0)
{
break;
}
row = stack[stack.length - 1][0];
item = stack[stack.length - 1][1];
stack.pop();
}
else
{
if (choices.length >= 2)
{
stack.push([row, item]);
}
choice = choices[random(choices.length)];
if (choice == "NORTH")
{
arrayOfCells[row][item].north.gotoAndStop(
2);
arrayOfCells[row - 1][item].south.gotoAndStop(2);
arrayOfCells[row - 1][item].carved = true;
row--;
}
if (choice == "EAST")
{
arrayOfCells[row][item].east.gotoAndStop(2
);
arrayOfCells[row][item + 1].west.gotoAndStop(2);
arrayOfCells[row][item + 1].carved = true;
item++;
}
if (choice == "SOUTH")
{
arrayOfCells[row][item].south.gotoAndStop(
2);
arrayOfCells[row + 1][item].north.gotoAndStop(2);
arrayOfCells[row + 1][item].carved = true;
row++;
}
if (choice == "WEST")
{
arrayOfCells[row][item].west.gotoAndStop(2
);
arrayOfCells[row][item - 1].east.gotoAndStop(2);
arrayOfCells[row][item - 1].carved = true;
item--;
}
}
}
}
Stack is what contains all the places where you had two or more choices -- push() adds an item to an array, and pop() deletes the last item.Place that code on the actions for the main timeline. Then, to run both functions:\
createGrid();
carveMaze();
stop();
It should look something like this: