Algorithms for 3D Mazes [closed]
Asked Answered
C

3

6

Are there algorithms to produce 3 dimensional mazes? Essentially the same as a 2D maze but the Z depth axis can be traversed? The idea is still the same though, to get from Start to End. Could backtracking still be used?

Which algorithm should I use to generate a 3D maze?

See here. I mean that you can go into the cube too, not just iterate the faces of it.

Camelot answered 10/12, 2011 at 0:15 Comment(7)
Do you want one that solves a maze, or generates a maze?Existent
you could create a 2d maze on a grid and to make it 3d every grid cell would instead be a box with a "height"Per
I do not just want a raised maze.Camelot
When you say 3D maze, are you talking about one where you can go up and down stairs/ladders to different "layers" like the one on the right side of this page?Obloquy
maybe you could explain more about what type of maze you're trying to create?Per
3D maze is just layered 2D maze, with some intersection points, where you can move on the z axis.Tush
For [2D/3D] mazes, I would recommend using Kruskal's algorithm. DFS is too easy, and Prim is too... weird. 2D Demo.Lecky
B
8

I made 2d mazes a few years ago using Kruskal's Algorithm here. There should be no reason this couldn't work with the 3d case you described. Basically you'd consider a cell a cube, and have a large array that has (for every cells), 6 walls in the +/- x, y, and z directions. The algorithm initially starts with all walls everywhere and randomly makes walls disappear until every cell in the maze is connected.

B answered 10/12, 2011 at 0:35 Comment(3)
+1 For Kruskal's algorithm. :)Lecky
I like the basic idea, but perhaps the goal should not be merely having every cell in the maze connected, but rather that in addition the connections should be loop-free (a "tree" in graph theory terminology). That would force the solution to the maze to be unique. This requires that some random choices for (intermal) walls to disappear would be rejected, whenever they would introduce loops in the connections. Equivalently these "rejected" choices are ones that do not reduce the number of connected components in the graph.Mantra
hardmath; Kruskal's algorithm takes care of this. I didn't really explain this with my oversimplified explanation. Basically, a wall will get deleted only if it connected 2 new regions. It does this by checking if both cells on each side of the wall belong to a distinct set. This can be done really efficiently with a Disjoint-set data structure. The Wikipedia link explains it better.B
E
0

I have the code for generating a 2D maze in, of all things, RPGLE (something I did as a self-exercise while learning the language). Because of the way I wrote it, about the only changes necessary for the general alogrithm would be to add the Z dimension as an additional dimension...

The entire thing is 20 pages long (although this includes input/output), so here's some code. You should be able to translate this into whatever language you need: I translated it from spaghetti-code BASIC (gotos were way overused here, yeah. But it was a fun exercise).

//set out maximum maze size
maximumMazeSquareCounter = mazeHorizontalSize * mazeVerticalSize + 1;
// generate a starting horizontal positiongetRandomNumber(seed : randomNumber);
currentHorizontalPosition = %inth(randomNumber * (mazeHorizontalSize - 1)) + 1;
currentVerticalPosition = 1;
mazeSquareCounter = 1;
// generate the top row of the maze (with entrance)
mazeTopRow = generateEntrance(currentHorizontalPosition);
//write to the printer file
writeMazeDataLine(mazeTopRow);
mazeSquareCounter += 1;
//set the first position in the maze(the entry square
setPathPoint(currentHorizontalPosition : currentVerticalPosition);
//do until we've reached every square in the maze
dou mazeSquareCounter >= maximumMazeSquareCounter;
//get the next available random direction
mazeDirection = getNextRandomDirection(getNextAvailableDirection(currentHorizontalPosition : currentVerticalPosition));
//select what to do by the returned results
select;
//when FALSE is returned - when the maze is trapped
when mazeDirection = FALSE;
//if not at the horizontal end of the maze
if currentHorizontalPosition <> mazeHorizontalSize;
//add one to the position
currentHorizontalPosition += 1;
//else if not at the vertical end of the maze
elseif currentVerticalPosition <> mazeVerticalSize;
//reset the horizontal position
currentHorizontalPosition = 1;
//increment the vertical position
currentVerticalPosition += 1;
//otherwise
else;
//reset both positions
currentHorizontalPosition = 1;
currentVerticalPosition = 1;
endif;
//when 'N' is returned - going up (other directions removed)
when mazeDirection = GOING_NORTH;
//set the point above current as visited
setPathPoint(currentHorizontalPosition : currentVerticalPosition - 1);
//set the wall point to allow passage
setWallDirection(currentHorizontalPosition : currentVerticalPosition : GOING_NORTH);
//change the position variable to reflect change
currentVerticalPosition -= 1;
//increment square counter
mazeSquareCounter += 1;
endsl;
enddo;
//generate a random exit
// get a random number
getRandomNumber(seed : randomNumber);
// set to the horzontal position
currentHorizontalPosition = %inth(randomNumber * (mazeHorizontalSize - 1)) + 1;
//set the vertical position
currentVerticalPosition = mazeVerticalSize;
//set wall to allow for exit
setWallDirection(currentHorizontalPosition : currentVerticalPosition : GOING_SOUTH);

The entire thing is backed by two two-dimensional arrays (well, the RPG equivalent): One for the walls that occupy the 'square', and the other for whether or not that square has been visited. The maze is created after every square has been visited. Garuanteed one-path only, worm-turns maze.

To make this three-dimensional, make it use three-dimensional arrays, and add the necessary dimension index.

Existent answered 10/12, 2011 at 0:36 Comment(0)
S
0

I designed an algorithm some time ago for 2D mazes on a square grid, there is no reason why this shouldn't also work for a 3D maze on a cubic grid.


Start with a 3D grid initially fully populated with wall cells.

...

Start an agent at an edge of the grid, the agent travels in a straight line in the X, Y, Z, -X, -Y or -Z direction clearing wall as she travels.

Action 'N' has a small chance of occurring each step.

Action 'M' occurs when the cell directly in front of the agent is wall and the cell in front of that is empty.

'N' is a random choice of:

  1. removing that agent
  2. turning left or right 90 degrees
  3. and creating an agent on the same square turned 90 degrees left, right or both (two agents).

'M' is a random choice of:

  1. removing that agent
  2. removing the wall in front of that agent and then removing that agent
  3. and doing nothing, carrying on
  4. turning left or right 90 degrees.
  5. and creating an agent on the same square turned 90 degrees left, right or both (two agents).

The mazes are distinctive, and their character is highly flexible by adjusting the trigger for 'M' (to do with valid junctions) and by also adjusting the chances of 1 to 8 occurring. You may want to remove an action or two, or introduce your own actions, for example one to make a small clearing or sidestep one step.

The trigger for 'N' can also be another sort of randomness, for example the example below can be used to create fairly branchy mazes that still have some long straight parts.

float n = 1;

while (random_0_to_1 > 0.15)
{
    n *= 1.2;
}

return (int)n;

Some small adjustments will be needed from my simple description, for example trigger for action 'M' will need to check the cells adjacent to the cells it checks as well depending on what sort of junctions are desirable.

Either 5 or 6 are needed for the maze to contain cycles and at least one alternative 'M' action to 5 and 6 is required for the maze to contain dead ends.

Some choices of chances/actions and 'M' triggers will tend to make mazes that don't work, for example are unsolvable or full of empty or wall cells, but many will produce consistently nice results.

Skittish answered 19/1, 2018 at 16:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.