锚点跳转的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
相关产品推荐
相关产品推荐

