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

锚点跳转的HTML页面中Tic Tac Toe游戏脚本无法运行

Tic Tac Toe页面跳转后脚本失效的修复方案

我在网站首页导航栏添加了指向Tic Tac Toe游戏页面的链接,游戏单独打开时所有功能正常,但从首页点击链接跳转后,游戏脚本完全无法执行。

首页HTML代码

<!DOCTYPE html>
<html>
<head>
  <title>My Website</title>
  <link rel="stylesheet" type="text/css" href="assets/style/home.css">
  <script type="module" src="assets/script/home.js"></script>

</head> 
<body>
  <header>
    <h1>My Website</h1>
    <nav>
      <ul>
        <li><a href="views/tictactoe.html">Tic Tac Toe</a></li>
      </ul>
    </nav>
  </header>
  <div class="container">
    <h2>Welcome to My Website</h2>
  </div>
</body>
</html>

Tic Tac Toe页面代码

<!DOCTYPE html>
<html>
<head>
  <title>Tic-Tac-Toe</title>
  <style>
    ...Styling...
  </style>
</head>
<body>
  <h1>Tic-Tac-Toe</h1>
  <h2>Score</h2>
  <div style="display: flex; justify-content: center;">
    <p style="margin-left: 20px; margin-right: 20px">Player 1: <span id="player1Score">0</span></p>
    <p style="margin-left: 20px; margin-right: 20px">Player 2: <span id="player2Score">0</span></p>
  </div>

  <button>Reset</button>
  <table>
    <tr>
      <td></td>
      <td></td>
      <td></td>
    </tr>
    <tr>
      <td></td>
      <td></td>
      <td></td>
    </tr>
    <tr>
      <td></td>
      <td></td>
      <td></td>
    </tr>
  </table>
  <script>
    // Create an array to represent the game board
var gameBoard = [
  ["", "", ""],
  ["", "", ""],
  ["", "", ""]
];

// Get all td elements in the table
var cells = document.getElementsByTagName("td");

document.getElementsByTagName("button")[0].addEventListener("click", resetGame);

function resetGame() {
  gameBoard = [    ["", "", ""],
    ["", "", ""],
    ["", "", ""]
  ];
  currentPlayer = "X";
  gameOver = false;
  for (var i = 0; i < cells.length; i++) {
    cells[i].innerHTML = "";
  }
}

// Add an event listener to each td element
for (var i = 0; i < cells.length; i++) {
  cells[i].addEventListener("click", function() {
    // When a td element is clicked, get its row and column indices
    var row = this.parentElement.rowIndex;
    var col = this.cellIndex;

    // Call the takeTurn function with the row and column indices
    takeTurn(row, col);
  });
}

// Initialize variables to keep track of the current player and the game state
var gameOver = false;

// Create a variable to keep track of the current player's symbol
var currentPlayer = "X";

// Function to handle a player's turn
// Function to handle a player's turn
function takeTurn(row, col) {
  // Check if the game is already over or if the selected cell is already occupied
  if (gameOver || gameBoard[row][col] != "") {
    return;
  }

  // Check if it is the current player's turn
  if (currentPlayer == "X") {
    // Place the current player's symbol on the game board
    gameBoard[row][col] = currentPlayer;

    // Update the td element to display the current player's symbol
    cells[row * gameBoard[0].length + col].innerHTML = currentPlayer;

    // Check if the current player has won
    if (checkWin(currentPlayer)) {
        // If the current player has won, set the game state to over and display a win message
        gameOver = true;

        if (currentPlayer === "X") {
            var scoreElement = document.getElementById("player1Score");
        } else {
            var scoreElement = document.getElementById("player2Score");
        }

        // Increment the player's score
        var currentScore = parseInt(scoreElement.innerHTML);
        scoreElement.innerHTML = currentScore + 1;

        alert(currentPlayer + " wins!");
    } else if (checkTie()) {
      // If there is a tie, set the game state to over and display a tie message
      gameOver = true;
      alert("It's a tie!");
    }

    // Switch the current player after each turn
    if (currentPlayer === "X") {
        currentPlayer = "O";
    } else {
        currentPlayer = "X";
    }
  }
  else if (currentPlayer == "O") {
    // Place the current player's symbol on the game board
    gameBoard[row][col] = currentPlayer;

    // Update the td element to display the current player's symbol
    cells[row * gameBoard[0].length + col].innerHTML = currentPlayer;

    // Check if the current player has won
    if (checkWin(currentPlayer)) {
        // If the current player has won, set the game state to over and display a win message
        gameOver = true;

        if (currentPlayer === "X") {
            var scoreElement = document.getElementById("player1Score");
        } else {
            var scoreElement = document.getElementById("player2Score");
        }

        // Increment the player's score
        var currentScore = parseInt(scoreElement.innerHTML);
        scoreElement.innerHTML = currentScore + 1;

        alert(currentPlayer + " wins!");
    } else if (checkTie()) {
        // If there is a tie, set the game state to over and display a tie message
        gameOver = true;
        alert("It's a tie!");
    }

    // Switch the current player after each turn
    if (currentPlayer === "X") {
        currentPlayer = "O";
    } else {
        currentPlayer = "X";
    }
    }
}

// Function to check if the current game is tied
function checkTie() {
  for (var row = 0; row < gameBoard.length; row++) {
    for (var col = 0; col < gameBoard[row].length; col++) {
      if (gameBoard[row][col] === "") {
        return false;
      }
    }
  }
  return true;
}

// Function to check if the current player has won
function checkWin(player) {
  // Check all rows
  for (var i = 0; i < gameBoard.length; i++) {
    if (gameBoard[i][0] == player && gameBoard[i][1] == player && gameBoard[i][2] == player) {
      return true;
    }
  }

  // Check all columns
  for (var i = 0; i < gameBoard[0].length; i++) {
    if (gameBoard[0][i] == player && gameBoard[1][i] == player && gameBoard[2][i] == player) {
      return true;
    }
  }

  // Check both diagonals
  if (gameBoard[0][0] == player && gameBoard[1][1] == player && gameBoard[2][2] == player) {
    return true;
  }
  if (gameBoard[0][2] == player && gameBoard[1][1] == player && gameBoard[2][0] == player) {
    return true;
  }

  // If none of the checks have returned true, the player has not won
  return false;
}
  </script>
</body>
</html>

问题原因

脚本直接放在<body>底部时,单独打开页面浏览器会按顺序解析DOM并执行脚本,不会有问题;但从其他页面跳转时,浏览器的页面加载机制可能导致脚本执行时DOM元素还未完全就绪,比如document.getElementsByTagName("td")获取不到元素,后续的事件绑定也就失效了。

修复方案

把所有游戏脚本代码包裹在DOMContentLoaded事件监听中,确保脚本只在DOM完全加载完成后执行,同时可以优化takeTurn函数的冗余代码:

<script>
document.addEventListener('DOMContentLoaded', function() {
    // Create an array to represent the game board
var gameBoard = [
  ["", "", ""],
  ["", "", ""],
  ["", "", ""]
];

// Get all td elements in the table
var cells = document.getElementsByTagName("td");

document.getElementsByTagName("button")[0].addEventListener("click", resetGame);

function resetGame() {
  gameBoard = [    ["", "", ""],
    ["", "", ""],
    ["", "", ""]
  ];
  currentPlayer = "X";
  gameOver = false;
  for (var i = 0; i < cells.length; i++) {
    cells[i].innerHTML = "";
  }
}

// Add an event listener to each td element
for (var i = 0; i < cells.length; i++) {
  cells[i].addEventListener("click", function() {
    // When a td element is clicked, get its row and column indices
    var row = this.parentElement.rowIndex;
    var col = this.cellIndex;

    // Call the takeTurn function with the row and column indices
    takeTurn(row, col);
  });
}

// Initialize variables to keep track of the current player and the game state
var gameOver = false;

// Create a variable to keep track of the current player's symbol
var currentPlayer = "X";

// Function to handle a player's turn
function takeTurn(row, col) {
  // Check if the game is already over or if the selected cell is already occupied
  if (gameOver || gameBoard[row][col] != "") {
    return;
  }

  // Place the current player's symbol on the game board
  gameBoard[row][col] = currentPlayer;
  // Update the td element to display the current player's symbol
  cells[row * gameBoard[0].length + col].innerHTML = currentPlayer;

  // Check if the current player has won
  if (checkWin(currentPlayer)) {
      gameOver = true;
      var scoreElement = document.getElementById(currentPlayer === "X" ? "player1Score" : "player2Score");
      var currentScore = parseInt(scoreElement.innerHTML);
      scoreElement.innerHTML = currentScore + 1;
      alert(currentPlayer + " wins!");
  } else if (checkTie()) {
    gameOver = true;
    alert("It's a tie!");
  }

  // Switch the current player after each turn
  currentPlayer = currentPlayer === "X" ? "O" : "X";
}

// Function to check if the current game is tied
function checkTie() {
  for (var row = 0; row < gameBoard.length; row++) {
    for (var col = 0; col < gameBoard[row].length; col++) {
      if (gameBoard[row][col] === "") {
        return false;
      }
    }
  }
  return true;
}

// Function to check if the current player has won
function checkWin(player) {
  // Check all rows
  for (var i = 0; i < gameBoard.length; i++) {
    if (gameBoard[i][0] == player && gameBoard[i][1] == player && gameBoard[i][2] == player) {
      return true;
    }
  }

  // Check all columns
  for (var i = 0; i < gameBoard[0].length; i++) {
    if (gameBoard[0][i] == player && gameBoard[1][i] == player && gameBoard[2][i] == player) {
      return true;
    }
  }

  // Check both diagonals
  if (gameBoard[0][0] == player && gameBoard[1][1] == player && gameBoard[2][2] == player) {
    return true;
  }
  if (gameBoard[0][2] == player && gameBoard[1][1] == player && gameBoard[2][0] == player) {
    return true;
  }

  // If none of the checks have returned true, the player has not won
  return false;
}
});
</script>

内容的提问来源于stack exchange,提问作者Dlybeck

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 07:05:44