javaScript minesweeper空字段显示

问题描述 投票:0回答:1

我正在尝试使用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个回答
2
投票

基本规则是:

  • 如果您发现炸弹旁边的邻近区域,请停止搜索
  • 如果邻近的场没有炸弹,继续扩展到新场的邻居

在代码中:

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;
}
<div class="board"></div>
© www.soinside.com 2019 - 2024. All rights reserved.