java生成迷宫prim,为什么我用Java实现的随机Prim's Algorithm只会生成完整的网格?

I attempted to follow this pseudocode on wikipedia https://en.wikipedia.org/wiki/Maze_generation_algorithmRandomized_Prim's_algorithm

but my code just generates a full grid. I seem to be missing something in my understanding of what the algorithm does. Can someone help explain what I'm doing wrong?

I've looked at a few sources but I can't wrap my head around it

public class MazeGen {

private int dimension, nodeCounter;

private Node[][] nodes;

private List walls;

public static void main(String[] args) {

MazeGen g = new MazeGen(20);

g.generate();

g.printMaze();

}

private void generate() {

pickCell();

generateMaze();

}

private void generateMaze() {

while (!walls.isEmpty()) {

int v;

Edge wall = walls.get(ThreadLocalRandom.current().nextInt(walls.size()));

if ((!wall.nodes[0].visited && wall.nodes[1].visited)

|| (wall.nodes[0].visited && !wall.nodes[1].visited)) {

if (!wall.nodes[0].visited)

v = 0;

else

v = 1;

includeNode(wall.nodes[v]);

wall.nodes[Math.abs(v - 1)].visited = true;

}

walls.remove(wall);

}

}

private void pickCell() {

int i = ThreadLocalRandom.current().nextInt(dimension);

int j = ThreadLocalRandom.current().nextInt(dimension);

includeNode(nodes[i][j]);

}

private void includeNode(Node node) {

node.visited = true;

node.partOfMaze = true;

walls.addAll(node.edges);

}

public void printMaze() {

for (int i = 0; i < dimension; i++) {

System.out.println();

for (int j = 0; j < dimension; j++) {

if (nodes[i][j].partOfMaze) {

System.out.print(".");

} else

System.out.print("p");

}

}

}

public MazeGen(int n) {

nodes = new Node[n][n];

walls = new ArrayList();

dimension = n;

createNodes();

connectAdjacents();

}

private void connectAdjacents() {

for (int i = 0; i < dimension; i++) {

for (int j = 0; j < dimension; j++) {

verifyConnection(i, j, i, j + 1);

verifyConnection(i, j, i + 1, j);

}

}

}

private void verifyConnection(int i, int j, int arg1, int arg2) {

if (arg1 < dimension && arg2 < dimension)

connect(i, j, arg1, arg2);

}

private void createNodes() {

for (int i = 0; i < dimension; i++) {

for (int j = 0; j < dimension; j++) {

nodes[i][j] = new Node();

}

}

}

private void connect(int row, int col, int row2, int col2) {

nodes[row][col].edges.add(new Edge(nodes[row][col], nodes[row2][col2]));

nodes[row2][col2].edges.add(new Edge(nodes[row][col], nodes[row2][col2]));

}

private class Node {

boolean visited, partOfMaze;

int number;

List edges;

Node() {

number = nodeCounter++;

edges = new ArrayList();

}

@Override

public String toString() {

return String.valueOf(number);

}

}

private class Edge {

Node[] nodes;

Edge(Node n, Node n2) {

nodes = new Node[2];

nodes[0] = n;

nodes[1] = n2;

}

@Override

public String toString() {

return nodes[0] + "-" + nodes[1];

}

}

解决方案

Forget Wikipedia, they censor free speech and manipulate information, especially in political and social areas. For that reason I also deleted all my additions to the Wikipedia page on "maze generation" (see page history).

The idea of "Prim's" MST algorithm is to maintain a "cut" (a set of edges) between disconnected subgraphs and always select the cheapest edge to connect these subgraphs. Visited vertices are marked to avoid generating cycles.

This can be used for maze generation by using edge random weights in a full grid graph or by starting with an empty grid graph and adding randomly weighted edges on the fly.

See my GitHub repository on maze generation for details:

public void createMaze(int x, int y) {

cut = new PriorityQueue<>();

expand(grid.cell(x, y));

while (!cut.isEmpty()) {

WeightedEdge minEdge = cut.poll();

int u = minEdge.either(), v = minEdge.other();

if (isCellUnvisited(u) || isCellUnvisited(v)) {

grid.addEdge(u, v);

expand(isCellUnvisited(u) ? u : v);

}

}

}

private void expand(int cell) {

grid.set(cell, COMPLETED);

grid.neighbors(cell).filter(this::isCellUnvisited).forEach(neighbor -> {

cut.add(new WeightedEdge<>(cell, neighbor, rnd.nextInt()));

});

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,生成迷宫的过程可以分为以下几个步骤: 1. 初始化迷宫 2. 以prim算法生成迷宫 3. 输出迷宫 下面是Java语言实现prim算法生成迷宫的代码。假设迷宫是一个 $n \times n$ 的矩阵,其中 $n$ 是偶数。 ```java import java.util.*; public class Maze { private int[][] maze; private int n; public Maze(int n) { this.n = n; maze = new int[n][n]; } public void generate() { Random rand = new Random(); int startX = rand.nextInt(n); int startY = rand.nextInt(n); maze[startX][startY] = 1; List<int[]> walls = new ArrayList<>(); if (startX > 0) walls.add(new int[]{startX - 1, startY, startX, startY}); if (startX < n - 1) walls.add(new int[]{startX + 1, startY, startX, startY}); if (startY > 0) walls.add(new int[]{startX, startY - 1, startX, startY}); if (startY < n - 1) walls.add(new int[]{startX, startY + 1, startX, startY}); while (!walls.isEmpty()) { int[] wall = walls.remove(rand.nextInt(walls.size())); int x1 = wall[0], y1 = wall[1], x2 = wall[2], y2 = wall[3]; if (maze[x1][y1] == 0 && maze[x2][y2] == 1) { maze[x1][y1] = 1; if (x1 > 0) walls.add(new int[]{x1 - 1, y1, x1, y1}); if (x1 < n - 1) walls.add(new int[]{x1 + 1, y1, x1, y1}); if (y1 > 0) walls.add(new int[]{x1, y1 - 1, x1, y1}); if (y1 < n - 1) walls.add(new int[]{x1, y1 + 1, x1, y1}); } } } public void print() { for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (maze[i][j] == 1) { System.out.print(" "); } else { System.out.print("#"); } } System.out.println(); } } public static void main(String[] args) { Maze maze = new Maze(10); maze.generate(); maze.print(); } } ``` 代码中,我们首先初始化了一个 $n \times n$ 的矩阵,然后随机选择一个起点开始生成迷宫。我们将起点标记为已访问,然后将与起点相邻的四个方格加入待选墙列表中。之后我们不断从待选墙列表中随机选择一面墙,将其拆除,并将与该墙相邻的未访问的方格加入待选墙列表中,直到所有的墙都被拆除为止。最后我们打印出生成迷宫。 希望能够帮到你!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值