Advertisement
Guest User

Untitled

a guest
Jun 18th, 2018
58
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 13.30 KB | None | 0 0
  1. /******************************************************************************
  2. * File: maze.cpp
  3. * Author: Damian Morgan
  4. * Class: COP2001; 201805; 50135
  5. * Purpose: Random maze generator using multi dimensional arrays
  6. *******************************************************************************/
  7. #include <iostream>
  8. #include <string>
  9. #include <cstdlib>
  10. #include <time.h>
  11.  
  12. using namespace std;
  13.  
  14. #define BYTE unsigned char
  15.  
  16. // wall & visited flag vales
  17. const BYTE CELL_TOP = 1;
  18. const BYTE CELL_BOTTOM = 2;
  19. const BYTE CELL_LEFT = 4;
  20. const BYTE CELL_RIGHT = 8;
  21. const BYTE CELL_VISITED = 16;
  22.  
  23. // maze dimensions
  24. const int MAZE_ROWS = 3;
  25. const int MAZE_COLS = 3;
  26.  
  27.  
  28. // starting cell
  29. const int START_CELL_ROW = 0;
  30. const int START_CELL_COL = 0;
  31. const int START_WALL = CELL_LEFT;
  32.  
  33. // ending cell
  34. const int END_CELL_ROW = 2;
  35. const int END_CELL_COL = 2;
  36. const int END_WALL = CELL_RIGHT;
  37.  
  38. // location indexes
  39. const int CELL_ROW_INDEX = 0;
  40. const int CELL_COL_INDEX = 1;
  41.  
  42.  
  43. // maze print characters
  44. const char OUT_TOP_LEFT = '-';
  45. const char OUT_TOP_MID = '-';
  46. const char OUT_TOP_RIGHT = '-';
  47. const char OUT_SIDE_LEFT = '|';
  48. const char OUT_SIDE_RIGHT = '|';
  49. const char OUT_BOT_LEFT = '-';
  50. const char OUT_BOT_MID = '-';
  51. const char OUT_BOT_RIGHT = '-';
  52. const char INSIDE_MIDDLE = '+';
  53. const char CELL_TOP_BOT = '-';
  54. const char CELL_LEFT_RIGHT = '|';
  55. const char CELL_OPEN_HORZ = ' ';
  56. const char CELL_OPEN_VERT = ' ';
  57. const char CELL_VISITIED_ON = '.';
  58. const char CELL_VISITIED_OFF = ' ';
  59.  
  60. // function declarations
  61. bool hasUnvisitedCells(BYTE cells[][MAZE_COLS]);
  62. bool hasAvailableNeighbors(BYTE cells[][MAZE_COLS], int location[]);
  63. void chooseRandomNeighbor(BYTE cells[][MAZE_COLS], int current[], int neighbor[]);
  64. void removeWalls(BYTE cells[][MAZE_COLS], int current[], int neighbor[]);
  65. void initMaze(BYTE cells[][MAZE_COLS]);
  66. int pushStack(int stack[][2], int location[], int stackPoint);
  67. void popStack(int stack[][2], int location[], int& stackPoint);
  68. void copyOneLocTwo(int locOne[], int locTwo[]);
  69. void printMaze(BYTE cells[][MAZE_COLS]);
  70. void printMazeDebug(BYTE cells[][MAZE_COLS]);
  71.  
  72.  
  73. int main() {
  74.     char tmp;                           // pause program
  75.  
  76.                                         // init random generator
  77.     srand(time(NULL));                  // stdlib; time.h
  78.  
  79.     // sotrage for the maze cells
  80.     BYTE maze[MAZE_ROWS][MAZE_COLS] = { 0 };
  81.  
  82.     // storage for our stack of visited cells
  83.     int stack[MAZE_ROWS * MAZE_COLS][2] = { 0 };
  84.  
  85.     int stackPointer = -1;              // empty stack value
  86.  
  87.     initMaze(maze);
  88.  
  89.     // set starting cell
  90.     int startCell[2];
  91.     startCell[CELL_ROW_INDEX] = START_CELL_ROW;
  92.     startCell[CELL_COL_INDEX] = START_CELL_COL;
  93.     // turn off starting wall
  94.     maze[startCell[CELL_ROW_INDEX]][startCell[CELL_COL_INDEX]] ^= START_WALL;
  95.  
  96.     // turn off ending wall
  97.     maze[END_CELL_ROW][END_CELL_COL] ^= END_WALL;
  98.  
  99.     printMaze(maze);
  100.  
  101.     cout << endl;
  102.  
  103.     printMazeDebug(maze);
  104.  
  105.     cout << endl;
  106.  
  107.     cin >> tmp;
  108.  
  109.     // 1. Make the inital cell the current cell and mark it as visited
  110.     int currentCell[2];
  111.     copyOneLocTwo(startCell, currentCell);
  112.     // mark visited flag
  113.     maze[currentCell[CELL_ROW_INDEX]][currentCell[CELL_COL_INDEX]] ^= CELL_VISITED;
  114.  
  115.  
  116.     // 2. While there are unvisited cells
  117.     while (hasUnvisitedCells(maze)) {
  118.  
  119.         // i. if the current cell has any neighbors which have not been visited
  120.         if (hasAvailableNeighbors(maze, currentCell)) {
  121.  
  122.             // 1. Chose randomly one of the unvisited neighbors
  123.             int neighborCell[2] = { 0 };
  124.             chooseRandomNeighbor(maze, currentCell, neighborCell);
  125.  
  126.             // 2. Push the current cell to the stack
  127.             stackPointer = pushStack(stack, currentCell, stackPointer);
  128.  
  129.             // 3. Remove the wall between the current cell and the chosen cell
  130.             removeWalls(maze, currentCell, neighborCell);
  131.  
  132.             // 4. Make the chosen cell the current cell and mark it as visited
  133.             copyOneLocTwo(neighborCell, currentCell);
  134.             // mark visited flag
  135.             maze[currentCell[CELL_ROW_INDEX]][currentCell[CELL_COL_INDEX]] ^= CELL_VISITED;
  136.  
  137.             // 5. Print the Maze
  138.             printMaze(maze);
  139.             cout << endl;
  140.  
  141.             printMazeDebug(maze);
  142.             cout << endl;
  143.  
  144.             cin >> tmp;
  145.  
  146.         } // end has any neighbors
  147.  
  148.           // ii. Else if the stack is not empty
  149.         else if (stackPointer > -1) {
  150.  
  151.             // Pop the last cell from the stack and make it the current cell
  152.             popStack(stack, currentCell, stackPointer);
  153.  
  154.         }
  155.  
  156.  
  157.     } // end while there are unvisitied cells
  158.  
  159.  
  160.       // 3. Print the Maze
  161.     printMaze(maze);
  162.     cout << endl;
  163.  
  164.     printMazeDebug(maze);
  165.     cout << endl;
  166.  
  167.     // pause program
  168.     cin >> tmp;
  169.  
  170.     return 0;
  171. } // end main
  172.  
  173.   /***/
  174. bool hasUnvisitedCells(BYTE cells[][MAZE_COLS]) {
  175.  
  176.     bool isVisited = true;
  177.  
  178.     int row = 0;
  179.  
  180.  
  181.     while (isVisited && row < MAZE_ROWS) {
  182.  
  183.         int col = 0;
  184.         while (isVisited && col < MAZE_COLS) {
  185.  
  186.             isVisited = cells[row][col] & CELL_VISITED;
  187.             col++;
  188.         }
  189.  
  190.         row++;
  191.     }
  192.  
  193.     return !isVisited;
  194. }
  195.  
  196.  
  197. /**
  198. * Checks to see if there are any available neigbors
  199. * @param cells - the maze
  200. * @param location - the position of the cells
  201. */
  202. bool hasAvailableNeighbors(BYTE cells[][MAZE_COLS], int location[]) {
  203.     // check if has neighbor above
  204.  
  205.     if (location[CELL_ROW_INDEX] > 0) {
  206.         // check if not visited
  207.         if (!(cells[location[CELL_ROW_INDEX] - 1][location[CELL_COL_INDEX]] & CELL_VISITED)) {
  208.             return true;
  209.         }
  210.     }
  211.  
  212.     // check if has neighbor below
  213.  
  214.     if (location[CELL_ROW_INDEX] < MAZE_ROWS - 1) {
  215.         // check if not visited
  216.         if (!(cells[location[CELL_ROW_INDEX] + 1][location[CELL_COL_INDEX]] & CELL_VISITED)) {
  217.             return true;
  218.         }
  219.     }
  220.  
  221.     // check if has left neighbor
  222.  
  223.     if (location[CELL_COL_INDEX] > 0) {
  224.         // check if not visited
  225.         if (!(cells[location[CELL_ROW_INDEX]][location[CELL_COL_INDEX] - 1] & CELL_VISITED)) {
  226.             return true;
  227.         }
  228.     }
  229.  
  230.     // check if has right neighbor
  231.  
  232.     if (location[CELL_COL_INDEX] < MAZE_COLS - 1) {
  233.         // check if not visited
  234.         if (!(cells[location[CELL_ROW_INDEX]][location[CELL_COL_INDEX] + 1] & CELL_VISITED)) {
  235.             return true;
  236.         }
  237.     }
  238.  
  239.     return false;
  240.  
  241. } // end hasAvailableNeighbors
  242.  
  243.  
  244.   /**
  245.   * Chooses a random neighbor in the maze
  246.   * @param cells - the maze
  247.   * @param current - the current position of the maze
  248.   * @param neighbor - the position of the neighbor
  249.   */
  250. void chooseRandomNeighbor(BYTE cells[][MAZE_COLS], int current[], int neighbor[]) {
  251.  
  252.     bool done = false;
  253.  
  254.     while (!done) {
  255.         int randNeighbor = rand() % 4;      // random 0 through 3
  256.  
  257.         switch (randNeighbor) {
  258.  
  259.         case 0:                     // TOP
  260.             if (current[CELL_ROW_INDEX] > 0) {
  261.                 if (!(cells[current[CELL_ROW_INDEX] - 1][current[CELL_COL_INDEX]] & CELL_VISITED)) {
  262.  
  263.                     neighbor[CELL_ROW_INDEX] = current[CELL_ROW_INDEX] - 1;
  264.                     neighbor[CELL_COL_INDEX] = current[CELL_COL_INDEX];
  265.  
  266.                     done = true;
  267.  
  268.                 }
  269.             }
  270.             break;
  271.  
  272.         case 1:                     // BOTTOM
  273.             if (current[CELL_ROW_INDEX] < MAZE_ROWS - 1) {
  274.                 if (!(cells[current[CELL_ROW_INDEX] + 1][current[CELL_COL_INDEX]] & CELL_VISITED)) {
  275.  
  276.                     neighbor[CELL_ROW_INDEX] = current[CELL_ROW_INDEX] + 1;
  277.                     neighbor[CELL_COL_INDEX] = current[CELL_COL_INDEX];
  278.  
  279.                     done = true;
  280.  
  281.                 }
  282.             }
  283.             break;
  284.  
  285.         case 2:                     // LEFT
  286.             if (current[CELL_COL_INDEX] > 0) {
  287.                 if (!(cells[current[CELL_ROW_INDEX]][current[CELL_COL_INDEX] - 1] & CELL_VISITED)) {
  288.  
  289.                     neighbor[CELL_ROW_INDEX] = current[CELL_ROW_INDEX];
  290.                     neighbor[CELL_COL_INDEX] = current[CELL_COL_INDEX] - 1;
  291.  
  292.                     done = true;
  293.                 }
  294.             }
  295.             break;
  296.  
  297.         case 3:                     // RIGHT
  298.             if (current[CELL_COL_INDEX] < MAZE_COLS - 1) {
  299.                 if (!(cells[current[CELL_ROW_INDEX]][current[CELL_COL_INDEX] + 1] & CELL_VISITED)) {
  300.  
  301.                     neighbor[CELL_ROW_INDEX] = current[CELL_ROW_INDEX];
  302.                     neighbor[CELL_COL_INDEX] = current[CELL_COL_INDEX] + 1;
  303.  
  304.                     done = true;
  305.  
  306.                 }
  307.             }
  308.             break;
  309.  
  310.         } // end switch
  311.  
  312.  
  313.     }
  314.  
  315. } //end chooseRandomNeighbor
  316.  
  317.  
  318.   /**
  319.   * Remove the wall between the current cell and the chosen cell
  320.   * @param cells - the maze
  321.   * @param current - the current position of the maze
  322.   * @param neighbor - the position of the neighbor
  323.   */
  324. void removeWalls(BYTE cells[][MAZE_COLS], int current[], int neighbor[]) {
  325.  
  326.     // test for the location of current and neighbor
  327.  
  328.     // test for neighbor above
  329.     if (neighbor[CELL_ROW_INDEX] < current[CELL_ROW_INDEX]) {
  330.  
  331.         cells[neighbor[CELL_ROW_INDEX]][neighbor[CELL_COL_INDEX]] ^= CELL_BOTTOM;   // toggle wall off
  332.         cells[current[CELL_ROW_INDEX]][current[CELL_COL_INDEX]] ^= CELL_TOP;
  333.     }
  334.  
  335.  
  336.     // test for neighbor below
  337.  
  338.     else if (neighbor[CELL_ROW_INDEX] > current[CELL_ROW_INDEX]) {
  339.  
  340.         cells[neighbor[CELL_ROW_INDEX]][neighbor[CELL_COL_INDEX]] ^= CELL_TOP;      // toggle wall off
  341.         cells[current[CELL_ROW_INDEX]][current[CELL_COL_INDEX]] ^= CELL_BOTTOM;
  342.     }
  343.  
  344.     // test for neighbor left
  345.  
  346.     else if (neighbor[CELL_COL_INDEX] < current[CELL_COL_INDEX]) {
  347.  
  348.         cells[neighbor[CELL_ROW_INDEX]][neighbor[CELL_COL_INDEX]] ^= CELL_RIGHT;    // toggle wall off
  349.         cells[current[CELL_ROW_INDEX]][current[CELL_COL_INDEX]] ^= CELL_LEFT;
  350.     }
  351.  
  352.     // neighbor must be right
  353.  
  354.     else {
  355.  
  356.         cells[neighbor[CELL_ROW_INDEX]][neighbor[CELL_COL_INDEX]] ^= CELL_LEFT;     // toggle wall off
  357.         cells[current[CELL_ROW_INDEX]][current[CELL_COL_INDEX]] ^= CELL_RIGHT;
  358.  
  359.     }
  360. } // end removeWalls
  361.  
  362.  
  363.   /**
  364.   * Initialize maze array elements to turn all
  365.   * walls on and visited off
  366.   * @param cells - the grid of cells in the maze
  367.   */
  368. void initMaze(BYTE cells[][MAZE_COLS]) {
  369.  
  370.     for (int row = 0; row < MAZE_ROWS; row++) {
  371.  
  372.         for (int col = 0; col < MAZE_COLS; col++) {
  373.             cells[row][col] = CELL_TOP | CELL_BOTTOM | CELL_LEFT | CELL_RIGHT;
  374.         }
  375.     }
  376.  
  377. }
  378.  
  379.  
  380. /*
  381. * Adds a cell location onto the stack
  382. * @param stack - the location stack
  383. * @param location - row and col of a maze cell
  384. * @param stackPoint - last location added to the stack
  385. * @return int - new stack pointer
  386. */
  387. int pushStack(int stack[][2], int location[], int stackPoint) {
  388.     int spNew = stackPoint;
  389.  
  390.     spNew++;                    // move sp up the stack
  391.     copyOneLocTwo(location, stack[spNew]);
  392.  
  393.     return spNew;
  394.  
  395. }
  396.  
  397.  
  398. /*
  399. * Pull a cell location off the stack
  400. * @param stack - the location stack
  401. * @param location - row and col of a maze cell
  402. * @param stackPoint - last location added to the stack and return new
  403. */
  404. void popStack(int stack[][2], int location[], int& stackPoint) {
  405.  
  406.     copyOneLocTwo(stack[stackPoint], location);
  407.     stackPoint--;
  408.  
  409.  
  410. }
  411.  
  412.  
  413. /*
  414. * Copies the contents of one location to another
  415. * @param locOne - one location
  416. * @param locTwo - another location
  417. */
  418. void copyOneLocTwo(int locOne[], int locTwo[]) {
  419.  
  420.     locTwo[CELL_ROW_INDEX] = locOne[CELL_ROW_INDEX];
  421.     locTwo[CELL_COL_INDEX] = locOne[CELL_COL_INDEX];
  422. }
  423.  
  424.  
  425. /**
  426. * Printing the maze to the console
  427. * @param cells - the grid of cells in the maze
  428. */
  429. void printMaze(BYTE cells[][MAZE_COLS]) {
  430.  
  431.     for (int row = 0; row < MAZE_ROWS; row++) {
  432.  
  433.         // print the top row of the cells
  434.         for (int col = 0; col < MAZE_COLS; col++) {
  435.  
  436.             /*** print left spacer ***/
  437.  
  438.             // are we on the top row
  439.             if (row == 0) {
  440.  
  441.                 // are we on the left wall
  442.                 if (col == 0) {
  443.  
  444.  
  445.  
  446.                     cout << OUT_TOP_LEFT;
  447.                 }
  448.                 else {
  449.                     cout << OUT_TOP_MID;
  450.                 }
  451.  
  452.             }
  453.  
  454.             else { // not on top row
  455.  
  456.                    // are we on the left wall
  457.                 if (col == 0) {
  458.  
  459.  
  460.  
  461.                     cout << OUT_SIDE_LEFT;
  462.                 }
  463.                 else {
  464.                     cout << INSIDE_MIDDLE;
  465.                 }
  466.  
  467.             }
  468.  
  469.             // print top left spacer
  470.  
  471.             /*** print cell top ***/
  472.  
  473.             if (cells[row][col] & CELL_TOP) {
  474.                 cout << CELL_TOP_BOT;
  475.             }
  476.             else {
  477.                 cout << CELL_OPEN_HORZ;
  478.             }
  479.  
  480.             // print last right spacer
  481.             if (col == MAZE_COLS - 1) {
  482.  
  483.                 //top row
  484.                 if (row == 0) {
  485.                     cout << OUT_TOP_RIGHT;
  486.                 }
  487.                 else { // not top row
  488.                     cout << OUT_SIDE_RIGHT;
  489.                 }
  490.             }
  491.  
  492.  
  493.         } //print top row
  494.  
  495.           // move down to start printing side walls
  496.         cout << endl;
  497.  
  498.         // print side walls of the cells
  499.         for (int col = 0; col < MAZE_COLS; col++) {
  500.  
  501.             // prints cell left side wall
  502.             if (cells[row][col] & CELL_LEFT) {
  503.                 cout << CELL_LEFT_RIGHT;
  504.  
  505.             }
  506.             else {
  507.                 cout << CELL_OPEN_VERT;
  508.             }
  509.  
  510.             // print cell visited
  511.             if (cells[row][col] & CELL_VISITED) {
  512.                 cout << CELL_VISITIED_ON;
  513.  
  514.             }
  515.             else {
  516.                 cout << CELL_VISITIED_OFF;
  517.             }
  518.  
  519.             // print right wall
  520.             if (col == MAZE_COLS - 1) {
  521.  
  522.                 // prints cell right side wall
  523.                 if (cells[row][col] & CELL_RIGHT) {
  524.                     cout << CELL_LEFT_RIGHT;
  525.  
  526.                 }
  527.                 else {
  528.                     cout << CELL_OPEN_VERT;
  529.                 }
  530.             }
  531.  
  532.  
  533.         } // print side walls
  534.  
  535.           // move down to start printing next top walls
  536.         cout << endl;
  537.  
  538.         // print bottom row
  539.         if (row == MAZE_ROWS - 1) {
  540.  
  541.             // print the bottom row of the cell walls
  542.             for (int col = 0; col < MAZE_COLS; col++) {
  543.  
  544.                 // print spacer
  545.                 if (col == 0) {
  546.                     cout << OUT_BOT_LEFT;
  547.                 }
  548.                 else {
  549.                     cout << OUT_BOT_MID;
  550.                 }
  551.  
  552.                 // print cell bottom wall
  553.                 if (cells[row][col] & CELL_BOTTOM) {
  554.                     cout << CELL_TOP_BOT;
  555.                 }
  556.                 else {
  557.                     cout << CELL_OPEN_HORZ;
  558.                 }
  559.  
  560.                 // print right corner
  561.                 if (col == MAZE_COLS - 1) {
  562.                     cout << OUT_BOT_RIGHT;
  563.                 }
  564.  
  565.             } // bottom walls
  566.  
  567.  
  568.               // end the cells
  569.             cout << endl;
  570.  
  571.         } // bottom row
  572.  
  573.  
  574.     } // end row loop
  575.  
  576. } // end printMaze
  577.  
  578.  
  579.  
  580.   /**
  581.   * Printing the maze call values to the console
  582.   * @param cells - the grid of cells in the maze
  583.   */
  584. void printMazeDebug(BYTE cells[][MAZE_COLS]) {
  585.  
  586.     for (int row = 0; row < MAZE_ROWS; row++) {
  587.  
  588.         for (int col = 0; col < MAZE_COLS; col++) {
  589.  
  590.             cout << to_string(int(cells[row][col])) << " ";
  591.         }
  592.  
  593.         cout << endl;
  594.     }
  595.  
  596. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement