看不到如何将 flood fill routine 更改为 DFS one
Can't see how to change flood fill routine to DFS one
我一直在使用泛洪填充例程检查某种类型的块,然后找到相同类型的所有连接块并将它们更改为类型 "stone"
我主要对块的坐标感兴趣,不想更改它们,但是当我删除 "change to stone" 语句时,它似乎无休止地 运行。
经过研究,深度优先搜索似乎可行,但不确定如何实现 - 似乎我只需要调整洪水填充,但我尝试的所有内容要么无限循环,要么在第一次迭代时停止。
这里是原程序。
//interact
var node1 = {
xy : []
};
var blockp;
//starting block type and position
blockp = world.getBlock(npc.getBlockX(), npc.getBlockY() - 1, npc.getBlockZ() + 1);
node1.xy[0] = npc.getBlockX();
node1.xy[1] = npc.getBlockZ() + 1;
node1.xy[2] = npc.getBlockY() - 1;
//
var floodfill = function (nameb, node) {
if (nameb == "minecraft:stone" || nameb == null) {
return;
}
var blkname;
var xy0 = node.xy[0];
var xy1 = node.xy[1];
var xy2 = node.xy[2];
//
//Line I would like to remove
world.setBlock(node.xy[0], node.xy[2], node.xy[1], world.createItem("minecraft:stone", 0, 1));
//
// collect x y z positions for all blocks
world.getTempData("X_corr").push(node.xy[0]);
world.getTempData("Y_corr").push(node.xy[2]);
world.getTempData("Z_corr").push(node.xy[1]);
//
node.xy[0] = xy0;
node.xy[1] = xy1 + 1;
node.xy[2] = xy2;
if (world.getBlock(node.xy[0], node.xy[2], node.xy[1]) == null) {
blkname = null;
} else {
blkname = world.getBlock(node.xy[0], node.xy[2], node.xy[1]).name;
}
floodfill(blkname, node);
//
node.xy[0] = xy0;
node.xy[1] = xy1 - 1;
node.xy[2] = xy2;
if (world.getBlock(node.xy[0], node.xy[2], node.xy[1]) == null) {
blkname = null;
} else {
blkname = world.getBlock(node.xy[0], node.xy[2], node.xy[1]).name;
}
floodfill(blkname, node);
//
node.xy[0] = xy0 + 1;
node.xy[1] = xy1;
node.xy[2] = xy2;
if (world.getBlock(node.xy[0], node.xy[2], node.xy[1]) == null) {
blkname = null;
} else {
blkname = world.getBlock(node.xy[0], node.xy[2], node.xy[1]).name;
}
floodfill(blkname, node);
//
node.xy[0] = xy0 - 1;
node.xy[1] = xy1;
node.xy[2] = xy2;
if (world.getBlock(node.xy[0], node.xy[2], node.xy[1]) == null) {
blkname = null;
} else {
blkname = world.getBlock(node.xy[0], node.xy[2], node.xy[1]).name;
}
floodfill(blkname, node);
//
node.xy[0] = xy0;
node.xy[1] = xy1;
node.xy[2] = xy2 + 1;
npc.say("go up " + blkname);
if (world.getBlock(node.xy[0], node.xy[2], node.xy[1]) == null) {
blkname = null;
} else {
blkname = world.getBlock(node.xy[0], node.xy[2], node.xy[1]).name;
npc.say("go up " + blkname);
}
floodfill(blkname, node);
//
node.xy[0] = xy0;
node.xy[1] = xy1;
node.xy[2] = xy2 - 1;
if (world.getBlock(node.xy[0], node.xy[2], node.xy[1]) == null) {
blkname = null;
} else {
blkname = world.getBlock(node.xy[0], node.xy[2], node.xy[1]).name;
}
floodfill(blkname, node);
//
return;
}
floodfill(blockp.name, node1);
让我从 floodfill 永不结束的原因开始:它不知道什么时候必须停止,因为 none 个块发生了变化。该程序认为它以前从未遇到过该块,并一次又一次地查看它...
深度优先搜索是一种不断深入直到无法再进行搜索的搜索方法。当你碰到一个部分的末尾时,你会返回,直到遇到一个你以前从未见过的项目,然后尽可能深入地研究与之相关的任何内容。
广度优先搜索恰恰相反。它检查连接到您的起点的内容,检查所有内容,然后检查他们的所有子项,以及他们的子项等等。
因为您想找到所有相互连接的块,所以您选择这些搜索方法中的哪一种都没有区别,因为它们会以相同的 O(n) 复杂度找到所有项目。
我个人对您要制作的东西一无所知,但我正在努力使它尽可能具有普遍性。
对于这些搜索中的任何一个,block
应该有一个名为 visited
或类似名称的变量,您可以使用它来表示您之前是否遇到过此块。您可能必须自己创建此变量。
您还需要一种方法来查找 block
连接到的所有 block
并将 return 作为数组或列表。在示例中,我将调用此函数 neighbours()
.
要实施 DFS,您需要 Stack。堆栈是后进先出的数据结构,这意味着最后进来的东西最先出来。将一些东西放入堆栈称为 push
。取回物品称为 pop
.
这是 DFS 的伪代码:
DFS(Block start) {
Stack stack = new stack();
stack.push(start); // Put the first block in the stack
while(stack.count > 0) {
Block current = stack.pop();
if(current.visited)
continue; // if we've already seen this block, don't bother
current.visited = true;
/* YOU CAN DO ANYTHING YOU WANT WITH THE BLOCK HERE */
Block[] neighbours = current.neighbours();
foreach(neighbour in neighbours)
stack.push(neighbour);
}
}
BFS 是不同的,并且稍微更适合您正在尝试做的事情。它使用 Queue 以先进先出的顺序存储需要搜索的所有内容。这意味着搜索树中更靠下的东西将被稍后搜索,这通常更适合任何搜索。向队列中添加东西称为 enqueue
,取出下一个东西称为 dequeue
。
这是 BFS 的伪代码:
BFS(Block start)
Queue queue = new Queue();
queue.enqueue(start); // Put the first block in the stack
while(queue.count > 0) {
Block current = queue.dequeue();
if(current.visited)
continue; // if we've already seen this block, don't bother
current.visited = true;
/* YOU CAN DO ANYTHING YOU WANT WITH THE BLOCK HERE */
Block[] neighbours = current.neighbours();
foreach(neighbour in neighbours)
queue.enqueue(neighbour);
}
}
正如你所看到的,两种搜索方法非常相似,它们都是 运行 在 O(n) time complexity.
祝编码顺利!
我一直在使用泛洪填充例程检查某种类型的块,然后找到相同类型的所有连接块并将它们更改为类型 "stone" 我主要对块的坐标感兴趣,不想更改它们,但是当我删除 "change to stone" 语句时,它似乎无休止地 运行。 经过研究,深度优先搜索似乎可行,但不确定如何实现 - 似乎我只需要调整洪水填充,但我尝试的所有内容要么无限循环,要么在第一次迭代时停止。 这里是原程序。
//interact
var node1 = {
xy : []
};
var blockp;
//starting block type and position
blockp = world.getBlock(npc.getBlockX(), npc.getBlockY() - 1, npc.getBlockZ() + 1);
node1.xy[0] = npc.getBlockX();
node1.xy[1] = npc.getBlockZ() + 1;
node1.xy[2] = npc.getBlockY() - 1;
//
var floodfill = function (nameb, node) {
if (nameb == "minecraft:stone" || nameb == null) {
return;
}
var blkname;
var xy0 = node.xy[0];
var xy1 = node.xy[1];
var xy2 = node.xy[2];
//
//Line I would like to remove
world.setBlock(node.xy[0], node.xy[2], node.xy[1], world.createItem("minecraft:stone", 0, 1));
//
// collect x y z positions for all blocks
world.getTempData("X_corr").push(node.xy[0]);
world.getTempData("Y_corr").push(node.xy[2]);
world.getTempData("Z_corr").push(node.xy[1]);
//
node.xy[0] = xy0;
node.xy[1] = xy1 + 1;
node.xy[2] = xy2;
if (world.getBlock(node.xy[0], node.xy[2], node.xy[1]) == null) {
blkname = null;
} else {
blkname = world.getBlock(node.xy[0], node.xy[2], node.xy[1]).name;
}
floodfill(blkname, node);
//
node.xy[0] = xy0;
node.xy[1] = xy1 - 1;
node.xy[2] = xy2;
if (world.getBlock(node.xy[0], node.xy[2], node.xy[1]) == null) {
blkname = null;
} else {
blkname = world.getBlock(node.xy[0], node.xy[2], node.xy[1]).name;
}
floodfill(blkname, node);
//
node.xy[0] = xy0 + 1;
node.xy[1] = xy1;
node.xy[2] = xy2;
if (world.getBlock(node.xy[0], node.xy[2], node.xy[1]) == null) {
blkname = null;
} else {
blkname = world.getBlock(node.xy[0], node.xy[2], node.xy[1]).name;
}
floodfill(blkname, node);
//
node.xy[0] = xy0 - 1;
node.xy[1] = xy1;
node.xy[2] = xy2;
if (world.getBlock(node.xy[0], node.xy[2], node.xy[1]) == null) {
blkname = null;
} else {
blkname = world.getBlock(node.xy[0], node.xy[2], node.xy[1]).name;
}
floodfill(blkname, node);
//
node.xy[0] = xy0;
node.xy[1] = xy1;
node.xy[2] = xy2 + 1;
npc.say("go up " + blkname);
if (world.getBlock(node.xy[0], node.xy[2], node.xy[1]) == null) {
blkname = null;
} else {
blkname = world.getBlock(node.xy[0], node.xy[2], node.xy[1]).name;
npc.say("go up " + blkname);
}
floodfill(blkname, node);
//
node.xy[0] = xy0;
node.xy[1] = xy1;
node.xy[2] = xy2 - 1;
if (world.getBlock(node.xy[0], node.xy[2], node.xy[1]) == null) {
blkname = null;
} else {
blkname = world.getBlock(node.xy[0], node.xy[2], node.xy[1]).name;
}
floodfill(blkname, node);
//
return;
}
floodfill(blockp.name, node1);
让我从 floodfill 永不结束的原因开始:它不知道什么时候必须停止,因为 none 个块发生了变化。该程序认为它以前从未遇到过该块,并一次又一次地查看它...
深度优先搜索是一种不断深入直到无法再进行搜索的搜索方法。当你碰到一个部分的末尾时,你会返回,直到遇到一个你以前从未见过的项目,然后尽可能深入地研究与之相关的任何内容。
广度优先搜索恰恰相反。它检查连接到您的起点的内容,检查所有内容,然后检查他们的所有子项,以及他们的子项等等。
因为您想找到所有相互连接的块,所以您选择这些搜索方法中的哪一种都没有区别,因为它们会以相同的 O(n) 复杂度找到所有项目。
我个人对您要制作的东西一无所知,但我正在努力使它尽可能具有普遍性。
对于这些搜索中的任何一个,block
应该有一个名为 visited
或类似名称的变量,您可以使用它来表示您之前是否遇到过此块。您可能必须自己创建此变量。
您还需要一种方法来查找 block
连接到的所有 block
并将 return 作为数组或列表。在示例中,我将调用此函数 neighbours()
.
要实施 DFS,您需要 Stack。堆栈是后进先出的数据结构,这意味着最后进来的东西最先出来。将一些东西放入堆栈称为 push
。取回物品称为 pop
.
这是 DFS 的伪代码:
DFS(Block start) {
Stack stack = new stack();
stack.push(start); // Put the first block in the stack
while(stack.count > 0) {
Block current = stack.pop();
if(current.visited)
continue; // if we've already seen this block, don't bother
current.visited = true;
/* YOU CAN DO ANYTHING YOU WANT WITH THE BLOCK HERE */
Block[] neighbours = current.neighbours();
foreach(neighbour in neighbours)
stack.push(neighbour);
}
}
BFS 是不同的,并且稍微更适合您正在尝试做的事情。它使用 Queue 以先进先出的顺序存储需要搜索的所有内容。这意味着搜索树中更靠下的东西将被稍后搜索,这通常更适合任何搜索。向队列中添加东西称为 enqueue
,取出下一个东西称为 dequeue
。
这是 BFS 的伪代码:
BFS(Block start)
Queue queue = new Queue();
queue.enqueue(start); // Put the first block in the stack
while(queue.count > 0) {
Block current = queue.dequeue();
if(current.visited)
continue; // if we've already seen this block, don't bother
current.visited = true;
/* YOU CAN DO ANYTHING YOU WANT WITH THE BLOCK HERE */
Block[] neighbours = current.neighbours();
foreach(neighbour in neighbours)
queue.enqueue(neighbour);
}
}
正如你所看到的,两种搜索方法非常相似,它们都是 运行 在 O(n) time complexity.
祝编码顺利!