# ===== CodeLab: game-js-ttt ===== # 以下代码片段按文章出现顺序拼接, 共 6 段 # ----- 片段 1 (html) -----

井字棋

轮到 X

# ----- 片段 2 (css) ----- #board { display: grid; grid-template-columns: repeat(3, 100px); gap: 4px; } .cell { width: 100px; height: 100px; background: #f8f9fa; border-radius: 8px; display: flex; align-items: center; justify-content: center; font-size: 2.5rem; cursor: pointer; user-select: none; } .cell:hover { background: #e9ecef; } # ----- 片段 3 (javascript) ----- const board = new Array(9).fill(null); let current = 'X'; let gameOver = false; const statusEl = document.getElementById('status'); const cells = document.querySelectorAll('.cell'); function render() { cells.forEach((cell, i) => { cell.textContent = board[i]; }); } # ----- 片段 4 (javascript) ----- const lines = [ [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 checkWin(player) { return lines.some(line => line.every(i => board[i] === player) ); } function handleClick(e) { if (gameOver) return; const i = Number(e.target.dataset.index); if (board[i]) return; board[i] = current; render(); if (checkWin(current)) { statusEl.textContent = current + ' 赢了!🎉'; gameOver = true; } else if (board.every(c => c)) { statusEl.textContent = '平局!'; gameOver = true; } else { current = current === 'X' ? 'O' : 'X'; statusEl.textContent = '轮到 ' + current; } } cells.forEach(cell => cell.addEventListener('click', handleClick)); # ----- 片段 5 (javascript) ----- function aiMove() { for (let i = 0; i < 9; i++) { if (!board[i]) { board[i] = 'O'; if (checkWin('O')) return i; board[i] = null; } } for (let i = 0; i < 9; i++) { if (!board[i]) { board[i] = 'X'; if (checkWin('X')) return i; board[i] = null; } } const empty = []; board.forEach((c, i) => { if (!c) empty.push(i); }); return empty[Math.floor(Math.random() * empty.length)]; } # ----- 片段 6 (javascript) ----- function applyMove(i) { board[i] = current; render(); if (checkWin(current)) { statusEl.textContent = current + ' 赢了!🎉'; gameOver = true; } else if (board.every(c => c)) { statusEl.textContent = '平局!'; gameOver = true; } else { current = current === 'X' ? 'O' : 'X'; statusEl.textContent = '轮到 ' + current; } } function handleClick(e) { if (gameOver) return; const i = Number(e.target.dataset.index); if (board[i]) return; applyMove(i); if (!gameOver && current === 'O') { setTimeout(() => { applyMove(aiMove()); }, 300); } }