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

JavaScript扫雷游戏数组匹配问题:判断雷位恒返回false

解决JavaScript扫雷游戏中数组比较的问题

嘿,我明白你碰到的麻烦了!在JavaScript里直接用==或者===比较两个数组根本行不通——因为数组是引用类型,这类比较判断的是两个数组是否指向内存里的同一个地址,而不是它们的内容是否一致。哪怕两个数组的元素完全一样,只要是不同的实例,结果就会是false,这就是你当前问题的根源。

先拆解你代码里的问题

在Mine构造函数的循环中,你每次用bombs[iter] == [this.x,this.y]做判断,右边的[this.x,this.y]是一个全新创建的数组,它和bombs里存储的数组肯定不是同一个引用,所以这个判断永远会返回false。而且循环最后一次如果不匹配,this.isBomb会被设为false,覆盖之前可能的true,导致所有Mine实例的isBomb全是false。

另外,你的炸弹生成逻辑还有个小漏洞:如果随机生成的位置重复了,bombs[i] = position不会执行,但i依然会递增,这会导致bombs数组里出现undefined的元素,后续判断也会出错。

三种可行的解决方案

1. 写个辅助函数比较数组内容

创建一个函数来检查两个数组的长度和对应元素是否完全一致:

function arraysEqual(arr1, arr2) {
  if (arr1.length !== arr2.length) return false;
  for (let i = 0; i < arr1.length; i++) {
    if (arr1[i] !== arr2[i]) return false;
  }
  return true;
}

然后修改Mine构造函数里的判断逻辑:

function Mine(x,y) {
  this.x = x;
  this.y = y;
  this.neighbors = findNeighbors(this.x,this.y);
  
  this.isBomb = false; // 默认不是炸弹
  for (var iter = 0; iter < bombs.length; iter++) {
    if (arraysEqual(bombs[iter], [this.x, this.y])) {
      this.isBomb = true;
      break; // 找到匹配后直接跳出循环,提升效率
    }
  }
  
  this.show = function() { return 'show' }
  this.setValue = function(value) { this.value = value; return value; }
}

2. 用JSON.stringify()转成字符串比较

把数组转换成字符串后再比较,适合元素都是简单类型(比如数字)的场景:

function Mine(x,y) {
  this.x = x;
  this.y = y;
  this.neighbors = findNeighbors(this.x,this.y);
  
  this.isBomb = false;
  const currentPosStr = JSON.stringify([this.x, this.y]);
  for (var iter = 0; iter < bombs.length; iter++) {
    if (JSON.stringify(bombs[iter]) === currentPosStr) {
      this.isBomb = true;
      break;
    }
  }
  
  // 其他方法...
}

3. 改进炸弹存储方式(推荐)

把炸弹的坐标从数组改成字符串(比如"x,y"格式),这样直接用includes()就能判断,代码更简洁高效:
首先修改setup里的炸弹生成逻辑(同时修复重复位置的问题):

function setup() {
  // create bombs
  bombs = []; // 先清空避免重复
  for (var i = 0; i < 45; ) { // 这里不先递增i,避免出现undefined
    var x = floor(random(0,15));
    var y = floor(random(0,15));
    var position = `${x},${y}`; // 用字符串存储坐标
    if (!bombs.includes(position)) {
      bombs.push(position);
      i++;
    }
  }
  
  // create board
  board = [];
  for (var y = 0; y < 15; y++) {
    board[y] = new Array();
    for (var x = 0; x < 15; x++) {
      board[y][x] = new Mine(y,x);
    }
  }
}

然后Mine构造函数里的判断就可以简化成一行:

function Mine(x,y) {
  this.x = x;
  this.y = y;
  this.neighbors = findNeighbors(this.x,this.y);
  
  this.isBomb = bombs.includes(`${this.x},${this.y}`); // 直接判断
  
  this.show = function() { return 'show' }
  this.setValue = function(value) { this.value = value; return value; }
}

额外提示

推荐第三种方法,不仅代码更简洁,字符串查找的效率也比循环比较数组要高,同时还修复了原炸弹生成逻辑里的undefined问题。

内容的提问来源于stack exchange,提问作者Jackson Long

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:08:07