【问题标题】:javaScript minesweeper empty fields revealjavaScript扫雷空域显示
【发布时间】:2018-03-06 01:41:09
【问题描述】:

我正在尝试使用 html css 和 js 创建一个扫雷游戏。我创建了板,字段(div 元素),放置了炸弹,每个字段“知道”他的位置(x,y)(x 和 y 坐标保存为 div 的数据属性),“知道”他是否炸弹和附近的炸弹数量。我设法创建了 onclick 事件以显示该图块是否为炸弹或显示附近的炸弹数量。现在我的问题是,如果我单击附近没有炸弹的图块(空图块),我想显示周围的所有空图块。 因此,如果我单击一个空字段,则会调用下一个函数:

function zero(x, y) {
    for (var i = x - 1; i <= x + 1; i++) {
        for (var j = y - 1; j <= y + 1; j++) {
            $('.tile[row-d=' + i + '][col-d=' + j + ']').text($('.tile[row-d=' + i + '][col-d=' + j + ']').attr('bomb_number')); // set the field text = bomb -number nearby
        }
    }
}

这样,我显示了单击的空白字段附近的所有周围字段,因此我仅显示 9 个字段。我想显示附近的所有空字段,而不仅仅是 9。我尝试使用递归函数,但页面崩溃了。 所以任何人都可以用递归函数来帮助我解决这个问题。谢谢你。 (如你所见,我也在使用 jQuery)

【问题讨论】:

    标签: javascript recursion minesweeper


    【解决方案1】:

    基本规则是:

    • 如果您发现炸弹旁边的相邻字段,请停止搜索
    • 如果相邻字段没有炸弹,则继续扩展到新字段的邻居

    在代码中:

    function zero(x, y) {
        for (var i = x - 1; i <= x + 1; i++) {
            for (var j = y - 1; j <= y + 1; j++) {
                var neighbor = $('.tile[row-d=' + i + '][col-d=' + j + ']');
                var bombNr = neighbor.attr('bomb_number');
    
                neighbor.text(bombNr);
    
                if (bombNr === "0") zero(i, j);
            }
        }
    }
    

    编辑:递归模式的一个快速而肮脏的例子

    // The recursive function
    const handleInput = i => {
      if (tapped.has(i)) return;
      
      // Count the bombs in neighboring tiles
      const bombs = neighbors(i)
        .map(j => board[j])
        .filter(v => v === x)
        .length;
    
      // Store the count so we can render it
      tapped.set(i, bombs);
      
      // If there are no bombs, handle all the neighbors'
      // as well.
      if (bombs === 0) {
        neighbors(i).forEach(handleInput);
      }
    };
    
    // Game state
    const x = "x";
    const board = [
      x, 0, 0, 0, 0,
      x, 0, 0, 0, 0,
      x, x, x, 0, 0,
      0, 0, 0, 0, 0,
      0, 0, x, 0, 0
    ];
    
    const tapped = new Map();
    
    // Quick & dirty render method to visualize what happens
    const render = board => {
      const el = document.querySelector(".board")
      
      el.innerHTML =
        board
          .map((v, i) => tapped.has(i) ? tapped.get(i) : v)
          .map(txt => `<div>${txt}</div>`)
          .join("");
        
      Array.from(el.children).forEach((c, i) => {
        c.addEventListener("click", () => {
          
          if (board[i] === x) return console.log("Boom!");
          
          handleInput(i);
          
          render(board);
          
        });
        
        c.classList.toggle("tapped", tapped.has(i));
      });
    }
    
    const row = i => i / 5 << 0;
    const col = i => i % 5;
    const neighbors = i => {
      const top =    [ -6, -5, -4 ];
      const right =  [ -4,  1,  6 ];
      const bottom = [  4,  5,  6 ];
      const left =   [ -6, -1,  4 ];
      
      const ds = new Set([...top, ...right, ...bottom, ...left]);
      const remove = d => ds.delete(d);
      
      if (row(i) === 0) top.forEach(remove);
      if (row(i) === 4) bottom.forEach(remove);
      if (col(i) === 0) left.forEach(remove);
      if (col(i) === 4) right.forEach(remove);
    
      return [...ds].map(d => d + i);
    };
    
    render(board);
    .board {
     width: 100px;
     height: 100px;
    }
    
    .board > div {
      width: 20px;
      height: 20px;
      border: 1px solid black;
      box-sizing: border-box;
      display: inline-block;
      text-align: center;
    }
    
    .board > div.tapped {
      background: yellow;
    }
    &lt;div class="board"&gt;&lt;/div&gt;

    【讨论】:

    • 感谢您的回答,但我尝试了类似的方法但没有成功,但我尝试了您的代码以确保得到相同的结果,即没有显示输出,页面冻结,页面上的任何其他按钮都不起作用,我无法刷新页面,并且在 30 秒后抛出错误:未捕获 RangeError:超出最大调用堆栈大小。那么有什么好的建议吗?
    • 我快速搭建了一个演示应用程序来展示bombs === 0 检查如何触发相邻图块上的递归模式。它远非完美(共享状态、糟糕的渲染等),但可能会帮助你明白这一点......
    • 感谢您的帮助。这对我来说有点难以理解(毕竟我只是 js 的初学者)。我设法找到了解决方案。我发现了一个类似的问题 stackoverflow.com/questions/34459086/… ,稍微修改了一下,效果很好。
    • 递归可能很困难,老实说,我的示例对初学者不太友好...确保使用调试器逐步完成每个步骤,如果您无法弄清楚,你总是可以从基于循环的方法开始:)
    • 我刚刚测试了我自己以前的版本,它不起作用,我设法修复它。我的问题是我没有检查瓷砖是否被显示,在我放了一个 if 语句来检查它之后,它工作得很好。再次感谢您的努力。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多