javaScript 扫雷空场显示
javaScript minesweeper empty fields reveal
我正在尝试使用 html css 和 js 创建一个扫雷游戏。我创建了面板,字段(div 元素),放置了炸弹,每个字段 "knows" 他的位置(x,y)(x 和 y 坐标保存为 [=20 的数据属性=]), "knows" 如果他是炸弹和附近的炸弹数量。我设法创建了 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)
基本规则是:
- 如果您找到炸弹旁边的相邻字段,请停止搜索
- 如果相邻字段没有炸弹,则继续扩展到新字段的邻居
在代码中:
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>
我正在尝试使用 html css 和 js 创建一个扫雷游戏。我创建了面板,字段(div 元素),放置了炸弹,每个字段 "knows" 他的位置(x,y)(x 和 y 坐标保存为 [=20 的数据属性=]), "knows" 如果他是炸弹和附近的炸弹数量。我设法创建了 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)
基本规则是:
- 如果您找到炸弹旁边的相邻字段,请停止搜索
- 如果相邻字段没有炸弹,则继续扩展到新字段的邻居
在代码中:
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>