扫雷游戏按钮事件监听器中函数无法运行问题求助
扫雷游戏问题修复方案
核心问题说明
- 原代码在生成tile的循环中重复绑定按钮点击事件,调用
getMinePositions生成新坐标后没有更新每个tile的mine属性,导致地雷位置不会变化 - 游戏失败后绑定的
stopImmediatePropagation拦截事件没有移除,导致无法点击操作
修复代码
仅需要修改JS代码,HTML和CSS无需改动,修改后完整JS代码如下:
const TILE_STATUSES = { HIDDEN: "hidden", MINE: "mine", NUMBER: "number", }; function createBoard(boardSize, numberOfMines) { const board = []; const minePositions = getMinePositions(boardSize, numberOfMines); for (let x = 0; x < boardSize; x++) { const row = []; for (let y = 0; y < boardSize; y++) { const element = document.createElement("div"); element.dataset.status = TILE_STATUSES.HIDDEN; const tile = { element, x, y, mine: minePositions.some(positionMatch.bind(null, { x, y })), get status() { return this.element.dataset.status; }, set status(value) { this.element.dataset.status = value; }, }; row.push(tile); } board.push(row); } return board; } function revealTile(tile) { if (tile.status !== TILE_STATUSES.HIDDEN) { return; } if (tile.mine) { tile.status = TILE_STATUSES.MINE; return; } tile.status = TILE_STATUSES.NUMBER; } function checkLose(board) { return board.some((row) => { return row.some((tile) => { return tile.status === TILE_STATUSES.MINE; }); }); } function getMinePositions(boardSize, numberOfMines) { const positions = []; while (positions.length < numberOfMines) { const position = { x: randomNumber(boardSize), y: randomNumber(boardSize), }; if (!positions.some(positionMatch.bind(null, position))) { positions.push(position); } } return positions; } function positionMatch(a, b) { return a.x === b.x && a.y === b.y; } function randomNumber(size) { return Math.floor(Math.random() * size); } const BOARD_SIZE = 5; const NUMBER_OF_MINES = 2; const board = createBoard(BOARD_SIZE, NUMBER_OF_MINES); const boardElement = document.querySelector(".board"); board.forEach((row) => { row.forEach((tile) => { boardElement.append(tile.element); tile.element.addEventListener("click", () => { revealTile(tile); checkGameEnd(); }); tile.element.addEventListener("contextmenu", (e) => { e.preventDefault(); }); }); }); boardElement.style.setProperty("--size", BOARD_SIZE); function checkGameEnd() { const lose = checkLose(board); if (lose) { boardElement.addEventListener("click", stopProp, { capture: true }); boardElement.addEventListener("contextmenu", stopProp, { capture: true }); } if (lose) { board.forEach((row) => { row.forEach((tile) => { if (tile.mine) revealTile(tile); }); }); } } function stopProp(a) { a.stopImmediatePropagation(); } // 新增重置游戏逻辑 document.querySelector(".btn").addEventListener("click", resetGame); function resetGame() { // 移除游戏结束拦截事件 boardElement.removeEventListener("click", stopProp, { capture: true }); boardElement.removeEventListener("contextmenu", stopProp, { capture: true }); // 生成新地雷坐标 const newMinePositions = getMinePositions(BOARD_SIZE, NUMBER_OF_MINES); // 重置所有tiles状态 board.forEach(row => { row.forEach(tile => { tile.status = TILE_STATUSES.HIDDEN; tile.mine = newMinePositions.some(positionMatch.bind(null, {x: tile.x, y: tile.y})) }) }) }
内容的提问来源于stack exchange,提问作者Bagnom
相关产品推荐
相关产品推荐

