Lab 07 - 3D Maze (10/28/2020)


Description

"Two SCUBA diving buddies have encountered a large, box-shaped storage facility inside the hull of the Heian Maru, a 512' submarine tender lying on the bottom of Truk Lagoon at 108'. The storage facility is composed of cells, some of which can be entered and some which cannot. The only exterior walls that are missing are on the front of the storage facility in the upper left corner, and on the rear of the storage facility in the lower right corner. The divers wish to determine a path through the storage facility. Use recursion to find a path through the maze or to prove that there is no path."

Learning Outcomes

By completing the 3D Maze Lab, you will be able to:


Discussion

Backtracking

Backtracking is an approach to implementing a systematic trial and error search for a solution. An example is finding a path through a maze. If you are attempting to walk through a maze, you will probably have many decisions to make at path junctions as to which path to take when there is more than one option. You hope to always pick the right path that will lead you out of the maze. However, inevitably you will end up choosing a non-solution path and encounter a "dead end". At that point you will have to "backtrack" to the last decision point and try another path. Eventually, you will reach your destination and exit the maze, or you discover there is no way out of the maze and you end up back where you started.

Backtracking is a systematic, non-repetitive approach to trying alternative paths and eliminating them if they don’t work. If you never try the same path more than once, you will eventually find a solution path if one exists. Problems that are solved by backtracking can be described as a set of choices made by some function. Recursion allows you to implement backtracking in a relatively straightforward manner. Each activation frame is used to remember the choice that was made at that particular decision point. A program used to solve a maz or play a decision game (such as chess) usually involves some kind of backtracking algorithm.

The Maze

The Maze class has-a 3 dimensional dynamic array that indicates whether a cell can be entered (OPEN), is walled off (BLOCKED), is part of the path (LEFT, RIGHT, UP, DOWN, OUT, IN) through the maze, is the maze exit cell (EXIT), or is a cell that has already been visited (VISITED). A enum statement allows the compiler to define these enumerations:

enum CellValue_t { OPEN, BLOCKED, VISITED, EXIT, LEFT, RIGHT, UP, DOWN, OUT, IN };

The maze size is defined by height x width x layer as specified on the first line of the test file. The 3 dimensional dynamic array is represented as 2 dimensional height x width layers as follows:

Dynamic Arrays.

A dynamic array is basically an array of pointers to arrays. A 2 dimensional 10 x 10 dynamic array is created using a loop as follows

int height = 10;
int width = 10;
int **myArray = new int*[height];
for(int i = 0; i < height; ++i)
{
    myArray[i] = new int[width];
}

Since new is used in creating the dynamic array, all width arrays must be deleted followed by the height array to prevent memory leaks:

for(int i = 0; i < height; ++i)
{
    delete [] myArray[i];
}
delete [] myArray;

The 3D maze array is of data type "int***" - that's right, a pointer to a pointer to a pointer to an int. The following diagram illustrates the memory layout for a 3 x 2 x 2 dynamic integer array:

The Lab

Lab guidelines:

  1. The format of a Maze input file ia as follows:

    • First row is the height, width, and number of layers of the maze.
    • Next follows the height x width values for each layer, beginning with a blank line and followed by the number 0 or 1 for each width value.
      • A 0 indicates an open path (can enter) and
      • A 1 indicates a closed path (blocked).

  2. The top-left (start) and bottom-right (exit) cells are always open (0).
  3. Your find_maze_path function should be able to solve any size array.
  4. To match the output files exactly, recurse in the following order: left (width - 1), right (width + 1), up (height - 1), down (height + 1), out (layer - 1), and in (layer + 1).

Lab requirements:

  1. You are,required to write a Maze class that inherits from the provided MazeInterface, available at the top of this page. Comments in MazeInterface.h explain exactly what each function should do.
  2. Your Maze class should contain a recursive and wrapper find_maze_path function.
  3. The maze output consists of height x width layers, with:

    • Each new layer is preceded by "Layer #".
    • Unvisited open cells are output as an underscore character ("_").
    • Visited cells not on the path are output as an asterisk character ("*").
    • Blocked cells are output as the character "X".
    • The solution path is output as either a 'L', 'R', 'U', 'D', 'O', or 'I' character.
    • The exit cell is output as the 'E' character.
    • Put a space between each cell character value.

  4. The overloaded find_maze_path functions are found inside the Maze class along with the setValue and toString functions.
  5. Use the Maze toString method to output the maze before and after finding a path through the maze.
  6. The following is an example of the output from a 2 x 2 x 2 maze:
    Solve Maze:
    Layer 1
     _ _
     _ X
    Layer 2
     X _
     X _
    
    Solution:
    Layer 1
     R I
     _ X
    Layer 2
     X D
     X E
  7. NO STL CONTAINERS MAY BE USED IN THIS LAB!
  8. REMEMBER: To match the output files exactly, recurse in the following order: left (width - 1), right (width + 1), up (height - 1), down (height + 1), out (layer - 1), and in (layer + 1).

Steps to Success:

Steps to Success:


Helps and Hints

Videos:

File Input and Output:

  1. Use argv[1] for input and argv[2] for output.
  2. if (argc < 3)
    {
       cerr << "Please provide name of input and output files";
       return 1;
    }
    cout << "Input file: " << argv[1] << endl;
    ifstream in(argv[1]);
    if (!in)
    {
       cerr << "Unable to open " << argv[1] << " for input";
       return 1;
    }
    cout << "Output file: " << argv[2] << endl;
    ofstream out(argv[2]);
    if (!out)
    {
       in.close();
       cerr << "Unable to open " << argv[2] << " for output";
    }

Understanding Valgrind Output.(collapse)

  • You can find helpful hints and explanations of Valgrind output here.

3D Maze Grading Criteria

Instructions for submitting your lab:

Use the following input and resulting output files in testing the 3D Maze lab.

Input FileOutput File
Test #1 lab07_in_01.txt lab07_out_01.txt
Test #2 lab07_in_02.txt lab07_out_02.txt
Test #3 lab07_in_03.txt lab07_out_03.txt
Test #5 lab07_in_05.txt lab07_out_05.txt

The auto-grader will be expecting to find in your output file the following sections:

Fail
Pass
Score = 0

 

The lab source will be peer reviewed using the following rubric:

No
Partial
Yes
Score = 0
Overall
Rating
Easy to follow, readable, organized, and well commented.
                      
***NOTE: Any attempt to circumvent any lab requirement (ie, hard coding
output, using loops instead of iterators where required, modifying a class interface, etc.) will be reported by peer reviewers and result in a zero score for the lab.
Total Score = 0