gpt4 book ai didi

algorithm - 生成和解决一个没有边界的迷宫?

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:08:39 25 4
gpt4 key购买 nike

好吧,假设你试图穿过迷宫的“北边”,你会回到同一个迷宫,但在“南边”。有点像在迷宫中穿行。

是否有可能生成和解决这样的迷宫?我还没有找到关于这个主题的文档......

最佳答案

关键点是将迷宫从像素网格重新概念化为图形。然后,您可以连接图形,使其形成环形。

威尔逊算法可能特别容易理解。它的另一个好处是它生成了一个统一生成树,它是从一个空间的所有可能生成树的集合中统一绘制的生成树。

执行以下操作:

  1. 随机选择任意顶点并将其添加到 UST。
  2. 选择任何不在 UST 中的顶点并执行 loop-erasing random walk直到遇到 UST 中的顶点。您可以修改此随机游走,使其在遇到边缘时环绕。
  3. 将随机游走中接触到的顶点和边添加到 UST。
  4. 重复 2 和 3,直到所有顶点都已添加到 UST。

可以讨论herehere .

这是该算法的草稿(剩余的粉红色单元格是绘图例程中的人工制品,但不影响结果)。

<!DOCTYPE html>
<meta charset="utf-8">
<style>

body {
background: #000;
}

</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>

var width = 200,
height = 200;

var N = 1 << 0,
S = 1 << 1,
W = 1 << 2,
E = 1 << 3;

var cellSize = 4,
cellSpacing = 4,
cellWidth = Math.floor((width - cellSpacing) / (cellSize + cellSpacing)),
cellHeight = Math.floor((height - cellSpacing) / (cellSize + cellSpacing)),
cells = new Array(cellWidth * cellHeight), // each cell’s edge bits
remaining = d3.range(cellWidth * cellHeight), // cell indexes to visit
previous = new Array(cellWidth * cellHeight), // current random walk path
i0, x0, y0; // end of current random walk

var canvas = d3.select("body").append("canvas")
.attr("width", width)
.attr("height", height);

var context = canvas.node().getContext("2d");

context.translate(
Math.round((width - cellWidth * cellSize - (cellWidth + 1) * cellSpacing) / 2),
Math.round((height - cellHeight * cellSize - (cellHeight + 1) * cellSpacing) / 2)
);

// Add the starting cell.
context.fillStyle = "white";
var start = remaining.pop();
cells[start] = 0;
fillCell(start);

// While there are remaining cells,
// add a loop-erased random walk to the maze.
context.fillStyle = "magenta";
d3.timer(function() {
for (var k = 0; k < 50; ++k) {
if (loopErasedRandomWalk()) {
return true;
}
}
});

function loopErasedRandomWalk() {
var i1;

// Pick a location that’s not yet in the maze (if any).
if (i0 == null) {
do if ((i0 = remaining.pop()) == null) return true;
while (cells[i0] >= 0);
previous[i0] = i0;
fillCell(i0);
x0 = i0 % cellWidth;
y0 = i0 / cellWidth | 0;
return;
}

// Perform a random walk starting at this location,
// by picking a legal random direction.
i1 = Math.random() * 4 | 0;
if (i1 === 0) {
if (y0 <= 0){
y0 = cellHeight-1;
i1 = i0 - cellWidth + cellWidth*cellHeight;
} else{
--y0;
i1 = i0 - cellWidth;
}
} else if (i1 === 1) {
if (y0 >= cellHeight - 1){
y0 = 0;
i1 = i0 + cellWidth - cellWidth*cellHeight;
} else {
++y0;
i1 = i0 + cellWidth;
}
} else if (i1 === 2) {
if (x0 <= 0){
x0 = cellWidth-1;
i1 = i0+cellWidth-1;
} else {
--x0;
i1 = i0 - 1;
}
} else {
if (x0 >= cellWidth - 1) {
x0 = 0;
i1 = i0-cellWidth+1;
} else {
++x0;
i1 = i0 + 1;
}
}

// If this new cell was visited previously during this walk,
// erase the loop, rewinding the path to its earlier state.
if (previous[i1] >= 0) eraseWalk(i0, i1);

// Otherwise, just add it to the walk.
else {
previous[i1] = i0;
fillCell(i1);
if (i1 === i0 - 1) fillEast(i1);
else if (i1 === i0 + 1) fillEast(i0);
else if (i1 === i0 - cellWidth) fillSouth(i1);
else fillSouth(i0);
}

// If this cell is part of the maze, we’re done walking.
if (cells[i1] >= 0) {

// Add the random walk to the maze by backtracking to the starting cell.
// Also erase this walk’s history to not interfere with subsequent walks.
context.save();
context.fillStyle = "#fff";
fillCell(i1);
while ((i0 = previous[i1]) !== i1) {
fillCell(i0);
if (i1 === i0 + 1) cells[i0] |= E, cells[i1] |= W, fillEast(i0);
else if (i1 === i0 - 1) cells[i0] |= W, cells[i1] |= E, fillEast(i1);
else if (i1 === i0 + cellWidth) cells[i0] |= S, cells[i1] |= N, fillSouth(i0);
else cells[i0] |= N, cells[i1] |= S, fillSouth(i1);
previous[i1] = NaN;
i1 = i0;
}
context.restore();

previous[i1] = NaN;
i0 = null;
} else {
i0 = i1;
}
}

function eraseWalk(i0, i2) {
var i1;
context.save();
context.globalCompositeOperation = "destination-out";
do {
i1 = previous[i0];
if (i1 === i0 - 1) fillEast(i1);
else if (i1 === i0 + 1) fillEast(i0);
else if (i1 === i0 - cellWidth) fillSouth(i1);
else fillSouth(i0);
fillCell(i0);
previous[i0] = NaN;
i0 = i1;
} while (i1 !== i2);
context.restore();
}

function fillCell(i) {
var x = i % cellWidth, y = i / cellWidth | 0;
context.fillRect(x * cellSize + (x + 1) * cellSpacing, y * cellSize + (y + 1) * cellSpacing, cellSize, cellSize);
}

function fillEast(i) {
var x = i % cellWidth, y = i / cellWidth | 0;
context.fillRect((x + 1) * (cellSize + cellSpacing), y * cellSize + (y + 1) * cellSpacing, cellSpacing, cellSize);
}

function fillSouth(i) {
var x = i % cellWidth, y = i / cellWidth | 0;
context.fillRect(x * cellSize + (x + 1) * cellSpacing, (y + 1) * (cellSize + cellSpacing), cellSize, cellSpacing);
}

d3.select(self.frameElement).style("height", height + "px");

</script>

关于algorithm - 生成和解决一个没有边界的迷宫?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51679134/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com