Computer Science Department
+---------+ 4 | | G| |---- | | 3 | | | | | 2 | | | | | ------| 1 | | | | | | 0 |S| | +---------+ 0 1 2 3 4
The diagram shows a map of 11x11 characters, but it is to be stored as a one-dimensional character array of 121 elements. Imagine a robot moving through the maze from the starting position, S, to the goal position, G. The robot makes up, right, down, and left movements of two positions at a time. The numbers show the row and column numbers that are the allowed robot positions. So, S is at position (0,0), representing the row and column as (row, column). If the robot moves up from S, it arrives at (1,0). Note that this is not (x,y) as on a plot, where x is the left to right position. Instead, we are using notation like (y,x). The goal, G, is at (4,4). The shortest path from S to G in this maze is 8 steps long, following positions (0,0), (1,0), (2,0), (3,0), (3,1), (3,2), (3,3), (3,4), (4,4). Obviously, the robot cannot go through any walls.
As your robot explores, it will leave a breadcrumb at every position that it has visited. A visited position will be marked by an asterisk, '*', in the map. For example, here is the result of one exploration after finding the goal. Notice that not all states were visited. It stopped as soon as it found the goal.
+---------+ | * *|* G| |---- | | |* * * * | | | | |*|* * | | | ------| |*|* | | | | |S| | +---------+
For each maze,
{ Erase all breadcrumbs.
Set the current state to the starting state.
Push the current state and zero steps on a stack.
While the goal has not been found,
{ Pop the state and
steps from the stack. Set the current state to this state.
Mark the current
state as visited.
Try each action, a, in order from the set (up, right, down, left)
{ If there is not a wall in the a direction from the current state, then
{ Get the new state, given the current state and the action a.
If the new state is the goal state, then
Set a flag variable that will cause the outer while loop to terminate.
else if the new state has not been visited, then
Push the current state and current steps + 1 onto the stack.
else
Just delete the the current state.
} else (there is a wall in the a direction)
do nothing.
} (end of action loop)
Delete the storage used for the current state.
} (end of while not goal loop)
Return the number of steps associated with the goal state.
}
You must run this algorithm once as is, and a second time using a queue in place of the stack.
Private variables will include the start state, the number of rows and columns and a dynamic 1-D character array for the map. This is the trickiest part. We will use the map to record all information, including the boundary walls, the start and goal states, the interior walls, and the states that have been visited so far. The array will contain all of the characters shown in the above maps, except the numbers along the side and bottom. Walls are marked with '|' and '-', the start state is marked by 'S', the goal state is marked by 'G', and the breadcrumbs with '*'.
When the robot moves, it either moves two characters to the right or left, or up or down the equivalent of two rows in the 1-D character array. It will be convenient if you define a private function, with a name like MapIndex, in the Maze class that translates a state into an index into the map. For example, in the maze above, the robot can be at 25 positions from (0,0) to (4,4), but the character array is actually 11x11 characters, or 121 characters total. The upper left '+' is at index 0 and the lower right '+' is at index 120. The start state is (0,0), but this is index 100 in the one-dimensional character array. The goal state is at (4,4), or index 21. This should give you some ideas about how to check for walls. If the robot is in state (0,0) and wants to move right, just check the character at index 101 to see if it is '|' or '-'. If you want to move up, you must check index 100-11, or 89. Remember to write your MapIndex function in a general way that works for any maze of a given number of rows and columns.
You must write public methods for all of the necessary functions. These functions are
Let's say the robot's position is at (r,c). For the example maze above, r and c are integers in the range 0 to 4. We want to find the linear function, f(r,c), that results in the 1-D index, which ranges from 0 to 11x11, or 121, for this example. Assume we are storing the characters of the maze in a 1-D character array in the order that they are read in. (Is this column major, or row major?)
Let's look at some example values of f(r,c). When the robot is in the upper left position, (r,c)=(4,0) for this maze. The 1-D index of the first '+' is 0, for the second '+' it is 10, for the first '|' it is 11, and for (r,c)=(4,0), it is 12. So f(4,0)=12. For the goal position, (r,c)=(4,4), and the 1-D index value is f(4,4)=20.
Now let's derive f. What is the form of f? We said earlier that it is linear. The most general linear form is
f(r,c) = u x r + v x c + w
How do we determine the constants u, v, and w? One way is trial and error, but this gets discouraging real fast. A more systematic way is to solve a set of simultaneous linear equations. To determine the values of the three constants, how many equations do we need? Three. We have two examples from above, f(4,0)=12 and f(4,4)=20. Let's pick a third that makes it real easy to find w. What is f(0,0)? The lower right '+' is at index 120, so the lower left '+' is at 110. The '|' above that '+' is at 110-11=99, so S, which is (0,0), is at index 100. So, f(0,0)=100.
Now our simultaneous linear equations are
f(0,0) = u x 0 + v x 0 + w = 100
f(4,0) = u x 4 + v x 0 + w = 12
f(4,4) = u x 4 + v x 4 + w = 20
The first equation tells us that w = 100. From this and the second equation, we get
u x 4 + 100 = 12
4u = -88
u = -22
Now we can solve for v in the third equation.
-22 x 4 + v x 4 + 100 = 20
-88 + v x 4 + 100 = 20
v x 4 = 8
v = 2
So, we now know that
f(r,c) = -22 x r + 2 x c + 100
For this assignment, you must generalize this for any maze with a given number of rows and columns. Your index mapping function must include these parameters, so f is now a function of four arguments, f(r,c,rows,columns), although if you write a mapping function as a method for your Maze class, rows and columns will be private variables and not arguments. You can derive this more general function f using the same simultaneous linear equation procedure, but the examples used to generate the equations must include the rows and columns parameters.
The input data file contains a sequence of four mazes, each specified by the rows and columns on one line, followed by the initial character map. Click here to get the input data file.
+---------+
| | G|
|---- | |
|* * *|
| | |
|*|* * * *|
| | ------|
|*|* * * *|
| | |
|S|* * * *|
+---------+
+---------+
| * *|* G|
|---- | |
|* * * * |
| | |
|*|* * |
| | ------|
|*|* |
| | |
|S| |
+---------+
Maze 1 was solved with paths of
10 steps using a stack and
8 steps using a queue.
The output from the other mazes will appear after this.
While writing your solution, you should add lots of calls to cout to produce
output you can use to debug your program. See this file of debugging output that was produced by a successful
program.
Copyright © 1998: Colorado State University for CS200. All rights reserved.