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

井字棋游戏重置后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>

关键修改点

  1. 新增boardState数组,用数字0/1/2记录每个格子的状态,彻底避免src解析问题
  2. 所有判断逻辑(空位置、获胜条件)都基于boardState,不再依赖img.src
  3. 简化了平局判断和获胜组合的写法,代码更易维护
  4. 移除了冗余的嵌套函数blockMoves(),直接在giveWin()里修改状态

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 23:12:04