Home > Back-end >  Variables are getting switched up somewhere
Variables are getting switched up somewhere

Time:01-06

I have made a random maze generator which takes in 3 commandline arguements (Height, Width, SeedValue). The maze in itself is finished, it works most of the time, however my parameters width and height are getting switched somewhere and I cant find it. e.g. if I give the parameters 10 and 10 the width should be 10 * 5 1 = 51 and the Height should be 10 * 3 1 = 31. I now have a height of 51 and a width of 31.

Does anyone see/have any tips where these variables might get switched up?

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

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

class Maze {
    private:
        int mazeHeight;
        int mazeWidth;
        int seedValue;
        std::vector <std::vector <char>> Maze_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();
};

//Make the variables accesible
void Maze::mazeConstructor(int x, int y, int z, std::vector <std::vector <char>> vect) {
    mazeWidth = x;
    mazeHeight = y;
    seedValue = z;
    Maze_maze = vect;
}
// Initialize the walls with '#'
std::vector <std::vector <char>> Maze::initializeMaze() {
    for (unsigned int i = 0; i < Maze_maze.size(); i  ) {
        for (unsigned int j = 0; j < Maze_maze[0].size(); j  ) {
            Maze_maze[i][j] = '#';
        }
    }
    return Maze_maze;
}

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

// Make the variables accessible
void Path::pathConstructor(std::vector <std::vector <char>> Maze, int mazeWidth, int mazeHeight) {
    Grid = Maze;
    Height = mazeHeight;
    Width = mazeWidth;
}

bool Path::checkValid(int xPos, int yPos) {
  if(xPos < 0 || xPos >= Width - 1) {
      return false;
  } 
  if( yPos < 0 || yPos >= Height) {
      return false;
  }
  return true;
} 

// Find a path using recursion
void Path::carvePath(int xPos, int yPos) {
    std::random_device dev;
    std::mt19937 rng(dev());
    std::uniform_int_distribution<std::mt19937::result_type> randomNumber(0, 3);
    Grid[xPos][yPos] = ' ';
    std::vector <int> Directions (4);
    Directions[0] = North;
    Directions[1] = East;
    Directions[2] = South;
    Directions[3] = West;
    for (int i = 0; i < 4;   i) {
        int toX = 0;
        int toY = 0;
        switch (Directions[randomNumber(rng)]) {
            case North: 
                toY = -1; 
                break;
            case South: 
                toY = 1; 
                break;
            case East: 
                toX = 1; 
                break;
            case West:
                toX = -1; 
                break;
        }
        int x2 = xPos   (toX << 1);
        int y2 = yPos   (toY << 1);
        if (checkValid(x2, y2)) {
            if (Grid[x2][y2] == '#') {
                Grid[x2 - toX][y2 - toY] = ' ';
                carvePath(x2, y2);
            }
        }
    }
}



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

// Check if user input is valid
void checkUserInput(int Input1, int Input2) {
    int checkIntWidth = 0;
    int checkIntHeight = 0;
    if (!(Input1 >> checkIntWidth) || !(Input2 >> checkIntHeight)) {
        throw std::runtime_error ("Invalid input");
    }
} 

// Get command line arguements 
int main(int argc, char* argv[]) {
    Maze c1;
    Path c2;
    srand (time(0));
    int Height;
    int Width;
    int seedValue;
    Height = atoi(argv[1]);
    Width = atoi(argv[2]);
    try {
        checkUserInput(Width, Height);
    }
    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 (Width * 5   1, std::vector <char> (Height * 3   1));
    c1.mazeConstructor(Width, Height, seedValue, Maze);
    c2.pathConstructor(c1.initializeMaze(), Width * 5   1, Height * 3   1);
    c2.carvePath(1, 1);
    c2.printMaze();
}

CodePudding user response:

The most obvious thing is that you've swapped height and width in the 2d vector you create in main. Just correcting it, from

std::vector<std::vector<char>> Maze(Width * 5   1, std::vector<char>(Height * 3   1));

to

std::vector<std::vector<char>> Maze(Height * 3   1, std::vector<char>(Width * 5   1));

... will not work right out of the box though since you've multiplied Height and Width with magic numbers and you've made the same mistake in Path where you use Grid[xPos][yPos] instead of Grid[yPos][xPos]. Changing both corrects the problem you are asking about.

We're taught in school to think {x, y} but since you print row by row and that arrays in C is stored in row-major order, I suggest that you use {y, x} everywhere in your program. That makes mistakes like this less likely.

You have some other details in the program that you could fix too.

  • You copy your maze vector around. Pass it by reference.
  • Don't create the original maze in main. Let the Maze class create (and own it).
  • Path - if that class is even needed, should probably carve paths in the maze that is owned by Maze, not copy a maze from Maze.
  • The carvePath algorithm sometimes "paints itself into a corner" and fails to fill the whole maze. I would probably not use recursion for this.
  • Each time carvePath is called you create a new pseudo random number generator. I suggest that you only create one and use that for the whole program.
  • The seed the user gives is not used so you'll get different mazes with the same seed.

Also, the actual vector would be simpler with a std::string:

std::vector<std::string>(Height, std::string(Width, '#'));

You could that just print each std::string in the vector when you want to print the maze.

void Path::printMaze() {
    for(auto& row : Grid) std::cout << row << '\n';
}
  •  Tags:  
  • Related