5

Goal


I am making a program which generates a 3D maze and am having a bit of trouble with the creation algorithm. For ease of interaction, it will be a rectangular prism with one entrance and one exit.

Algorithm


The problem is the actual coding of the algorithm: I figured the best way to go with this is make a class called MazeBlock, which has six boolean states (up, down, left, right, in, out) which signify in which direction the maze can go next. using a 3D array of MazeBlocks, I want to fill the maze, each iteration of filling checking the blocks to the left, right, above, below, in front of, and behind it to see if there is any opening to that side to which to attach.

I already have one that will make the edges, placing random open slots toward the interior of the maze. All I have trouble with is the actual interior, ensuring that the maze has one entrance, one exit, and one solution to traverse it (I once solved a "difficult" 3D maze in a popup book by going only a few steps opposite the intended direction.

Question


As I siad, I think I have the basic idea for the algorithm, but I don't know how to code it. Can someone come up with a Java algorithm for this that accomplishes the task relatively quickly?

The solution must not use external libraries.

templatetypedef
  • 328,018
  • 92
  • 813
  • 992
Ben Leggiero
  • 25,904
  • 38
  • 161
  • 267
  • 1
    Could you please ask the question in the form of a question? – Jason S Jan 14 '11 at 00:13
  • There are many questions (and answers) to 2D maze generation. It's trivial to take the algorithms into the third dimension. See http://en.wikipedia.org/wiki/Maze_generation_algorithm. – TreDubZedd Jan 14 '11 at 15:07

1 Answers1

8

There are many maze generation algorithms that work quite well here, most of which are based on creating some sort of spanning tree in a graph of the 3D grid.

As an example, let's suppose that we have a 2D grid of cells (which I can actually render using ASCII art!) that looks like this:

*---*---*---*
|   |   |   |
*---*---*---*
|   |   |   |
*---*---*---*
|   |   |   |
*---*---*---*

We can think of this as a graph where each cell is a vertex and each of the connections between the cells is an edge. Our goal is to find some tree that connects all of the nodes. If we do this, then all cells will be reachable from one another (because a tree is connected), but there are no loops (because a tree is a minimally-connected graph). There are many different trees we could use; for example, here's one tree:

*---*---*---*
|   |   |   |
*   *   *   *
|   |   |   |
*   *   *   *
|   |   |   |
*   *   *   *

And here's another:

*   *---*   *
|   |   |   |
*---*   *   *
        |   |
*---*---*---*
    |       |
*---*   *---*

If you are looking for some sort of tree connecting the maze cells, one option would be to use a depth-first search over the graph, randomly ordering the edges that need to be visited. This strategy is a well-known maze generation algorithm and produces long, twisty mazes full of dead-ends and confusing branchings.

Another approach that's commonly used to create mazes is to reducing it to the problem of finding a minimum spanning tree of a graph. In particular, suppose you create a graph where every cell is a node with links to each of its neighbors. Choose random weights for each of the edges, and then construct a minimum spanning tree for the graph. This tree has no cycles and there's a unique path from each node to each other node, meaning that the maze has a unique solution. Moreover, the algorithm is very efficient - in a 3D cube of size n x n x n, then you have O(n3) nodes, O(n3) edges, and you can find the MST in O(n3 lg n) time using either Prim's algorithm or Kruskal's algorithm. These also produce high-quality mazes, though their properties are very different from the mazes created using the randomized depth-first search.

Hope this helps!

templatetypedef
  • 328,018
  • 92
  • 813
  • 992
  • Can you translate that into use with my MazeBlock3D objects? – Ben Leggiero Jan 14 '11 at 16:49
  • @Supuhstar- Sure! You'll probably want to update your `MazeBlock3D` type so that in addition to storing what directions are open, you store an associated cost with each direction (which should be the same, by the way, as the cost in the reverse direction!) Next, run one of the MST algorithms. A simple approach would be to use a naive version of Kruskal's algorithm. Create an array of all the links between rooms, then sort those links into ascending order by length. Next, initially mark each cell as being disconnected from all other cells. Then, continuously link together rooms that... – templatetypedef Jan 14 '11 at 18:44
  • @Supuhstar- ...are adjacent to one another in the order in which the edges appear. Whenever you link two cells together, mark those two cells, as well as all of the cells those cells are connected to, as being part of the same cluster. If you ever find an edge that would link together two cells that are already in the same cluster, skip it. You might want to check out the Kruskal's algorithm page for more info on this approach. – templatetypedef Jan 14 '11 at 18:46
  • and this will work when all the `MazeBlock3D`s are cubic and each have 1-6 openings in their sides? It just isn't clear whether you understand that they're... actually blocks – Ben Leggiero Jan 18 '11 at 03:34
  • alternatively, the `MazeBlock3D`s can be thought of as the walls, if you can imagine that. – Ben Leggiero Jan 18 '11 at 04:06