0

0

Tic Tac Toe 游戏提前判定胜利失效的修复指南

碧海醫心

碧海醫心

发布时间:2026-02-11 09:34:05

|

131人浏览过

|

来源于php中文网

原创

Tic Tac Toe 游戏提前判定胜利失效的修复指南

本文详解 tic tac toe 游戏中“获胜后仍继续输入”的典型 bug,核心原因是 `haslastmoverwon` 函数参数顺序错误及 `prompt` 返回值处理不当,导致胜负检测逻辑失效。

在实现井字棋(Tic Tac Toe)这类回合制游戏时,一个常见却隐蔽的逻辑缺陷是:游戏在某一方已达成三连胜条件后,仍未终止循环,反而继续提示玩家输入,直至棋盘填满才判定为平局。这不仅破坏用户体验,更暴露了状态检测与控制流设计的关键漏洞。

问题根源在于两个关键函数的签名与调用不匹配:

? 1. 参数顺序错误:hasLastMoverWon 的致命错位

原始代码中,hasLastMoverWon 定义为:

function hasLastMoverWon(currentPlayerSymbol, gameBoard) { ... }

但在 isGameOver 中却被错误地调用为:

hasLastMoverWon(gameBoard, currentPlayerSymbol) // ❌ 顺序颠倒!

由于 JavaScript 不校验参数类型与顺序,该调用会静默传入错误参数:currentPlayerSymbol(如 "X")被当作 gameBoard 数组使用,而 gameBoard 被误作 currentPlayerSymbol 字符串。结果是 gameBoard[i1] 实际访问的是字符串 "X"[0](即 "X"),后续所有索引访问均返回 undefined,导致胜利检测恒为 false。

修复方案:统一函数签名与调用顺序,确保 gameBoard 始终为第一参数:

创客贴设计
创客贴设计

创客贴设计,一款智能在线设计工具,设计不求人,AI助你零基础完成专业设计!

下载
function hasLastMoverWon(gameBoard, currentPlayerSymbol) { /* 正确实现 */ }
// 对应调用:
if (hasLastMoverWon(gameBoard, currentPlayerSymbol)) { ... }

⚠️ 2. 输入处理缺陷:prompt 返回值未正确解析

原始 getUserInput 中对 prompt 结果直接使用 +prompt(...) 强转数字:

return +prompt(...); // 若用户点取消 → 返回 NaN;点确定但留空 → 返回 0

这会导致:

  • 用户点击「取消」时,NaN 被传入 isMoveValid,gameBoard[NaN] 为 undefined → undefined === null 为 false,验证失败,但 do...while 循环可能因 NaN 的特殊性陷入异常行为;
  • 更稳妥的做法是显式检查 null(用户取消)并抛出异常或退出。

增强健壮性:在 makeAMove 中添加取消处理:

function makeAMove(gameBoard, nextPlayerSymbol) {
  const newGameBoard = [...gameBoard];
  let move;
  do {
    move = getUserInput(nextPlayerSymbol, gameBoard);
    if (move === null) throw new Error("Game interrupted by user");
  } while (!isMoveValid(move, gameBoard));
  newGameBoard[move] = nextPlayerSymbol;
  return newGameBoard;
}

function getUserInput(nextPlayerSymbol, gameBoard) {
  const input = prompt(`${getboardstring(gameBoard)}\n dove vuoi posizionare la ${nextPlayerSymbol}?`);
  return input === null ? null : Number(input); // 显式转换,保留 null 语义
}

✅ 完整修复后的核心逻辑(精简版)

function isGameOver(gameBoard, currentPlayerSymbol) {
  // ✅ 正确调用:board 在前,符号在后
  if (hasLastMoverWon(gameBoard, currentPlayerSymbol)) {
    alert(`${currentPlayerSymbol} has won the game!`);
    return true;
  }
  if (!gameBoard.includes(null)) {
    alert(`Game ended in a draw`);
    return true;
  }
  return false;
}

function ticTacToe() {
  let gameBoard = Array(9).fill(null);
  let currentPlayerSymbol = 'X'; // 初始化为 X,避免 null 切换歧义
  while (true) {
    gameBoard = makeAMove(gameBoard, currentPlayerSymbol);
    if (isGameOver(gameBoard, currentPlayerSymbol)) break;
    currentPlayerSymbol = currentPlayerSymbol === 'X' ? 'O' : 'X';
  }
}

? 注意事项与最佳实践

  • 参数顺序一致性:在多人协作或长期维护项目中,建议使用 JSDoc 注释明确参数含义,或借助 TypeScript 提供编译期检查。
  • 输入验证前置:prompt/confirm 等用户输入应视为不可信源,始终验证 null、空字符串、非数字等边界情况。
  • 避免隐式类型转换:+prompt() 易引发 NaN 问题,推荐 Number(prompt()) 配合显式 isNaN() 检查。
  • 循环结构优化:do...while 适合“至少执行一次”的场景,但此处更推荐 while(true) + break,逻辑更清晰且易控制退出点。

修复后,游戏将在任一玩家达成胜利组合(如 [0,1,2] 全为 'X')的立即下一轮检测中弹出胜利提示并终止,彻底解决“赢了还继续下”的体验断层。

在线游戏
在线游戏

海量精品小游戏合集,无需安装即点即玩,休闲益智、动作闯关应有尽有,秒开即玩,轻松解压,快乐停不下来

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

243

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

664

2024.03.01

while的用法
while的用法

while的用法是“while 条件: 代码块”,条件是一个表达式,当条件为真时,执行代码块,然后再次判断条件是否为真,如果为真则继续执行代码块,直到条件为假为止。本专题为大家提供while相关的文章、下载、课程内容,供大家免费下载体验。

101

2023.09.25

java中break的作用
java中break的作用

本专题整合了java中break的用法教程,阅读专题下面的文章了解更多详细内容。

120

2025.10.15

java break和continue
java break和continue

本专题整合了java break和continue的区别相关内容,阅读专题下面的文章了解更多详细内容。

258

2025.10.24

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

485

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

213

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1544

2023.10.24

包子漫画网页版入口与全集阅读指南_正版免费漫画快速访问方法
包子漫画网页版入口与全集阅读指南_正版免费漫画快速访问方法

本专题汇总了包子漫画官网和网页版入口,提供最新章节抢先看方法、正版免费阅读指南,以及稳定访问方式,帮助用户快速直达包子漫画页面,无广告畅享全集漫画内容。

50

2026.02.10

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号