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

井字棋游戏无法结束并提示平局问题求助

问题:井字棋游戏平局判断异常

我开发的井字棋游戏可以正常运行并判定胜负,但无法在无胜者的游戏结束时提示平局。尝试在getWinner()函数中添加平局返回逻辑时,要么游戏仅点击一次就结束,要么平局提示不生效。怀疑是for循环逻辑有问题,但找不到具体原因。


现有代码

JavaScript

/*----- constants -----*/
// 选中格子的背景色:玩家1(1)为粉色+X,玩家2(-1)为浅绿色+O
const COLORS = {
  '0': 'white',
  '1': 'pink',
  '-1': 'lightgreen'
};

// 选中格子的标记:X或O
const MARK = {
  '0': '',
  '1': 'X',
  '-1': 'O'
};

// 获胜组合
const COMBOS = [
  [0, 1, 2],
  [3, 4, 5],
  [6, 7, 8],
  [6, 4, 2],
  [0, 4, 8],
  [0, 3, 6],
  [1, 4, 7],
  [2, 5, 8]
];

/*----- 状态变量 -----*/
let board; // 9个格子的数组
let turn; // 当前玩家:1或-1
let winner; // null=无胜者;1/-1=对应玩家获胜;'T'=平局

/*----- 缓存DOM元素 -----*/
const message = document.querySelector('h1');
const resetButton = document.querySelector('button');

/*----- 事件监听 -----*/
document.getElementById('board').addEventListener('click', handleClick);
resetButton.addEventListener('click', init);

/*----- 函数定义 -----*/
init();
// 初始化状态并渲染页面
function init() {
  board = [0, 0, 0, 0, 0, 0, 0, 0, 0];
  turn = 1;
  winner = null;
  render();
}

// 将状态可视化到DOM
function render() {
  renderBoard();
  renderMessage();
}

// 渲染棋盘
function renderBoard() {
  board.forEach(function(boardVal, boardIdx) {
    const squareId = `box-${boardIdx}`;
    const squareEl = document.getElementById(squareId);
    // 设置玩家选中后的样式
    squareEl.style.backgroundColor = COLORS[boardVal];
    squareEl.innerHTML = MARK[boardVal];
    squareEl.style.display = 'flex';
    squareEl.style.justifyContent = 'center';
    squareEl.style.alignItems = 'center';
    squareEl.style.fontSize = '19vmin';
  });
}

// 显示当前回合或胜负结果
function renderMessage() {
  if (winner === 'T') {
    message.innerHTML = '平局!游戏结束!';
  } else if (winner) {
    message.innerHTML = `玩家${MARK[winner]}获胜!`;
  } else {
    message.innerHTML = `玩家${MARK[turn]}的回合`;
  }
}

// 处理格子点击事件
function handleClick(event) {
  const boxIdx = parseInt(event.target.id.replace('box-', ''));
  // 点击无效区域、格子已被占用或已有胜者时,终止函数
  if (isNaN(boxIdx) || board[boxIdx] || winner)
    return;
  // 更新棋盘状态为当前玩家标识
  board[boxIdx] = turn;
  // 切换玩家
  turn *= -1;
  // 检查胜负
  winner = getWinner();
  render();
}

// 判断胜负:返回1/-1(胜者)、'T'(平局)、null(游戏继续)
// 这里遇到了瓶颈,参考过示例并研究了Math.abs函数,但还是没搞定
function getWinner() {
  for (let i = 0; i < COMBOS.length; i++) {
    if (Math.abs(board[COMBOS[i][0]] + board[COMBOS[i][1]] + board[COMBOS[i][2]]) === 3) {
      return board[COMBOS[i][0]];
    } else if (board.includes(null)) {
      return null;
    }
  }
  // return 'T'; 
  // 启用这行代码后,游戏只点击一次就结束了
}

CSS

* {
  box-sizing: border-box;
}

body {
  height: 100vh;
  margin: 0;
  font-family: 'Raleway', sans-serif;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

header {
  margin-top: 5vmin;
  font-size: 10vmin;
  color: darkslategrey;
}

h1 {
  color: slategrey;
}

#board {
  display: grid;
  grid-template-columns: repeat(3, 20vmin);
  grid-template-rows: repeat(3, 20vmin);
}

#board>div {
  border: 0.5vmin solid slategrey;
}

button {
  margin-top: 5vmin;
  margin-bottom: 5vmin;
  padding: 2vmin;
  font-size: 3vmin;
  border-radius: 4vmin;
  border: 0.5vmin solid lightslategrey;
  background-color: aliceblue;
  color: darkslategrey;
}

button:hover {
  color: azure;
  background-color: cadetblue;
}

HTML

<link href="https://fonts.googleapis.com/css2?family=Raleway:wght@100&display=swap" rel="stylesheet">

<header>Tic-Tac-Toe</header>
<h1>X's Turn</h1>
<section id="board">
  <div id="box-0"></div>
  <div id="box-1"></div>
  <div id="box-2"></div>
  <div id="box-3"></div>
  <div id="box-4"></div>
  <div id="box-5"></div>
  <div id="box-6"></div>
  <div id="box-7"></div>
  <div id="box-8"></div>
</section>
<button>Reset Match</button>

问题分析与修复

你的getWinner()函数存在两个关键问题:

  1. 循环内提前终止逻辑错误:遍历赢局组合时,只要第一个组合不满足胜负条件,就执行else if分支返回null,直接终止函数,导致后续赢局组合无法被检查,游戏会提前判定为无胜者。
  2. 空格子判断逻辑错误:初始化的board数组元素是0而非null,所以board.includes(null)永远为false,这行判断完全无效。

修复后的getWinner()函数

function getWinner() {
  // 先遍历所有赢局组合,检查是否有胜者
  for (let i = 0; i < COMBOS.length; i++) {
    const sum = board[COMBOS[i][0]] + board[COMBOS[i][1]] + board[COMBOS[i][2]];
    if (Math.abs(sum) === 3) {
      return board[COMBOS[i][0]];
    }
  }
  // 检查棋盘是否已满(无空格子),满了则返回平局
  if (!board.includes(0)) {
    return 'T';
  }
  // 棋盘未满且无胜者,返回null表示游戏继续
  return null;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 18:34:53