JavaScript扫雷克隆项目边界单元格调试求助
扫雷克隆项目边界单元格标记问题排查
核心问题分析
你在开发Windows经典扫雷克隆时,单元格编号从1开始,通过编号加减判断炸弹周围的绿色/蓝色提示单元格,但边界处出现错误标记,根源是边界判断逻辑错误,直接用编号加减+模运算的方式容易出现跨边界误判。
1. 绿色单元格的无效边界判断
你尝试的这段代码逻辑完全错误,导致条件从未触发:
if (bombsArray.includes(cellNumb) == (gridLenght * 10)) { singleCell.classList.remove('green'); console.log("bomb on the right border"); }
bombsArray.includes(cellNumb)返回布尔值(true/false),和数值gridLength*10比较永远为false,条件不可能成立- 判断炸弹是否在右边界,应直接检查单元格的列位置,而非和固定数值比较
2. 蓝色单元格的跨边界错误
你的twoLeftSide和twoRightSide判断逻辑错误,导致边界处误判:
const twoLeftSide = (cellNumb - 1) % gridLength === 0 || (cellNumb) % gridLength === 2; const twoRightSide = cellNumb % gridLength === 0 || (cellNumb + 1) % gridLength === 0;
- 这种模运算写法无法准确判断“是否有足够空间向左/右延伸2个单元格”,比如单元格在最左列时,
cellNumb%gridLength===2完全不成立,导致!twoLeftSide为true,错误允许向左减2,从而跨边界到另一侧单元格
修正方案:用行列坐标替代纯编号判断
把单元格编号转换成行号+列号,边界判断会更直观,避免模运算混乱:
let gridLength = Math.sqrt(numbOfCells); const cellNumb = Number(singleCell.textContent); // 转换为行号(从1开始) const row = Math.ceil(cellNumb / gridLength); // 转换为列号(从1开始) const column = ((cellNumb - 1) % gridLength) + 1;
修正绿色单元格的边界判断
重新梳理绿色单元格条件,每个方向先判断是否越界,再检查炸弹数组:
if (bombsArray.includes(cellNumb)) { singleCell.classList.add('bomb'); } else if ( // 左边单元格 (column > 1 && bombsArray.includes(cellNumb - 1)) || // 右边单元格 (column < gridLength && bombsArray.includes(cellNumb + 1)) || // 上边单元格 (row > 1 && bombsArray.includes(cellNumb - gridLength)) || // 下边单元格 (row < gridLength && bombsArray.includes(cellNumb + gridLength)) || // 左上对角线 (row > 1 && column > 1 && bombsArray.includes(cellNumb - gridLength - 1)) || // 右上对角线 (row > 1 && column < gridLength && bombsArray.includes(cellNumb - gridLength + 1)) || // 左下对角线 (row < gridLength && column > 1 && bombsArray.includes(cellNumb + gridLength - 1)) || // 右下对角线 (row < gridLength && column < gridLength && bombsArray.includes(cellNumb + gridLength + 1)) ) { singleCell.classList.add('green'); singleCell.addEventListener('click', addGreenPoints); }
修正蓝色单元格的边界判断
先修正twoLeftSide和twoRightSide的逻辑,再逐一修正每个方向的条件:
// 判断是否无法向左延伸2个单元格(列1或列2) const twoLeftSide = column <= 2; // 判断是否无法向右延伸2个单元格(列gridLength或gridLength-1) const twoRightSide = column >= gridLength - 1; // 判断是否无法向上延伸2行 const twoTopSide = row <= 2; // 判断是否无法向下延伸2行 const twoBottomSide = row >= gridLength - 1; // 蓝色单元格条件 else if ( // 左2单元格 (!twoLeftSide && bombsArray.includes(cellNumb - 2)) || // 右2单元格 (!twoRightSide && bombsArray.includes(cellNumb + 2)) || // 上2单元格 (!twoTopSide && bombsArray.includes(cellNumb - gridLength * 2)) || // 下2单元格 (!twoBottomSide && bombsArray.includes(cellNumb + gridLength * 2)) || // 左上2对角线(↖↖) (!twoTopSide && !twoLeftSide && bombsArray.includes(cellNumb - gridLength * 2 - 2)) || // 左上1对角线(↖) (!twoTopSide && column > 1 && bombsArray.includes(cellNumb - gridLength * 2 - 1)) || // 右上1对角线(↗) (!twoTopSide && column < gridLength && bombsArray.includes(cellNumb - gridLength * 2 + 1)) || // 右上2对角线(↗↗) (!twoTopSide && !twoRightSide && bombsArray.includes(cellNumb - gridLength * 2 + 2)) || // 右上侧右1(➡) (!twoTopSide && !twoRightSide && bombsArray.includes(cellNumb - gridLength + 2)) || // 右下侧右1(↘) (!twoBottomSide && !twoRightSide && bombsArray.includes(cellNumb + gridLength + 2)) || // 右下2对角线(↘↘) (!twoBottomSide && !twoRightSide && bombsArray.includes(cellNumb + gridLength * 2 + 2)) || // 右下1对角线(↘) (!twoBottomSide && column < gridLength && bombsArray.includes(cellNumb + gridLength * 2 + 1)) || // 左下1对角线(↙) (!twoBottomSide && column > 1 && bombsArray.includes(cellNumb + gridLength * 2 - 1)) || // 左下2对角线(↙↙) (!twoBottomSide && !twoLeftSide && bombsArray.includes(cellNumb + gridLength * 2 - 2)) || // 左下侧左1(⬅) (!twoBottomSide && !twoLeftSide && bombsArray.includes(cellNumb + gridLength - 2)) || // 左上侧左1(⬅) (!twoTopSide && !twoLeftSide && bombsArray.includes(cellNumb - gridLength - 2)) ) { singleCell.classList.add('blue'); singleCell.addEventListener('click', addBluePoints); }
额外优化建议
- 把行列坐标的转换逻辑封装成函数,避免重复代码
- 提前计算所有炸弹的行列位置,直接判断当前单元格的行列是否在炸弹的绿色/蓝色范围内,比反复调用
bombsArray.includes()效率更高
内容的提问来源于stack exchange,提问作者Pietro_
相关产品推荐
相关产品推荐

