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

Vanilla JS井字棋游戏:胜负/平局提示异常问题求助

井字棋游戏胜负与平局提示异常问题修复

我在用Vanilla JS开发井字棋游戏时遇到两个问题:

  • 玩家回合切换提示正常,但获胜提示始终不出现
  • 平局提示会在棋盘为空时自动弹出,无需任何操作

原实现代码

HTML部分

<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <link rel="stylesheet" href="style.css">
  </head>
<body>
<h1>TIC-TAC-TOE</h1>
<h2 id="player1"> Player 1: </h2>
<h2 id="player2">Player 2: </h2>
<h2 id="result"></h2>
<table id="board">
    <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>
<button>Restart</button>
</body>
<script src="app.js"></script>
</html>

JS部分

let players = ['x', 'o'] 

let board = [
    null, null, null,  
    null, null, null,
    null, null, null 
]

let boardWins = [
    [0, 1, 2], 
    [3, 4, 5], 
    [6, 7, 8],
    [0, 3, 6],
    [1, 4, 7],
    [2, 5, 8],
    [0, 4, 8],
    [2, 4, 6]
] 


let result = document.getElementById('result')
let cells = document.querySelectorAll('td')
let currentPlayer = players[0] 

cells.forEach(function(cell) { 
    cell.addEventListener('click', function() {
       
       if (cell.innerHTML != '') {
          return; 
        }  
          if (!cell) {
          return;
        }
        if (currentPlayer === players[0]) {
          currentPlayer = players[1] 
           cell.innerHTML = players[0]
           result.innerHTML = "Player O's turn!"
        } else if (currentPlayer === players[1]){
          currentPlayer = players[0]
           cell.innerHTML = players[1]
           result.innerHTML = "Player X's turn!"
        } 
    }) 
    wins() 
})

function wins() {
    for (let i = 0; i < boardWins.length; i++) {
        let win = boardWins[i] 
        let zero = win[0]
        let one = win[1]
        let two = win[2]
        if (board[zero] === players[0] && board[zero] === board[one] && board[zero] === board[two]) {
            result.innerHTML = 'Player X wins!'
        }
        else if (board[i] != null) {
            result.innerHTML = 'Draw!' 
        }
        }

    }
}

问题根源

  1. 获胜判断失效:board数组从未同步页面上的落子操作,始终是初始全null状态,导致胜负判断条件永远不满足。
  2. 平局提示异常:
    • wins()函数在页面加载时就被调用(cells.forEach里直接执行wins()),而非落子后触发
    • 平局判断逻辑错误:用board[i] != null,这里的i是获胜组合数组的索引(0-7),不是棋盘格子索引,只要board[0]到board[7]中有一个不为null就触发平局,完全不符合逻辑。
  3. 胜负检查时机错误:没有在每次玩家落子后立即检查胜负状态。

修复后的JS代码

let players = ['x', 'o'] 
let board = [null, null, null, null, null, null, null, null, null]
let boardWins = [
    [0, 1, 2], [3, 4, 5], [6, 7, 8],
    [0, 3, 6], [1, 4, 7], [2, 5, 8],
    [0, 4, 8], [2, 4, 6]
] 

let result = document.getElementById('result')
let cells = document.querySelectorAll('td')
let currentPlayer = players[0]
let gameOver = false // 新增游戏结束状态,防止后续操作

// 绑定格子点击事件
cells.forEach(function(cell, index) { // 获取cell索引,对应board数组位置
    cell.addEventListener('click', function() {
        if (gameOver || cell.innerHTML !== '') {
            return; // 游戏结束或格子已被占用,直接返回
        }

        // 落子并同步更新board数组
        cell.innerHTML = currentPlayer
        board[index] = currentPlayer

        // 检查是否获胜
        if (checkWinner()) {
            result.innerHTML = `Player ${currentPlayer.toUpperCase()} wins!`
            gameOver = true
            return
        }

        // 检查是否平局
        if (checkDraw()) {
            result.innerHTML = 'Draw!'
            gameOver = true
            return
        }

        // 切换玩家
        currentPlayer = currentPlayer === players[0] ? players[1] : players[0]
        result.innerHTML = `Player ${currentPlayer.toUpperCase()}'s turn!`
    })
})

// 检查获胜逻辑
function checkWinner() {
    for (let win of boardWins) {
        const [a, b, c] = win
        if (board[a] && board[a] === board[b] && board[a] === board[c]) {
            return true
        }
    }
    return false
}

// 检查平局逻辑
function checkDraw() {
    return board.every(cell => cell !== null)
}

// 重启按钮功能
document.querySelector('button').addEventListener('click', function() {
    board.fill(null)
    cells.forEach(cell => cell.innerHTML = '')
    currentPlayer = players[0]
    gameOver = false
    result.innerHTML = `Player X's turn!`
})

关键修改点

  • 落子时通过格子索引同步更新board数组,让胜负判断有正确的数据依据
  • 将胜负、平局判断拆分为独立函数,逻辑更清晰
  • 新增gameOver状态,避免获胜或平局后继续落子
  • 调整检查时机,每次落子后立即判断胜负
  • 修复平局逻辑:通过board.every()判断所有格子是否被占用
  • 增加重启按钮功能,完善游戏体验

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 11:05:26