井字棋游戏重置后img.src与img.style.display无法更新问题
井字棋重置后玩家点击失效的问题解决
问题根源
你遇到的核心问题是通过img.src === ""判断格子是否为空的逻辑完全失效。当你在reset()里设置img.src = ""时,浏览器会自动将其解析为当前页面的绝对URL(比如http://127.0.0.1:5500/),而非空字符串。重置后点击棋盘,playerClick()里的if (img.src === "")条件永远不成立,导致后续更新src和display的逻辑完全不执行。
另外,checkWin()里直接比较src的绝对URL,虽然初始游戏能正常运行,但重置后同样会因为src变为页面URL而出现判断异常。
解决方案
改用状态数组记录每个格子的占用状态(空、玩家O、电脑X),完全脱离对img.src的依赖,这是更可靠的游戏状态管理方式。
修改后的完整代码
JavaScript
const greenO = "https://www.freeiconspng.com/uploads/green-circle-png-10.png" const redX = "https://pnghq.com/wp-content/uploads/pnghq.com-download-red-cross-mark-download-png-hq-png-image.png" const slots = document.getElementsByClassName("slots") const slotImages = document.getElementsByClassName("slot-images") let playerClickAvailable = true let computerMoveAvailable = false // 状态数组:0=空,1=玩家O,2=电脑X let boardState = Array(9).fill(0) for (let i = 0; i <= 8; i++) { slots[i].addEventListener("click", function() { playerClick(i) }) } function playerClick(i) { if (playerClickAvailable && boardState[i] === 0) { const img = slotImages[i] img.src = greenO img.style.display = "block" boardState[i] = 1 playerClickAvailable = false computerMoveAvailable = true if (!checkWin()) { setTimeout(computerMove, 750); } } } function computerMove() { if (!computerMoveAvailable) return // 检查是否平局 const isFull = boardState.every(state => state !== 0) if (isFull) { console.log("tie") document.getElementById("reset").style.display = "block" return } // 随机找空位置 let randomIndex do { randomIndex = Math.floor(Math.random() * 9) } while (boardState[randomIndex] !== 0) const img = slotImages[randomIndex] img.src = redX img.style.display = "block" boardState[randomIndex] = 2 playerClickAvailable = true computerMoveAvailable = false checkWin() } function giveWin(winner) { playerClickAvailable = false computerMoveAvailable = false document.getElementById("reset").style.display = "block" console.log(winner === 1 ? "player won" : "computer won") return winner === 1 ? "player" : "computer" } function checkWin() { // 所有获胜组合 const winPatterns = [ [0,1,2], [3,4,5], [6,7,8], // 横向 [0,3,6], [1,4,7], [2,5,8], // 纵向 [0,4,8], [2,4,6] // 对角线 ] for (const pattern of winPatterns) { const [a, b, c] = pattern if (boardState[a] !== 0 && boardState[a] === boardState[b] && boardState[a] === boardState[c]) { return giveWin(boardState[a]) } } return null } function reset() { // 重置状态数组 boardState = Array(9).fill(0) // 重置UI for (let i = 0; i <= 8; i++) { const img = slotImages[i] img.src = "" img.style.display = "none" } document.getElementById("reset").style.display = "none" playerClickAvailable = true computerMoveAvailable = false }
CSS(无需修改)
body { min-height: 800; min-width: 800; } .center-flex { display: flex; justify-content: center; } #main-container { width: 600px; height: 600px; display: grid; grid-template: repeat(3, 1fr) / repeat(3, 1fr); gap: 15px; margin-bottom: 100px; } .slots { display: flex; justify-content: center; align-items: center; border-radius: 10%; padding: 15px; border: 10px solid rgb(71, 71, 71); background-color: cadetblue; } .slot-images { width: 100%; height: 100%; display: none; } #reset { width: 200px; height: 75px; display: none; border: 3px solid black; font-size: 50px; border-radius: 15px; } #reset-container { display: flex; justify-content: center; } #game-container { display: flex; justify-content: center; align-items: center; }
HTML(无需修改)
<div id="game-container"> <div id="main-container"> <button class="slots"><img class="slot-images"></button> <button class="slots"><img class="slot-images"></button> <button class="slots"><img class="slot-images"></button> <button class="slots"><img class="slot-images"></button> <button class="slots"><img class="slot-images"></button> <button class="slots"><img class="slot-images"></button> <button class="slots"><img class="slot-images"></button> <button class="slots"><img class="slot-images"></button> <button class="slots"><img class="slot-images"></button> </div> </div> <div id="reset-container"> <button id="reset" onclick="reset()">Reset!</button> </div>
关键修改点
- 新增
boardState数组,用数字0/1/2记录每个格子的状态,彻底避免src解析问题 - 所有判断逻辑(空位置、获胜条件)都基于
boardState,不再依赖img.src - 简化了平局判断和获胜组合的写法,代码更易维护
- 移除了冗余的嵌套函数
blockMoves(),直接在giveWin()里修改状态
内容的提问来源于stack exchange,提问作者MistyKing
相关产品推荐
相关产品推荐

