'Check if the position is a valid cell in a maze

I am trying to make a maze. The walls consist of '#' and I want to make a path from top left to bottom right using '.'. I have come this far, However when I run it now I get a segmentation fault and nothing happens. Anyone know what I am doing wrong? I think my problems lie with my recursive function. Be my guest to edit it! Thanks in advance! :D

#include <iostream>
#include <vector>
#include <stack>
#include <sstream>
#include <time.h>

#define North 0
#define East 1
#define South 2
#define West 3

class Maze {
    private:
        int mazeHeight;
        int mazeWidth;
        int seedValue;
        std::vector <std::vector <char>> Maze;
    public:
        void checkuserInput(int Input1, int Input2);
        void mazeConstructor(int x, int y, int z, std::vector <std::vector <char>> vect);
        std::vector <std::vector <char>> initializeMaze();
};

class Path {
    private:
        std::vector <std::vector <char>> Grid;
        bool visited;
        int Height;
        int Width;
    public:
        void pathConstructor(std::vector <std::vector <char>> Maze, int mazeHeight, int mazeWidth);
        bool checkValid(int yPos, int xPos);
        void findPath(int yPos, int xPos);
        void printMaze();
};

// Check if user input is valid
void checkUserInput(int Input1, int Input2) {
    int Height;
    int Width;
    if (!(Input1 >> Height)) {
        throw std::runtime_error ("Invalid input");
    }
    if (!(Input2 >> Height)) {
        throw std::runtime_error ("Invalid input");
    }
} 
//Make the variables accesible
void Maze::mazeConstructor(int x, int y, int z, std::vector <std::vector <char>> vect) {
    mazeHeight = x;
    mazeWidth = y;
    seedValue = z;
    Maze = vect;
}
// Initialize the outer walls with '#'
std::vector <std::vector <char>> Maze::initializeMaze() {
    for (int i = 0; i < mazeWidth; i++) {
        for (int j = 0; j < mazeHeight; j++) {
            Maze[i][j] = '#';
        }
    }
    return Maze;
}
// Make the variables accessible
void Path::pathConstructor(std::vector <std::vector <char>> Maze, int mazeHeight, int mazeWidth) {
    Grid = Maze;
    Height = mazeHeight;
    Width = mazeWidth;
}

bool Path::checkValid(int yPos, int xPos) {
  if(xPos >= Width || xPos < 0) {
      return false;
  } 
  if(yPos >= Height || yPos < 0) {
      return false;
  }
  if (Grid[xPos][yPos] == '#') {
     return false;
  }
  return true;
} 

// Find a path using recursion
void Path::findPath(int yPos, int xPos) {
    if (yPos == Height || xPos == Width) {
        printMaze();
    }
    else {
        Grid[yPos][xPos] = '.';
        int randomNumber = rand() % 3; 
        switch (randomNumber) {
            case South:
                if (checkValid(yPos, xPos)) {
                findPath(yPos + 1, xPos);
                }
                else {
                    findPath(yPos, xPos);
                }
            case East:
                if (checkValid(yPos, xPos)) {
                findPath(yPos, xPos + 1);
                }
                else {
                    findPath(yPos, xPos);
                }
            case North:
                if (checkValid(yPos, xPos)) {
                findPath(yPos - 1, xPos); 
                }
                else {
                    findPath(yPos, xPos);
                }
            case West:
                if (checkValid(yPos, xPos)) {
                findPath(yPos, xPos - 1); 
                }
                else {
                    findPath(yPos, xPos);
                } 
        }   
    }
} 

// Output the maze
void Path::printMaze() {
    for (int i = 0; i < Grid.size(); i++) {
        for (int j = 0; j < Grid[0].size(); j++) {
            std::cout << Grid[i][j];
        }
        std::cout << std::endl;
    }
}

// Get command line arguments 
int main(int argc, char* argv[]) {
    Maze maze;
    Path Path;
    srand (time(0));
    int Height;
    int Width;
    int seedValue;
    Height = atoi(argv[2]);
    Width = atoi(argv[2]);
    try {
        checkUserInput(Height, Width);
    }
    catch(std::runtime_error& e) {
        std::cerr << e.what() << std::endl;
        return 1;
    }
    if (argc > 3) {
        seedValue = atoi(argv[3]);
    } else {
        seedValue = rand();
    }
    std::vector <std::vector <char>> Maze (Height * 3 + 1, std::vector <char> (Width * 5 + 1, ' '));
    maze.mazeConstructor(Height, Width, seedValue, Maze);
    Path.pathConstructor(maze.initializeMaze(), Height, Width);
    Path.printMaze();
    Path.findPath(1, 1);
}```


Solution 1:[1]

If I understand the question correctly, you just need to check if the position is within the bounds of the maze and that it's a valid "cell".

To check for the validity of the cell, just compare the character you're storing against whatever it is you're using as empty.

To check the position is inside the maze, all you need to do is ensure the y value and x value are within the range [0, mazeHeight) and [0, mazeWidth) respectively. A simple pseudocode function might be this:

function checkValid(yPos, xPos)
    // Check that yPos is valid
    if yPos < 0 or yPos >= mazeHeight
        return false

    // Check that xPos is valid
    if xPos < 0 or xPos >= mazeWidth
        return false

    // At this point, you know the location is inside the maze
    // so just check it's an empty square
    return Maze[yPos][xPos] == ' ' // Assuming ' ' is empty

Hopefully this helps!

====================== EDIT ======================

Just a couple extra points about your code:

In your findPath function, you're using rand() % 3 when there are 4 possible outcomes (0, 1, 2, 3). rand() % 3 will wrap at 3, so you'll get something like this: [0, 1, 2, 0, 1, 2, 0, ...] if rand() were to generate [1, 2, 3, 4, ....]

Reading your code more carefully, I believe checkUserInput is the issue. You are comparing (want to be comparing) the inputs against the width and height -- this is not what the code is doing:

// Check if user input is valid
void checkUserInput(int Input1, int Input2) {
    int Height; // Create a variable called height -- no initial value
    int Width; // Create a variable called width-- no initial value
    if (!(Input1 >> Height)) { // ???? -- See below
        throw std::runtime_error ("Invalid input");
    }
    if (!(Input2 >> Height)) { // Again, see below
        throw std::runtime_error ("Invalid input");
    }
} 

To check the value, you're using the following condition: !(Input1 >> Height). What I believe you want to do is Input1 <= Height. The operator >> is not a greater than operation, it's a bit-wise left-shift, which results in you halving the number. (Also, generally speaking you should just use less than or equal (<=) instead of inverting the output of greater than

The cause of the segfault, however, is the uninitialized variables. C++ has created a little pocket of memory for them within your program, but has not yet filled that space with something meaningful. You need to set the variable to something (initialize it) with the = operator.

How you choose to fix this is up to you, but I would suggest just using the mazeHeight and mazeWidth member variables in the class

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1