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

使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 19:55:18