You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现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>

问题分析与修复方案

现有重置函数的核心问题

  1. 重复绑定点击事件:HTML按钮已经通过onClick="resetGame()"绑定事件,函数内部又再次添加click监听,导致每次点击都会累加绑定,引发异常行为。
  2. 未处理棋盘DOM:只重置了状态变量,没清空棋盘上的circle/cross元素,也没恢复方块的点击事件。
  3. 提示文本未重置:没有把回合提示和获胜消息恢复到初始状态。

修复后的重置函数

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 10:09:49