我的JavaScript四子棋checkWin函数为何未按预期工作?
四子棋checkWin函数功能异常修复
我写的JavaScript四子棋checkWin函数没按预期工作,逻辑是记录玩家每一步到数组后检查获胜条件,但现在会错误触发胜利提示(未达成四子连线却显示Win)。
原函数代码:
function checkWin(CheckArray){ for(i = 0; i<CheckArray.length; i++){ if(CheckArray.includes(CheckArray[i] && CheckArray[i] + width && CheckArray[i] + (2*width) && CheckArray[i] + (3*width)) || CheckArray.includes(CheckArray[i] && CheckArray[i] + 1 && CheckArray[i] + 2 && CheckArray[i]+3) || CheckArray.includes(CheckArray[i] &&CheckArray[i] + (width-1) && CheckArray[i]+2*(width+1) && CheckArray[i] + 3*(width-1)) || CheckArray.includes(CheckArray[i] && CheckArray[i] + (width+1) && CheckArray[i] + 2*(width+1) && CheckArray[i] + 3*(width+1)){ disCurrentPlayer.innerHTML=` Win`; } } }
错误原因分析
- 逻辑判断完全错误:
CheckArray.includes(CheckArray[i] && ...)是把多个值做逻辑与运算后,只检查最后一个值是否在数组里,而不是同时验证四个值都存在。比如a && b会返回b(若a为真),导致只要最后一个值存在就触发胜利,完全不符合四子连线的要求。 - 循环变量未声明:
i没有用let/var声明,会变成全局变量,可能引发其他代码冲突。 - 斜向位置计算错误:第三个条件里的
CheckArray[i]+2*(width+1)是错误的,右上到左下的斜向每步应该加width-1,这里应该写成CheckArray[i] + 2*(width-1)。 - 未终止循环:找到胜利条件后仍继续循环,会重复修改DOM,造成不必要的性能浪费。
- 缺少边界检查:比如横向判断时,没有确保四个棋子在同一行,可能把跨行列的位置误判为连线。
修复后的代码
function checkWin(CheckArray) { for (let i = 0; i < CheckArray.length; i++) { const currentPos = CheckArray[i]; // 纵向连线:当前位置 + width*1、*2、*3 const isVerticalWin = CheckArray.includes(currentPos + width) && CheckArray.includes(currentPos + 2 * width) && CheckArray.includes(currentPos + 3 * width); // 横向连线:当前位置 +1、+2、+3,且在同一行 const currentCol = currentPos % width; const isHorizontalWin = CheckArray.includes(currentPos + 1) && CheckArray.includes(currentPos + 2) && CheckArray.includes(currentPos + 3) && currentCol + 3 < width; // 右上到左下斜向连线:+width-1、+2*(width-1)、+3*(width-1),且不超出左边界 const isDiagonalLeftWin = CheckArray.includes(currentPos + (width - 1)) && CheckArray.includes(currentPos + 2 * (width - 1)) && CheckArray.includes(currentPos + 3 * (width - 1)) && currentCol >= 3; // 左上到右下斜向连线:+width+1、+2*(width+1)、+3*(width+1),且不超出右边界 const isDiagonalRightWin = CheckArray.includes(currentPos + (width + 1)) && CheckArray.includes(currentPos + 2 * (width + 1)) && CheckArray.includes(currentPos + 3 * (width + 1)) && currentCol + 3 < width; if (isVerticalWin || isHorizontalWin || isDiagonalLeftWin || isDiagonalRightWin) { disCurrentPlayer.innerHTML = ` Win`; // 找到胜利条件后立即终止函数,避免无效循环 return; } } }
修复说明
- 拆分每个方向的判断为单独变量,代码更易读和调试。
- 新增行列边界检查,避免跨行列的误判。
- 用
let声明循环变量i,避免全局污染。 - 找到胜利条件后用
return终止函数,减少不必要的计算。
内容的提问来源于stack exchange,提问作者liz
相关产品推荐
相关产品推荐

