Maze generation - recursive division (how it works?)

3.7k views Asked by At

I would like to learn how to generate a perfect maze. I am trying to understand Recursive Division Algorithm. I can't understand how to implement this algorithm. This is my code:

bool maze[20][20];

void initMaze()
{
    for(int i = 0; i < 20; i++)
        for(int j = 0; j < 20; j++)
            maze[i][j] = false;

    for(int i = 0; i < 20; i++)
        maze[0][i] = true;

    for(int i = 0; i < 20; i++)
        maze[19][i] = true;

    for(int i = 0; i < 20; i++)
        maze[i][0] = true;

    for(int i = 0; i < 20; i++)
        maze[i][19] = true;
}

int randNum(int min, int max)
{
    return rand()%(max-min+1)+min;
}

void drawVWall(int minY, int maxY, int x)
{
   int passage = randNum(minY, maxY);

    for(int i = minY; i <= maxY; i++)
        if(i != passage)
            maze[i][x] = true;
}

void drawHWall(int minX, int maxX, int y)
{
    int passage = randNum(minX, maxX);

    for(int i = minX; i <= maxX; i++)
        if(i != passage)
            maze[y][i] = true;
}

void divison(int x, int y, int maxx, int maxy, int h)
{
    if(h)
    {
        if(maxx <= 2)
            return;

        int wallY = randNum(y, maxy);
        drawHWall(x, maxx, wallY);

        if(wallY < maxy - wallY)
            divison(x, wallY, maxx, maxy, !h);
        else if(wallY > maxy - wallY)
            divison(x, y, maxx, wallY, !h);
    }
    else
    {
        if(maxy <= 2)
            return;

        int wallX = randNum(x, maxx);
        drawVWall(y, maxy, wallX);

        if(wallX < maxx - wallX)
            divison(wallX, y, maxx, maxy, !h);
        else if(wallX > maxx - wallX)
            divison(x, y, wallX, maxy, !h);
    }
}

initMaze();
divison(2, 2, 18, 18, true);

There is something wrong with this code, because it often freezes the program (infinite loop somewhere), but if it works it generates a 'maze' like this: Generated 'maze'

I don't want to ask you about my code. I just want to understand how to implement this algorithm, where am I wrong and what I should do. I need to generate a perfect maze without closed areas.

1

There are 1 answers

1
M Oehm On

First you must decide how you design your maze. You use whole cells to represent walls or passages. That means that you have some restrictions on the numbers you pick as new walls and passages. The thick walls in your example, where two vertical walls are adjacent without passage between them shouldn't be created.

With your method, an N × N maze is represented by an array of (2*N + 1) × (2*N + 1). You have the "maze" coordinates 0 to N and the "grid" coordinates 0 to 2*N + 1. Do the algorithm in maze coordinates and use grid coordinates when you create the walls.

In grid coordinates, walls must be at even indices and corridord must be at odd indices. Both indices even is always a wall in the final maze and both indices odd is always a free cell. One even one odd means a possible passage through a wall.

To illustrate, here's a4×4 maze:

 X    0   1   2   3

 x  0 1 2 3 4 5 6 7 8

    # # # # # # # # #   0
    #   +   +   +   #   1  0
    # + # + # + # # #   2
    #   +   +   +   #   3  1
    # + # + # + # # #   4
    #   +   +   +   #   5  2
    # + # + # + # # #   6
    #   +   +   +   #   7  3
    # # # # # # # # #   8

                        y  Y

Small letters(x, y) are the grid coordinates; capital letters (X, Y) are the maze coordinates. The hash marks # are always walls, but the plusses + end up being either passages or walls.

The second problem is the recursion itself. When you have built a wall, you have subdivided the active space into two regions. You must now apply the algorithm to both new regions.

So instead of:

    if (wallY < maxy - wallY)
        divison(x, wallY, maxx, maxy, !h);
    else if (wallY > maxy - wallY)
        divison(x, y, maxx, wallY, !h);

you should do something like this:

    divison(x, wallY, maxx, maxy, !h);
    divison(x, y, maxx, wallY, !h);

Of course you must have a condition to stop your recursion, but you have that already: You don't build further walls when the space is too small.

The big rooms in your example show that you have only recursed into one new subsection of the maze. The big rooms are the ones you didn't recurse into.