What's a good algorithm to generate a maze?

后端 未结 9 1414
囚心锁ツ
囚心锁ツ 2020-11-27 09:55

Say you want a simple maze on an N by M grid, with one path through, and a good number of dead ends, but that looks \"right\" (i.e. like someone made it by hand without too

相关标签:
9条回答
  • 2020-11-27 10:26

    Recursive Backtracking is the easiest algorithm to implement.

    Here's a Java implementation:

    Here Cell is a class representing a cell in a 2D grid and cells is a 2D array of Cell objects. Cell has boolean variables top, bottom, left and right to indicate whether a cell has walls on these sides, a boolean variable visited to check whether we have traversed it and two integer variables row and col to indicate its position in the grid.

    Cell current = cells[0][0] , next;
        current.visited=true;
        do{
            next = getNeighbour(current);
            if(next!=null){
                removeWall(current , next);
                st.push(current);
                current = next;
                current.visited = true;
            }
            else {
                current = st.pop();
            }
        }
        while (!st.empty());
    
    
        private Cell getNeighbour(Cell cell){
        ArrayList<Cell> ara = new ArrayList<>();
        if(cell.col>0 && !cells[cell.col-1][cell.row].visited)
             ara.add(cells[cell.col-1][cell.row]);
    
        if(cell.row>0 && !cells[cell.col][cell.row-1].visited)
             ara.add(cells[cell.col][cell.row-1]);
    
        if(cell.col<col-1 && !cells[cell.col+1][cell.row].visited)
             ara.add(cells[cell.col+1][cell.row]);
        if(cell.row<row-1 && !cells[cell.col][cell.row+1].visited)
             ara.add(cells[cell.col][cell.row+1]); 
    
    
        if(ara.size()>0){
            return ara.get(new Random().nextInt(ara.size()));
        }else{
            return null;
        }
    }
    private void removeWall(Cell curr , Cell nxt){
        if((curr.col == nxt.col) && (curr.row == nxt.row+1)){/// top
            curr.top=nxt.botttom=false;
        }
        if(curr.col==nxt.col && curr.row == nxt.row-1){///bottom
            curr.botttom = nxt.top = false;
        }
        if(curr.col==nxt.col-1 && curr.row==nxt.row ){///right
            curr.right = nxt.left = false;
        }
        if(curr.col == nxt.col+1 && curr.row == nxt.row){///left
            curr.left = nxt.right = false;
        }
    }
    
    0 讨论(0)
  • 2020-11-27 10:27

    My favorite way is to use Kruskal's algorithm, but when randomly choosing and edge to remove, weight the choice based on the types of edges it's connected to.

    By varying the weights for different edge types, you can generate mazes with lots of distinct characteristics or "personalities". See my example here:

    https://mtimmerm.github.io/webStuff/maze.html

    0 讨论(0)
  • 2020-11-27 10:30

    From http://www.astrolog.org/labyrnth/algrithm.htm

    Recursive backtracker: This is somewhat related to the recursive backtracker solving method described below, and requires stack up to the size of the Maze. When carving, be as greedy as possible, and always carve into an unmade section if one is next to the current cell. Each time you move to a new cell, push the former cell on the stack. If there are no unmade cells next to the current position, pop the stack to the previous position. The Maze is done when you pop everything off the stack. This algorithm results in Mazes with about as high a "river" factor as possible, with fewer but longer dead ends, and usually a very long and twisty solution. It runs quite fast, although Prim's algorithm is a bit faster. Recursive backtracking doesn't work as a wall adder, because doing so tends to result in a solution path that follows the outside edge, where the entire interior of the Maze is attached to the boundary by a single stem.

    They produce only 10% dead ends

    is an example of a maze generated by that method.

    0 讨论(0)
提交回复
热议问题