我正在使用原生 JavaScript 构建扫雷游戏。我有一个处理网格逻辑的 Grid 类,一个基本上充当空间属性容器的 Space 类,以及一个处理游戏逻辑的 Game 类。
在 Grid 类中,我有一个名为 openAdjoiningSpaces
的方法。此方法的预期行为是从单击的空白空间开始在每个方向上打开板上所有连接的空间,并在下一个空间与地雷接壤时终止。如果您不熟悉扫雷,您可以在 http://minesweeperonline.com/ 查看此行为。 .
openAdjoiningSpaces
方法调用另一个方法,getBorderingSpaces
。此方法接受单击的空间作为参数并返回一个包含每个边界空间的数组,包括在 Angular 落处接触的空间。
当 openAdjoiningSpaces
被调用时,它首先获取不包含地雷的边界空间并将它们放入一个名为 toOpen
的数组中。然后该方法使用一个 while 循环。在while循环中,打开toOpen
中的每一个空格,然后对于每一个打开的空格,获取其边界空格,如果为空,则将它们添加到一个名为next的数组中
。在循环结束时,如果next
数组的长度大于0,则将toOpen
变量重新赋值给next
,否则循环终止。
这应该会导致所需的行为,但事实并非如此。每次我用另一种方式重写它时,它要么使浏览器崩溃(即使它不是无限循环),要么它只打开点击空间的周围空间然后终止。这是方法本身:
openAdjoiningSpaces(space)
{
if (space.isEmpty) {
let loop = true;
var toOpen = [ ...this.getBorderingSpaces(space).filter(space => !space.hasMine)];
while (loop) {
const next = [];
toOpen.forEach(space => {
this.openSpace(space.id);
const neighbouring = this.getBorderingSpaces(space);
neighbouring.forEach(space => {
if (!space.hasMine && space.isEmpty) {
next.push(space);
}
});
});
if (next.length > 0) {
toOpen = next;
break;
} else {
loop = false;
}
}
}
}
这两天我一直在尝试创建这种空间开放行为。每次我接近成功时,网格仍然显示某种错误行为。整个下午我都在不断地尝试以不同的方式重写这个方法,但都无济于事。我束手无策,真的需要一些外部输入。请不要犹豫,让我澄清有关代码的任何内容。我应该澄清的一件事是,Space 对象有两个独立的属性 hasMine
和 isEmpty
。第一个只是指空间是否有地雷。第二个是指它是否包含数字。也许是设计缺陷,我不知道,但我想我应该提一下。
最佳答案
找到它有点棘手,但是 openAdjoiningSpaces
中有一个错误。当您将项目添加到 next
时,您永远不会检查当前空间是否已经打开。这导致 isOpen
数组在每次迭代中都变大,从而使循环永无止境。将此添加到您的代码并删除 toOpen = next
break
改变这个
toOpen.forEach(space => {
this.openSpace(space.id);
const neighbouring = this.getBorderingSpaces(space);
neighbouring.forEach(space => {
if (!space.hasMine && space.isEmpty) {
next.push(space);
}
});
});
为此
toOpen.forEach(space => {
this.openSpace(space.id);
const neighbouring = this.getBorderingSpaces(space);
neighbouring.forEach(space => {
if (!space.hasMine && space.isEmpty && space.status !== 'open') {
next.push(space);
}
});
});
关于javascript - while 循环要么崩溃要么不执行所需的操作 - 非常困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59523554/