Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <cassert>
- #include <queue>
- #include <stack>
- #include <string>
- using namespace std;
- class Coord
- {
- public:
- Coord(int r, int c) : m_row(r), m_col(c) {}
- int r() const { return m_row; }
- int c() const { return m_col; }
- private:
- int m_row;
- int m_col;
- };
- // Returns true if a path exists from (starting_row, starting_col) to (ending_row, ending_col)
- bool pathExists(string maze[], int number_of_rows, int number_of_cols, int starting_row, int starting_col, int ending_row, int ending_col)
- {
- // Initialize a Queue of Coordinates
- queue<Coord> queue_of_coordinates;
- // Push the Queue by putting in the starting row and starting col
- // Assignment instructions that starting point is always going to be a "." and not a wall
- queue_of_coordinates.push(Coord(starting_row, starting_col));
- // The maze is an array of strings
- // While we have only defined the rows of the string, the "columns" of the string are implict because they are each of the individual characters of the string
- // We will overwrite that as D to mark it as discovered
- maze[starting_row][starting_col] = 'D';
- while (!queue_of_coordinates.empty())
- {
- // Pop the queue by taking the coordinate in queue and popping it
- // Different from stack because stack pops the most recent item whereas queue pops the item that has been there the longest
- Coord current = queue_of_coordinates.front();
- queue_of_coordinates.pop();
- const int current_row = current.r();
- const int current_col = current.c();
- if (current_row == ending_row && current_col == ending_col)
- return true;
- // Remember to use IF statements for the following, not else if statements
- // You need to put each and every possible point on the stack
- // First, check EAST, which is (r, c+1)
- if (maze[current_row][current_col + 1] == '.')
- {
- queue_of_coordinates.push(Coord(current_row, current_col + 1));
- maze[current_row][current_col + 1] = 'D';
- }
- // Second, check NORTH, which is (r-1, c)
- if (maze[current_row - 1][current_col] == '.')
- {
- queue_of_coordinates.push(Coord(current_row - 1, current_col));
- maze[current_row - 1][current_col] = 'D';
- }
- // Third, check WEST, which is (r, c-1)
- if (maze[current_row][current_col - 1] == '.')
- {
- queue_of_coordinates.push(Coord(current_row, current_col - 1));
- maze[current_row][current_col - 1] = 'D';
- }
- // Finally, check SOUTH, which is (r+1, c)
- if (maze[current_row + 1][current_col] == '.')
- {
- queue_of_coordinates.push(Coord(current_row + 1, current_col));
- maze[current_row + 1][current_col] = 'D';
- }
- }
- return false;
- }
- void printMaze(string maze[], int number_of_rows, int number_of_cols)
- {
- for (int i = 0; i < number_of_rows; i++)
- {
- for (int j = 0; j < number_of_cols; j++)
- {
- cout << maze[i][j];
- }
- cout << endl;
- }
- cout << endl;
- }
- bool mapDirections(string maze[], const int number_of_rows, const int number_of_cols, const int starting_row, const int starting_col, const int ending_row, const int ending_col)
- {
- /*
- * Psuedo Code Approach:
- * First run to check if the path even exists
- * Checking if the path exists marks each discoverable area as a D
- *
- * For this approach because we are checking individual paths, we will use a stack
- * We'll mark each point we retrace as R
- * Instead of popping coordinates whenever checking them at the top, we will keep them in the stack and only pop them when they lead nowhere
- * Instead of putting each direction possible on the stack, we will try pushing a single direction individually on the stack
- * If that single direction leads nowhere, we will mark it as N and then try the other directions
- *
- * We will denote a spot leading nowhere if there is no possible D to travel to that brings you to the start
- *
- * My intuition is to start from the end and go to the beginning because there are less paths to check initially
- */
- // If a path exists, but it's because you do nothing, simply say do nothing
- if (starting_row == ending_row && starting_col == ending_col)
- {
- cout << "There are no directions because the start point is the same as the end point." << endl;
- return true;
- }
- pathExists(maze, number_of_rows, number_of_cols, starting_row, starting_col, ending_row, ending_col);
- if (maze[ending_row][ending_col] != 'D')
- return false;
- stack<Coord> stack_of_retraced_coords;
- stack_of_retraced_coords.push(Coord(ending_row, ending_col));
- // Instead of popping coordinates after checking the top, we will actually keep them in the stack
- // We will pop coordinates when we reach a dead end or reach the beginning
- while (!stack_of_retraced_coords.empty())
- {
- Coord current = stack_of_retraced_coords.top();
- const int current_row = current.r();
- const int current_col = current.c();
- if (current_row == starting_row && current_col == starting_col)
- break;
- maze[current_row][current_col] = 'R';
- // Need to make sure that we actually are moving even if it isn't a dead end
- int has_moved = 0;
- // First, check EAST, which is (r, c+1)
- if (maze[current_row][current_col + 1] == 'D')
- {
- stack_of_retraced_coords.push(Coord(current_row, current_col + 1));
- maze[current_row][current_col + 1] = 'R';
- has_moved++;
- }
- // Second, check NORTH, which is (r-1, c)
- else if (maze[current_row - 1][current_col] == 'D')
- {
- stack_of_retraced_coords.push(Coord(current_row - 1, current_col));
- maze[current_row - 1][current_col] = 'R';
- has_moved++;
- }
- // Third, check WEST, which is (r, c-1)
- else if (maze[current_row][current_col - 1] == 'D')
- {
- stack_of_retraced_coords.push(Coord(current_row, current_col - 1));
- maze[current_row][current_col - 1] = 'R';
- has_moved++;
- }
- // Last, check SOUTH, which is (r+1, c)
- else if (maze[current_row + 1][current_col] == 'D')
- {
- stack_of_retraced_coords.push(Coord(current_row + 1, current_col));
- maze[current_row + 1][current_col] = 'R';
- has_moved++;
- }
- if (has_moved == 0)
- {
- maze[current_row][current_col] = 'N';
- stack_of_retraced_coords.pop();
- }
- }
- return true;
- }
- void verbalizeDirections(string maze[], int number_of_rows, int number_of_cols, int starting_row, int starting_col, int ending_row, int ending_col)
- {
- if (maze[ending_row][ending_col] != 'R')
- {
- cout << "Path is not solvable";
- return;
- }
- if (starting_row == ending_row && starting_col == ending_col)
- {
- cout << "There are no directions because the start point is the same as the end point." << endl;
- return;
- }
- cout << "Path is solvable, writing directions now: " << endl;
- int current_row = starting_row;
- int current_col = starting_col;
- // W denotes has walked
- maze[current_row][current_col] = 'W';
- // !(a&&b) represents a NAND gate, meaning it only returns false if both A and B are true
- while (!(current_row == ending_row && current_col == ending_col))
- {
- if (maze[current_row][current_col + 1] == 'R')
- {
- maze[current_row][current_col + 1] = 'W';
- cout << "Walk to the East one space." << endl;
- current_col = current_col + 1;
- }
- // Second, check NORTH, which is (r-1, c)
- else if (maze[current_row - 1][current_col] == 'R')
- {
- maze[current_row - 1][current_col] = 'W';
- cout << "Walk to the North one space." << endl;
- current_row = current_row - 1;
- }
- // Third, check WEST, which is (r, c-1)
- else if (maze[current_row][current_col - 1] == 'R')
- {
- maze[current_row][current_col - 1] = 'W';
- cout << "Walk to the West one space." << endl;
- current_col = current_col - 1;
- }
- // Last, check SOUTH, which is (r+1, c)
- else if (maze[current_row + 1][current_col] == 'R')
- {
- maze[current_row + 1][current_col] = 'W';
- cout << "Walk to the South one space." << endl;
- current_row = current_row + 1;
- }
- }
- cout << "You have arrived at the end. " << endl;
- }
- void findDirections(string maze[], int number_of_rows, int number_of_cols, int starting_row, int starting_col, int ending_row, int ending_col)
- {
- if (starting_row == ending_row && starting_col == ending_col)
- {
- cout << "There are no directions because the start is the same as the end" << endl;
- return;
- }
- pathExists(maze, number_of_rows, number_of_cols, starting_row, starting_col, ending_row, ending_col);
- if (maze[ending_row][ending_col] != 'D')
- {
- cout << "There are no directions because the maze is unsolvable";
- return;
- }
- mapDirections(maze, number_of_rows, number_of_cols, starting_row, starting_col, ending_row, ending_col);
- verbalizeDirections(maze, number_of_rows, number_of_cols, starting_row, starting_col, ending_row, ending_col);
- }
- int main()
- {
- string maze1[10] = {
- "XXXXXXXXXX",
- "X.X..X...X",
- "X.XX.X.XXX",
- "X....X.X.X",
- "XX.X.X...X",
- "XXX..X.X.X",
- "X...X...XX",
- "X.XX..X.XX",
- "X....X...X",
- "XXXXXXXXXX",
- };
- string maze2[10] = {
- "XXXXXXXXXX",
- "X.X..X...X",
- "XXXX.X.XXX",
- "X....X.X.X",
- "XX.X.X...X",
- "XXX..X.X.X",
- "X...X...XX",
- "X.XX..X.XX",
- "X....X...X",
- "XXXXXXXXXX",
- };
- string maze3[10] = {
- "XXXXXXXXXX",
- "XX.....XXX",
- "X..XX....X",
- "X...X...XX",
- "X.X.XXX..X",
- "XXXX..X..X",
- "XX....X..X",
- "X.......XX",
- "X..XXXXXXX",
- "XXXXXXXXXX",
- };
- string maze4[10] = {
- "XXXXXXXXXX",
- "XX.....XXX",
- "X..XX....X",
- "X...X...XX",
- "X.X.XXX..X",
- "XXXX..X..X",
- "XX....X..X",
- "X.X.....XX",
- "X..XXXXXXX",
- "XXXXXXXXXX",
- };
- string maze5[6] = {
- "XXXXXX",
- "XX.XXX",
- "XX.XXX",
- "X...XX",
- "XX.XXX",
- "XXXXXX",
- };
- string maze6[10] = {
- "XXXXXXXXXX",
- "X.XXXXXXXX",
- "X...XXXX.X",
- "X.XXXXXX.X",
- "X.XXXXXX.X",
- "X.XXXXXX.X",
- "X.XXXXXX.X",
- "X.XXXXXX.X",
- "X........X",
- "XXXXXXXXXX",
- };
- string maze7[10] = {
- "XXXXXXXXXX",
- "X....X...X",
- "X.XX.XX..X",
- "XXX....X.X",
- "X.XXX.XXXX",
- "X.X...X..X",
- "X...X.X..X",
- "XXXXX.X.XX",
- "X........X",
- "XXXXXXXXXX" };
- cout << "Maze 5" << endl;
- pathExists(maze5, 6, 6, 4, 2, 1, 2);
- printMaze(maze5, 6, 6);
- mapDirections(maze5, 6, 6, 4, 2, 1, 2);
- printMaze(maze5, 6, 6);
- verbalizeDirections(maze5, 6, 6, 4, 2, 1, 2);
- cout << "Maze 1" << endl;
- pathExists(maze1, 10, 10, 8, 6, 1, 1);
- printMaze(maze1, 10, 10);
- mapDirections(maze1, 10, 10, 8, 6, 1, 1);
- printMaze(maze1, 10, 10);
- verbalizeDirections(maze1, 10, 10, 8, 6, 1, 1);
- cout << "Maze 6" << endl;
- pathExists(maze6, 10, 10, 8, 8, 1, 1);
- printMaze(maze6, 10, 10);
- mapDirections(maze6, 10, 10, 8, 8, 1, 1);
- printMaze(maze6, 10, 10);
- verbalizeDirections(maze6, 10, 10, 8, 8, 1, 1);
- cout << "Maze 3" << endl;
- pathExists(maze3, 10, 10, 4, 3, 7, 1);
- printMaze(maze3, 10, 10);
- mapDirections(maze3, 10, 10, 4, 3, 7, 1);
- printMaze(maze3, 10, 10);
- verbalizeDirections(maze3, 10, 10, 4, 3, 7, 1);
- cout << "Maze 7" << endl;
- pathExists(maze7, 10, 10, 3, 5, 8, 8);
- printMaze(maze7, 10, 10);
- findDirections(maze7, 10, 10, 3, 5, 8, 8);
- printMaze(maze7, 10, 10);
- cout << "Maze 2" << endl;
- pathExists(maze2, 10, 10, 1, 1, 1, 3);
- findDirections(maze2, 10, 10, 1, 1, 1, 3);
- cout << endl;
- cout << "Maze 2" << endl;
- pathExists(maze2, 10, 10, 1, 1, 1, 3);
- findDirections(maze2, 10, 10, 1, 1, 1, 1);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement