如何实现JavaScript井字棋游戏的正常重置功能?
井字棋重置功能问题排查与修复
我用JavaScript开发简易井字棋,其他功能正常,但添加重置函数时,要么生成新棋盘,要么在按钮区域创建元素,目标是清空现有棋盘,求可行方案。
我的JavaScript代码
const playBoard = document.querySelector("#playboard"); const playerTurn = document.querySelector("#gamerChange"); const winner = document.querySelector("#winnerMessage"); // defining the cells the X and O are going to be placed let startCells = ["", "", "", "", "", "", "", "", ""]; let start = "circle"; // playerTurn.textContent = "Circle goes first"; // winner.textContent = "Circle wins!"; // function to create the whole playboard function createPlayBoard() { startCells.forEach((cell, index) => { const cellElement = document.createElement("div"); cellElement.classList.add("square"); cellElement.id = index; cellElement.addEventListener("click", addElement); playBoard.append(cellElement); }); } createPlayBoard(); function addElement(event) { const elementDisplay = document.createElement("div"); elementDisplay.classList.add(start); event.target.append(elementDisplay); start = start === "circle" ? "cross" : "circle"; playerTurn.textContent = "It is " + start + "'s turn!"; event.target.removeEventListener("click", addElement); checkTheScore(); } function checkTheScore() { const allSquares = document.querySelectorAll(".square"); const winningCombs = [ [0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 4, 8], [2, 4, 6], [1, 4, 7], [0, 3, 6], [2, 5, 8], ]; winningCombs.forEach((array) => { const circleWins = array.every((cell) => allSquares[cell].firstChild?.classList.contains("circle") ); if (circleWins) { winner.textContent = "Circle wins!"; playerTurn.textContent = ""; allSquares.forEach((square) => square.replaceWith(square.cloneNode(true)) ); return; } }); winningCombs.forEach((array) => { const crossWins = array.every((cell) => allSquares[cell].firstChild?.classList.contains("cross") ); if (crossWins) { winner.textContent = "Cross wins!"; playerTurn.textContent = ""; allSquares.forEach((square) => square.replaceWith(square.cloneNode(true)) ); return; } }); } function resetGame() { const button = document.getElementById("restart"); button.addEventListener("click", () => { startCells = ["", "", "", "", "", "", "", "", ""]; start = "circle"; }); checkTheScore(); }
我的HTML代码
<!DOCTYPE HTML> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="style.css"> </head> <body> <div class="text"> <h1>Welcome to TicTacToe</h1> <p id="gamerChange"></p> <p id="winnerMessage"></p> </div> <div id="playboard"></div> <button id="restart" onClick="resetGame()">Restart game!</button> <!--Javascript file--> <script src="app.js"></script> </body> </html>
问题分析与修复方案
现有重置函数的核心问题
- 重复绑定点击事件:HTML按钮已经通过
onClick="resetGame()"绑定事件,函数内部又再次添加click监听,导致每次点击都会累加绑定,引发异常行为。 - 未处理棋盘DOM:只重置了状态变量,没清空棋盘上的
circle/cross元素,也没恢复方块的点击事件。 - 提示文本未重置:没有把回合提示和获胜消息恢复到初始状态。
修复后的重置函数
function resetGame() { // 重置游戏状态变量 startCells = ["", "", "", "", "", "", "", "", ""]; start = "circle"; // 重置页面提示文本 playerTurn.textContent = "Circle goes first"; winner.textContent = ""; // 清空棋盘并恢复交互 const allSquares = document.querySelectorAll(".square"); allSquares.forEach(square => { // 清空方块内的棋子元素 square.innerHTML = ""; // 重新绑定点击事件(之前点击后已移除) square.addEventListener("click", addElement); }); }
额外优化:移除重复事件绑定
把HTML中按钮的onClick="resetGame()"删除,改为在JavaScript中一次性绑定,避免重复绑定问题:
// 在代码末尾添加,替代HTML中的onClick属性 document.getElementById("restart").addEventListener("click", resetGame);
完整修复后的JavaScript代码
const playBoard = document.querySelector("#playboard"); const playerTurn = document.querySelector("#gamerChange"); const winner = document.querySelector("#winnerMessage"); let startCells = ["", "", "", "", "", "", "", "", ""]; let start = "circle"; playerTurn.textContent = "Circle goes first"; function createPlayBoard() { startCells.forEach((cell, index) => { const cellElement = document.createElement("div"); cellElement.classList.add("square"); cellElement.id = index; cellElement.addEventListener("click", addElement); playBoard.append(cellElement); }); } createPlayBoard(); function addElement(event) { const elementDisplay = document.createElement("div"); elementDisplay.classList.add(start); event.target.append(elementDisplay); start = start === "circle" ? "cross" : "circle"; playerTurn.textContent = "It is " + start + "'s turn!"; event.target.removeEventListener("click", addElement); checkTheScore(); } function checkTheScore() { const allSquares = document.querySelectorAll(".square"); const winningCombs = [ [0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 4, 8], [2, 4, 6], [1, 4, 7], [0, 3, 6], [2, 5, 8], ]; let gameWon = false; winningCombs.forEach((array) => { const circleWins = array.every((cell) => allSquares[cell].firstChild?.classList.contains("circle") ); if (circleWins) { winner.textContent = "Circle wins!"; playerTurn.textContent = ""; allSquares.forEach((square) => square.replaceWith(square.cloneNode(true)) ); gameWon = true; return; } }); if (gameWon) return; winningCombs.forEach((array) => { const crossWins = array.every((cell) => allSquares[cell].firstChild?.classList.contains("cross") ); if (crossWins) { winner.textContent = "Cross wins!"; playerTurn.textContent = ""; allSquares.forEach((square) => square.replaceWith(square.cloneNode(true)) ); gameWon = true; return; } }); } function resetGame() { startCells = ["", "", "", "", "", "", "", "", ""]; start = "circle"; playerTurn.textContent = "Circle goes first"; winner.textContent = ""; const allSquares = document.querySelectorAll(".square"); allSquares.forEach(square => { square.innerHTML = ""; square.addEventListener("click", addElement); }); } // 绑定重置按钮事件 document.getElementById("restart").addEventListener("click", resetGame);
修复后的HTML代码
<!DOCTYPE HTML> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="style.css"> </head> <body> <div class="text"> <h1>Welcome to TicTacToe</h1> <p id="gamerChange"></p> <p id="winnerMessage"></p> </div> <div id="playboard"></div> <button id="restart">Restart game!</button> <script src="app.js"></script> </body> </html>
内容的提问来源于stack exchange,提问作者meii18
相关产品推荐
相关产品推荐

