使用JavaScript实现井字棋(TTT):点击格子生成X/O及功能实现问题
井字棋(Tic Tac Toe)完整实现方案
一、X/O的两种绘制方式
1. 文本方式(最简单)
直接修改格子的文本内容显示X/O,配合CSS美化字体样式,让符号更醒目直观。
2. CSS图形绘制(更美观)
利用CSS伪元素生成X和O,无需依赖图片,保持页面轻量化,还能自定义样式。
二、完整功能实现代码
以下是包含棋盘渲染、轮流下棋、胜负判定、平局检测和游戏重置的完整代码:
HTML结构
<div class="game-container"> <h1>井字棋</h1> <div class="board" id="board"></div> <div class="game-info"> <p id="status">轮到X下棋</p> <button id="resetBtn">重置游戏</button> </div> </div>
CSS样式
.game-container { text-align: center; font-family: Arial, sans-serif; } .board { display: grid; grid-template-columns: repeat(3, 100px); grid-template-rows: repeat(3, 100px); gap: 5px; margin: 20px auto; width: 310px; } .cell { background-color: #f0f0f0; border: 2px solid #333; display: flex; align-items: center; justify-content: center; font-size: 48px; font-weight: bold; cursor: pointer; } .cell.x { color: #ff4444; } .cell.o { color: #33b5e5; } .cell.disabled { cursor: not-allowed; } #status { font-size: 24px; margin-bottom: 10px; } #resetBtn { padding: 10px 20px; font-size: 18px; cursor: pointer; background-color: #4CAF50; color: white; border: none; border-radius: 5px; }
JavaScript逻辑
// 初始化游戏核心状态 const board = document.getElementById('board'); const statusText = document.getElementById('status'); const resetBtn = document.getElementById('resetBtn'); let currentPlayer = 'X'; let gameActive = true; let gameState = ['', '', '', '', '', '', '', '', '']; // 预定义获胜条件(对应棋盘格子索引组合) 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] ]; // 生成3x3棋盘格子 function createBoard() { gameState.forEach((_, index) => { const cell = document.createElement('div'); cell.classList.add('cell'); cell.dataset.index = index; cell.addEventListener('click', handleCellClick); board.appendChild(cell); }); } // 处理格子点击事件 function handleCellClick(e) { const cell = e.target; const index = parseInt(cell.dataset.index); // 格子已被占用或游戏结束时,不响应点击 if (gameState[index] !== '' || !gameActive) return; // 更新游戏状态与界面显示 gameState[index] = currentPlayer; cell.textContent = currentPlayer; cell.classList.add(currentPlayer.toLowerCase(), 'disabled'); checkGameResult(); } // 检查游戏结果(胜负/平局) function checkGameResult() { let roundWon = false; // 遍历所有获胜条件,判断是否达成连线 for (let i = 0; i < winningConditions.length; i++) { const [a, b, c] = winningConditions[i]; if (gameState[a] && gameState[a] === gameState[b] && gameState[a] === gameState[c]) { roundWon = true; break; } } if (roundWon) { statusText.textContent = `${currentPlayer}获胜!`; gameActive = false; return; } // 检查平局:所有格子填满且无胜者 const roundDraw = !gameState.includes(''); if (roundDraw) { statusText.textContent = '平局!'; gameActive = false; return; } // 切换当前玩家 currentPlayer = currentPlayer === 'X' ? 'O' : 'X'; statusText.textContent = `轮到${currentPlayer}下棋`; } // 重置游戏状态 function resetGame() { currentPlayer = 'X'; gameActive = true; gameState = ['', '', '', '', '', '', '', '', '']; statusText.textContent = '轮到X下棋'; // 清空所有格子的内容与状态类 document.querySelectorAll('.cell').forEach(cell => { cell.textContent = ''; cell.classList.remove('x', 'o', 'disabled'); }); } // 初始化游戏 createBoard(); resetBtn.addEventListener('click', resetGame);
三、核心功能说明
- 轮流下棋:通过
currentPlayer变量切换X/O,每次有效点击后更新玩家状态。 - 胜负判定:遍历预定义的获胜条件数组,检查是否有三个相同符号连成一线。
- 平局检测:判断游戏状态数组中是否存在空值,无空值则判定为平局。
- 防重复点击:给已点击的格子添加
disabled类,阻止二次操作。
内容的提问来源于stack exchange,提问作者john james
相关产品推荐
相关产品推荐

