Open main menu
Home
Random
Recent changes
Special pages
Community portal
Preferences
About Wikipedia
Disclaimers
Incubator escapee wiki
Search
User menu
Talk
Dark mode
Contributions
Create account
Log in
Editing
Maze generation algorithm
(section)
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
== Graph theory based methods == [[File:Graph based maze animation.gif|thumb|Animation of graph theory based method (randomized depth-first search)]] A maze can be generated by starting with a predetermined arrangement of cells (most commonly a rectangular grid but other arrangements are possible) with wall sites between them. This predetermined arrangement can be considered as a [[connected graph]] with the edges representing possible wall sites and the nodes representing cells. The purpose of the maze generation algorithm can then be considered to be making a subgraph in which it is challenging to find a route between two particular nodes. If the subgraph is not [[connected graph|connected]], then there are regions of the graph that are wasted because they do not contribute to the search space. If the graph contains loops, then there may be multiple paths between the chosen nodes. Because of this, maze generation is often approached as generating a random [[spanning tree (mathematics)|spanning tree]]. Loops, which can confound naive maze solvers, may be introduced by adding random edges to the result during the course of the algorithm. The animation shows the maze generation steps for a graph that is not on a rectangular grid. First, the computer creates a random [[planar graph]] G shown in blue, and its [[Dual graph|dual]] F shown in yellow. Second, the computer traverses F using a chosen algorithm, such as a depth-first search, coloring the path red. During the traversal, whenever a red edge crosses over a blue edge, the blue edge is removed. Finally, when all vertices of F have been visited, F is erased and two edges from G, one for the entrance and one for the exit, are removed. === Randomized depth-first search === [[File:Depth-First Search Animation.ogv|thumb|right|Animation of generator using depth-first search]] [[File:Depth-First Search Animation-2.gif|thumb|A different animation of a generator using depth-first search]] This algorithm, also known as the "recursive backtracker" algorithm, is a randomized version of the [[depth-first search]] algorithm. Frequently implemented with a [[Stack (abstract data type)|stack]], this approach is one of the simplest ways to generate a maze using a computer. Consider the space for a maze being a large grid of cells (like a large chess board), each cell starting with four walls. Starting from a random cell, the computer then selects a random neighbouring cell that has not yet been visited. The computer removes the wall between the two cells and marks the new cell as visited, and adds it to the stack to facilitate backtracking. The computer continues this process, with a cell that has no unvisited neighbours being considered a dead-end. When at a dead-end it backtracks through the path until it reaches a cell with an unvisited neighbour, continuing the path generation by visiting this new, unvisited cell (creating a new junction). This process continues until every cell has been visited, causing the computer to backtrack all the way back to the beginning cell. We can be sure every cell is visited. As given above this algorithm involves deep recursion which may cause stack overflow issues on some computer architectures. The algorithm can be rearranged into a loop by storing backtracking information in the maze itself. This also provides a quick way to display a solution, by starting at any given point and backtracking to the beginning. [[File:Horizontally Influenced Depth-First Search Generated Maze.png|thumb|right|Horizontal Passage Bias]] Mazes generated with a depth-first search have a low branching factor and contain many long corridors, because the algorithm explores as far as possible along each branch before backtracking. ==== Recursive implementation ==== [[File:Hexamaze.webm|thumb|Randomized depth-first search on a hexagonal grid]] The [[depth-first search]] algorithm of maze generation is frequently implemented using [[backtracking]]. This can be described with a following [[recursion (computer science)|recursive]] routine: # Given a current cell as a parameter # Mark the current cell as visited # While the current cell has any unvisited neighbour cells ## Choose one of the unvisited neighbours ## Remove the wall between the current cell and the chosen cell ## Invoke the routine recursively for the chosen cell which is invoked once for any initial cell in the area. ==== Iterative implementation (with stack) ==== A disadvantage of the first approach is a large depth of [[recursion]] – in the worst case, the routine may need to recur on every cell of the area being processed, which may exceed the maximum recursion stack depth in many environments. As a solution, the same backtracking method can be implemented with an explicit [[stack (abstract data type)|stack]], which is usually allowed to grow much bigger with no harm. # Choose the initial cell, mark it as visited and push it to the stack # While the stack is not empty ## Pop a cell from the stack and make it a current cell ## If the current cell has any neighbours which have not been visited ### Push the current cell to the stack ### Choose one of the unvisited neighbours ### Remove the wall between the current cell and the chosen cell ### Mark the chosen cell as visited and push it to the stack === Iterative randomized Kruskal's algorithm (with sets) === [[File:KruskalGeneratedMaze.webm|thumb|An animation of generating a 30 by 20 maze using Kruskal's algorithm]] This algorithm is a randomized version of [[Kruskal's algorithm]]. # Create a list of all walls, and create a set for each cell, each containing just that one cell. # For each wall, in some random order: ## If the cells divided by this wall belong to distinct sets: ### Remove the current wall. ### Join the sets of the formerly divided cells. There are several data structures that can be used to model the sets of cells. An efficient implementation using a [[disjoint-set data structure]] can perform each union and find operation on two sets in nearly constant [[amortized time]] (specifically, <math>O(\alpha(V))</math> time; <math>\alpha(x) < 5</math> for any plausible value of <math>x</math>), so the running time of this algorithm is essentially proportional to the number of walls available to the maze. It matters little whether the list of walls is initially randomized or if a wall is randomly chosen from a nonrandom list, either way is just as easy to code. Because the effect of this algorithm is to produce a minimal spanning tree from a graph with equally weighted edges, it tends to produce regular patterns which are fairly easy to solve. === Iterative randomized Prim's algorithm (without stack, without sets) === [[File:MAZE 30x20 Prim.ogv|thumb|upright=1.6|An animation of generating a 30 by 20 maze using Prim's algorithm]] This algorithm is a randomized version of [[Prim's algorithm]]. # Start with a grid full of walls. # Pick a cell, mark it as part of the maze. Add the walls of the cell to the wall list. # While there are walls in the list: ## Pick a random wall from the list. If only one of the cells that the wall divides is visited, then: ### Make the wall a passage and mark the unvisited cell as part of the maze. ### Add the neighboring walls of the cell to the wall list. ## Remove the wall from the list. Note that simply running classical Prim's on a graph with random edge weights would create mazes stylistically identical to Kruskal's, because they are both minimal spanning tree algorithms. Instead, this algorithm introduces stylistic variation because the edges closer to the starting point have a lower effective weight. ==== Modified version ==== Although the classical Prim's algorithm keeps a list of edges, for maze generation we could instead maintain a list of adjacent cells. If the randomly chosen cell has multiple edges that connect it to the existing maze, select one of these edges at random. This will tend to branch slightly more than the edge-based version above. ==== Simplified version ==== The algorithm can be simplified even further by randomly selecting cells that neighbour already-visited cells, rather than keeping track of the weights of all cells or edges. It will usually be relatively easy to find the way to the starting cell, but hard to find the way anywhere else. === Wilson's algorithm === {{Main|Loop-erased random walk}} [[File:WilsonMazeGen.gif|thumb|right|Maze generation animation using Wilson's algorithm (gray represents an ongoing random walk). Once built the maze is solved using depth first search.]] All the above algorithms have biases of various sorts: depth-first search is biased toward long corridors, while Kruskal's/Prim's algorithms are biased toward many short dead ends. Wilson's algorithm,<ref>{{cite conference | title = Generating random spanning trees more quickly than the cover time | first = David Bruce | last = Wilson | date = May 22–24, 1996 | conference = Symposium on Theory of Computing | book-title = Proceedings of the Twenty-Eighth Annual ACM Symposium on Theory of Computing | publisher = ACM | location = Philadelphia | pages = 296–303 | isbn = 0-89791-785-5 | doi = 10.1145/237814.237880 |citeseerx = 10.1.1.47.8598}}</ref> on the other hand, generates an ''unbiased'' sample from the [[discrete uniform distribution|uniform distribution]] over all mazes, using [[loop-erased random walk]]s. We begin the algorithm by initializing the maze with one cell chosen arbitrarily. Then we start at a new cell chosen arbitrarily, and perform a random walk until we reach a cell already in the maze—however, if at any point the random walk reaches its own path, forming a loop, we erase the loop from the path before proceeding. When the path reaches the maze, we add it to the maze. Then we perform another loop-erased random walk from another arbitrary starting cell, repeating until all cells have been filled. This procedure remains unbiased no matter which method we use to arbitrarily choose starting cells. So we could always choose the first unfilled cell in (say) left-to-right, top-to-bottom order for simplicity. === Aldous-Broder algorithm === The Aldous-Broder algorithm also produces uniform spanning trees. However, it is one of the least efficient maze algorithms.<ref> {{cite web |author=Jamis Buck |title=Maze Generation: Aldous-Broder algorithm |url=https://weblog.jamisbuck.org/2011/1/17/maze-generation-aldous-broder-algorithm |date=17 January 2011}} </ref> # Pick a random cell as the current cell and mark it as visited. # While there are unvisited cells: ## Pick a random neighbour. ## If the chosen neighbour has not been visited: ### Remove the wall between the current cell and the chosen neighbour. ### Mark the chosen neighbour as visited. ## Make the chosen neighbour the current cell. ===Recursive division method=== {| class="wikitable" style="margin:auto" |+ '''Illustration of Recursive Division''' |- ! width="110px" | ''original chamber'' ! width="110px" | ''division by two walls'' ! width="110px" | ''holes in walls'' ! width="110px" | ''continue subdividing...'' ! width="110px" | ''completed'' |- | align="center" | [[File:Chamber.svg|thumb|step 1|101px]] | align="center" | [[File:Chamber-division.svg|thumb|step 2|101px]] | align="center" | [[File:Chamber-divided.svg|thumb|step 3|101px]] | align="center" | [[File:Chamber-subdivision.svg|thumb|step 4|101px]] | align="center" | [[File:Chamber-finished.svg|thumb|step 5|101px]] |} {{clear}} Mazes can be created with ''recursive division'', an algorithm which works as follows: Begin with the maze's space with no walls. Call this a chamber. Divide the chamber with a randomly positioned wall (or multiple walls) where each wall contains a randomly positioned passage opening within it. Then recursively repeat the process on the subchambers until all chambers are minimum sized. This method results in mazes with long straight walls crossing their space, making it easier to see which areas to avoid. For example, in a rectangular maze, build at random points two walls that are perpendicular to each other. These two walls divide the large chamber into four smaller chambers separated by four walls. Choose three of the four walls at random, and open a one cell-wide hole at a random point in each of the three. Continue in this manner recursively, until every chamber has a width of one cell in either of the two directions. === Fractal Tessellation algorithm === [[File:Tessellation_Maze_Generator.gif|thumb|right|Maze generation animation using a tessellation algorithm]] This is a simple and fast way to generate a maze.<ref>{{cite web |author=Ze Oliveira |title=Maze Walls |url=https://arcalusitana.org/MuseuZX/Pascalated_ZXBASIC |date=18 June 2023}}</ref> On each iteration, this algorithm creates a maze twice the size by copying itself 3 times. At the end of each iteration, 3 paths are opened between the 4 smaller mazes. The advantage of this method is that it is very fast. The downside is that it is not possible to get a maze of a chosen size - but various tricks can be used to get around this problem.
Edit summary
(Briefly describe your changes)
By publishing changes, you agree to the
Terms of Use
, and you irrevocably agree to release your contribution under the
CC BY-SA 4.0 License
and the
GFDL
. You agree that a hyperlink or URL is sufficient attribution under the Creative Commons license.
Cancel
Editing help
(opens in new window)