它们基本上非常相似,只有很小的不同,我遵循了我在网上找到的伪代码(我理解算法本身,我在纸上try 过它,它很管用,我的代码也是如此,但我只是对生成的迷宫有多相似不满意). 伪码:

  1. 第一步:初始化第一行.
  2. 步骤2:对于该行中每一列,如果它没有单元格, 创建一个并将其添加到自己的集合中.行中的每个单元格都应该是 在这一点上是一套的一部分.
  3. 步骤3:从左到右,如果当前单元格和下一个单元格 小区在不同的集合中,随机决定连接到下一个 手机.如果它们连接在一起,则将这些单元的集合合并在一起.
  4. 第四步:初始化下一行.对于当前行中的每个集合, 每组至少一个单元格向下连接,将该单元格添加到 它与之相连的集合.
  5. 步骤5:移至下一行,重复步骤2至4.
  6. 步骤6:当在最后一行时,重复步骤3,但删除 随机性,总是连接到下一个细胞,如果它在一个 不同的布景.不要做任何向下的联系.

我的代码(Java):

import java.util.*;

public class MazeGeneratorEller {
    private int[][] grid; // The grid representing the maze
    private int[] tiles; // The tiles used to represent walls and paths
    private int r; // The number of rows in the maze
    private int c; // The number of columns in the maze
    private int[] disjointedSet; // The disjoint set data structure used to keep track of connected components

    public MazeGeneratorEller(int m, int n, int[] tile) {
        this.r = m;
        this.c = n;
        this.grid = new int[m * 2 + 1][n * 2 + 1];
        this.tiles = tile.clone();
        this.disjointedSet = new int[m * n];
        Arrays.fill(this.disjointedSet, -1);
    }

    class Vertex {
        int x;
        int y;

        Vertex(int x, int y) {
            this.x = x;
            this.y = y;
        }

        public String toString() {
            return "(" + this.x + "," + this.y + ")";
        }

        @Override
        public boolean equals(Object obj) {
            if (obj == null || this.getClass() != obj.getClass())
                return false;
            if (this == obj)
                return true;
            Vertex test = (Vertex) obj;
            return this.x == test.x && this.y == test.y;
        }

        @Override
        public int hashCode() {
            return Objects.hash(this.x, this.y);
        }
    }

    class Edge {
        Vertex from;
        Vertex to;

        Edge(Vertex x, Vertex y) {
            this.from = x;
            this.to = y;
        }

        public String toString() {
            return this.from + "<->" + this.to;
        }
    }

    HashMap<Vertex, Integer> map = new HashMap<Vertex, Integer>();
    ArrayList<Edge> solution = new ArrayList<Edge>();

    // Adds all the vertices to the map
    private void addVertices() {
        int index = 0;
        for (int i = 0; i < this.r; i++) {
            for (int j = 0; j < this.c; j++)
                this.map.put(new Vertex(i, j), index++);
        }
    }

    // Finds the root of the disjoint set that f belongs to
    private int find(int f) {
        if (this.disjointedSet[f] < 0) {
            return f;
        } else {
            this.disjointedSet[f] = find(this.disjointedSet[f]);
            return this.disjointedSet[f];       }
    }

    // Merges the disjoint sets that the two vertices of the edge belong to
    private void union(Edge e) {
        int x = find(this.map.get(e.from));
        int y = find(this.map.get(e.to));
        if (x != y) {
            this.solution.add(e);
            if (this.disjointedSet[x] <= this.disjointedSet[y]) {
                this.disjointedSet[x] += this.disjointedSet[y];
                this.disjointedSet[y] = x;
            } else {
                this.disjointedSet[y] += this.disjointedSet[x];
                this.disjointedSet[x] = y;
            }
        }
    }

    // Generates the maze
    public int[][] generateMaze() {
        addVertices();
        for (int i = 0; i < this.r - 1; i++) {
            for (int j = 0; j < this.c - 1; j++) {
                Random rand = new Random(System.nanoTime());
                Vertex k = new Vertex(i, j);
                if (find(this.map.get(k)) == find(this.map.get(new Vertex(i, j + 1))))
                    continue;
                int choose = rand.nextInt(4);
                if (choose == 1)
                    union(new Edge(k, new Vertex(i, j + 1)));
            }
//start of new part
            int checkerBelow = 0;
            for (int j = 0; j < this.c; j++) {
                if (checkerBelow == 0) {
                    union(new Edge(new Vertex(i, j), new Vertex(i + 1, j)));
                    checkerBelow = 1;
                } else {
                    int choose = rand.nextInt(2);
                    if (choose == 1) {
                        union(new Edge(new Vertex(i, j), new Vertex(i + 1, j)));
                    }
                }
                if (j == this.c - 1)
                    continue;
                if (find(this.map.get(new Vertex(i, j))) != find(this.map.get(new Vertex(i, j + 1)))) {
                    checkerBelow = 0;
                }
            }
//end of new part
        }
        for (int j = 0; j < this.c - 1; j++) {
            union(new Edge(new Vertex(this.r - 1, j), new Vertex(this.r - 1, j + 1)));
        }//The algorithm ends here. The rest is just filling the grid.
        // Fill the grid array with walls and paths
        for (int i = 0; i < this.grid.length; i++)
            Arrays.fill(this.grid[i], this.tiles[1]);
        for (Edge e : this.solution) {
            int x1 = e.from.x * 2 + 1;
            int y1 = e.from.y * 2 + 1;
            int x2 = e.to.x * 2 + 1;
            int y2 = e.to.y * 2 + 1;
            this.grid[x1][y1] = this.tiles[0];
            this.grid[x2][y2] = this.tiles[0];
            this.grid[(x1 + x2) / 2][(y1 + y2) / 2] = this.tiles[0];
        }
        return this.grid;
    }
}

These are 3 mazes generated by my implementation of the algorithm, note that I enlarge the grid to display both walls and paths so the maze size is (m2+1)(n2+1), first is 33 grid, 45, 6*4(all before enlarging)个 抱歉,我的英语很差,我的问题表达也很糟糕.

我将新的部分添加到代码中,它现在工作得很好.

推荐答案

我发现了问题所在,判断当前行中的每个单元格,如果该单元格属于只有1个元素的集合,或者如果该单元格属于与下一行没有连接的集合,则必须将该单元格与其下一行中的单元格连接,否则您可以随机决定是否将当前单元格与其下一单元格连接.因此,为了实现这一点,我做了以下工作:

int checkerBelow = 0;
            for (int j = 0; j < this.c; j++) {
                if (checkerBelow == 0) {
                    union(new Edge(new Vertex(i, j), new Vertex(i + 1, j)));
                    checkerBelow = 1;
                } else {
                    int choose = rand.nextInt(2);
                    if (choose == 1) {
                        union(new Edge(new Vertex(i, j), new Vertex(i + 1, j)));
                    }
                }
                if (j == this.c - 1)
                    continue;
                if (find(this.map.get(new Vertex(i, j))) != find(this.map.get(new Vertex(i, j + 1)))) {
                    checkerBelow = 0;
                }
            }

I added a flag variable called checkerBelow and initialize it to 0, if it is 0 then we connect the current cell with the cell below it and flip checkerBelow to 1, otherwise we randomly decide whether or not to connect the current cell with the cell below it. I also added another conditional,(note that first I check if I am at the last cell, if I am then I can't compare the last cell with the cell after it in the same row) if the current cell and the cell after it belong to different sets, then I will flip checkerBelow to 0, to make sure that the following set has connection to the next row. and the result is a truly randomized maze (I displayed the maze in a GUI this time instead of just printing it to the terminal) example 1:100x100 grid example 2:100x100 grid

我再一次为我糟糕的英语道歉,并非常感谢 comments 区里那些帮助我的人.开斋节-穆巴拉克!

Java相关问答推荐

无法运行Java(已解决)

我可以在regex中的字符类中放置断言吗?

当我用OkHttpClient重写shouldInterceptRequest来发布数据时,Android WebView正在以纯HTML加载URL内容

如何调用Firebase Realtime Database中的子图像列表到android studio中的回收器视图?

使用标记时,场景大纲不在多个线程上运行

Java 21 struct 化连接货币,需要可预知的子任务异常排序

如何修复IndexOutOfBoundsException在ClerView适配器的onRowMoved函数?

FALSE:它应该在什么时候使用?

如何调整工作时间日历中的时间

为什么Java编译器不区分不同类型的方法?

使用PDFBox从PDF中删除图像

Java中将文本拆分为数字或十进制数字和字符串

搜索列表返回多个频道

虚拟线程应该很快消亡吗?

在Frege中,我如何将一个字符串安全地转换为一个可能的Int?

使用htmlunit和java单击按钮

为什么有两种实现来检索数组类的组件类型?

Java页面筛选器问题

EXCEL中的公式单元格显示#NAME?

Java类型推断:为什么要编译它?