如何将井字棋的X/O字段值存入board数组以实现胜负判定?
井字棋:同步board数组与完成胜负判定方案
核心问题解决步骤:
1. 同步标记到board数组
原代码点击棋盘时仅更新DOM,未同步到gameBoard的board数组。需给每个棋盘格子绑定索引,点击时将对应标记存入数组:
- 在
fields.forEach循环中添加index参数,用于定位board数组位置 - 修正回合判断逻辑(原
turn %= 2是赋值操作,会导致回合混乱) - 根据当前回合的玩家标记,同步更新
board[index]
2. 实现胜负判定
在game对象的checkWinner函数中,遍历获胜组合数组,对比gameBoard.board中对应位置的标记是否一致且非空:
- 每次点击后调用
checkWinner,若检测到胜者则更新提示信息并标记游戏结束 - 当剩余可点击格子为0且无胜者时,触发平局提示
3. 修复重启按钮功能
原重启按钮仅尝试清空DOM,但未重置游戏状态和重新绑定事件:
- 循环清空每个field的内容和样式
- 重置
board数组、回合计数、剩余格子数、胜者状态 - 重新给每个field绑定点击事件(因原事件使用
{once:true},重启后需重新添加)
修改后的完整代码
JavaScript
// player factory function const createPlayer = (name, marker) => { return { name, marker } } // gameboard object const gameBoard = (() => { let board = Array(9).fill("") const fields = document.querySelectorAll(".field") const nextTurn = document.querySelector(".message") let turn = 0 // 绑定点击事件的函数,方便重启时复用 function bindFieldEvents() { fields.forEach((field, index) => { field.addEventListener('click', () => handleClick(field, index), { once: true }) }) } function handleClick(field, index) { const currentMarker = turn % 2 === 0 ? "X" : "O" // 更新DOM field.innerHTML = currentMarker field.classList.add("marker") // 同步到board数组 board[index] = currentMarker // 更新回合提示 nextTurn.innerHTML = turn % 2 === 0 ? "Player O's turn" : "Player X's turn" turn++ // 调用胜负判定 game.checkWinner() } // 重启游戏 const restart = document.getElementById("restart-button") restart.addEventListener("click", restartGame) function restartGame() { // 重置board数组 board = Array(9).fill("") turn = 0 game.resetGameState() // 清空DOM fields.forEach(field => { field.innerHTML = "" field.classList.remove("marker") }) nextTurn.innerHTML = "Player X's turn" // 重新绑定事件 bindFieldEvents() } // 初始化绑定事件 bindFieldEvents() return { getBoard: () => [...board], // 返回数组副本避免外部直接修改 restartGame } })() // game object const game = (() => { const playerOne = createPlayer("player x", "X") const playerTwo = createPlayer("player o", "O") let activePlayer = playerOne let winnerDeclared = false let remainingSpots = 9 const playerName = document.querySelector('.message') const winningConditions = [ [0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6] ]; function checkWinner() { const board = gameBoard.getBoard() // 遍历所有获胜组合 for (const condition of winningConditions) { const [a, b, c] = condition if (board[a] && board[a] === board[b] && board[a] === board[c]) { winnerDeclared = true playerName.innerHTML = `${board[a]} wins!` disableAllFields() return } } // 检查平局 remainingSpots-- if (!winnerDeclared && remainingSpots === 0) { declareTie() } } function declareTie() { playerName.innerHTML = "It's a tie!" } function disableAllFields() { document.querySelectorAll(".field").forEach(field => { field.replaceWith(field.cloneNode(true)) }) } function resetGameState() { winnerDeclared = false remainingSpots = 9 activePlayer = playerOne } return { checkWinner, resetGameState } })()
CSS
.gameboard{ display: grid; grid-template-columns: repeat(3,1fr); grid-gap: 5px; margin: 20px 0; } .field{ width: 150px; height: 150px; background-color: #ededee; display: flex; align-items: center; justify-content: center; font-size: 4rem; cursor: pointer; font-family: Arial, sans-serif; } .marker { color: #2c3e50; } .center { text-align: center; } #restart-button { padding: 10px 20px; font-size: 1rem; background-color: #3498db; color: white; border: none; border-radius: 4px; cursor: pointer; } #restart-button:hover { background-color: #2980b9; } .header-text { font-size: 2rem; text-align: center; padding: 15px 0; font-weight: bold; color: #2c3e50; } .message { text-align: center; font-size: 1.2rem; margin-bottom: 10px; color: #34495e; }
HTML
<div class="container"> <div class="header"> <div class="header-text"> Tic-Tac-Toe </div> </div> <div class="body-container"> <div class="message">Player X's turn</div> <div class="gameboard"> <div class="field"></div> <div class="field"></div> <div class="field"></div> <div class="field"></div> <div class="field"></div> <div class="field"></div> <div class="field"></div> <div class="field"></div> <div class="field"></div> </div> <div class="center"> <button id="restart-button">Restart</button> </div> </div> </div>
内容的提问来源于stack exchange,提问作者Master1
相关产品推荐
相关产品推荐

