【问题标题】:while loop is either crashing or not performing the desired actions - very confusedwhile 循环要么崩溃,要么没有执行所需的操作 - 非常困惑
【发布时间】:2020-04-18 18:28:53
【问题描述】:

我正在使用原生 JavaScript 构建扫雷游戏。我有一个处理网格逻辑的 Grid 类,一个基本上充当空间属性容器的 Space 类,以及一个处理游戏逻辑的 Game 类。

在 Grid 类中,我有一个名为 openAdjoiningSpaces 的方法。此方法的预期行为是打开板上每个方向上的所有连接空间,从单击的空白空间开始,并在下一个空间与地雷接壤时终止。如果您不熟悉 Minesweeper,您可以在 http://minesweeperonline.com/ 看到此行为。

openAdjoiningSpaces 方法调用另一个方法,getBorderingSpaces。此方法接受单击的空间作为参数,并返回一个包含每个边界空间的数组,包括在角落接触的空间。

当调用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;
                }

            }
        }
    }

我已经尝试创建这种空间打开行为两天了。每次我接近成功时,网格仍然显示某种错误行为。整个下午,我不断尝试以不同的方式重写此方法,但无济于事。我束手无策,真的需要一些外部输入。请不要犹豫,要求我澄清有关代码的任何内容。我应该澄清的一件事是,空间对象有两个独立的属性hasMineisEmpty。第一个只是指空间是否有地雷。第二个是指它是否包含数字。也许是设计缺陷,我不知道,但我想我应该提一下。

【问题讨论】:

  • 澄清一下,while 循环应该一直持续到next.length === 0?如果是这种情况,在您的代码中,您总是以任何一种方式结束循环(break 打破循环),因此您应该删除break。无论如何,您能否将this.getBorderingSpaces 的代码包含在内?如果您还可以添加一些测试“空格”和预期的结果,那就更好了。
  • 有助于发布有效代码,第一行似乎缺少关键字。
  • @RobG 没有缺少关键字。 JavaScript 中的方法省略了 function 关键字。
  • 发布的代码包含语法错误。
  • 我无法在此处发布getBorderingSpaces 方法,因为它太长了。但是,它确实正确获取了与目标空间接触的所有空间。

标签: javascript while-loop minesweeper


【解决方案1】:

这有点难找,但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);
                    }
                });
            });

【讨论】:

  • 感谢您的努力。这确实修复了一个错误,但该方法仍然没有产生预期的结果。方法仍然只打开直接接触点击空间的空间,而不是扇出。
  • 没关系,我删除了break 声明。期望的行为几乎达到。现在唯一的问题是它只打开所有空白空间。我实际上应该继续打开空间,直到它找到一个与地雷接壤的空间,然后打开该空间并终止。不过越来越近了。我很受鼓舞。
  • 再次感谢您的帮助。如果你有兴趣,这里是克隆:michaelacook.github.io/minesweeper 大约完成了 98%。
猜你喜欢
  • 2015-01-22
  • 1970-01-01
  • 2018-08-27
  • 1970-01-01
  • 2023-03-17
  • 1970-01-01
  • 1970-01-01
  • 2014-03-15
  • 2020-03-07
相关资源
最近更新 更多