检查二维数组中相邻方块的值

Posted

技术标签:

【中文标题】检查二维数组中相邻方块的值【英文标题】:Check value of neighbouring squares in 2D array 【发布时间】:2014-04-03 18:22:25 【问题描述】:

我正在创建一个带有 2D 阵列的简单扫雷板。我想用各自的数字填充“炸弹”周围的方块。 我不需要关心我创建的板是否可以解决。 (这里不重要)

我的问题是:我们如何才能优雅地填充数字而不像硬编码一样列出所有可能性?

我现在想出的是一个巨大的嵌套 if 语句来检查邻居是否是

 -Inside bounds of array
 -Is it a bomb
 -Is it empty
 -Is it already a number

它看起来非常长并且是硬编码的。

有没有一种简单而优雅的方法来检查二维矩阵中邻居的值?

我意识到在用 Python 语言询问 SO 中有类似的问题,那里的解决方案非常“pythonic”。我正在寻找一种简单的方法,只需在一个简单的二维数组上使用简单的结构,如(循环、if 语句等)。

想象一下,这个任务是交给一个只知道 if 语句和循环等基础知识的编程新学生。因此,应避免使用 lambda、递归、迭代器等建议的解决方案。

【问题讨论】:

你不能只遍历炸弹并在每个炸弹周围的 8 个单元中增加一个计数器吗?当然,您仍然需要进行适当的边界检查,以免尝试访问不存在的单元格。 @mhj 这就是我的观点。但是,如果不列出所有可能性,你怎么做呢?目前我列出了所有方向 - NW,N,NE,W,E,SW,S,SE。一个长嵌套的 if 解决方案,我正在寻找用循环或简单的东西替换它的方法。 好吧,我假设您知道二维数组中炸弹位置的 x 和 y 索引。所以找到它们相邻的 8 个单元只需要访问 index[x-1][y-1] (NW), index[x][y-1] (N), index[x+1][y-1 ] (NE)、index[x-1][y] (W) 等等。您只需为每个炸弹执行一次,因此无需遍历整个网格。 @Mhj 对不起,如果我没有明确指定我的问题。目前我已经在检查炸弹的邻居了。但我正在寻找简化邻居检查算法的方法。 我想我会建议一种不同的方法。从一个空板开始 - 每个条目都是 0。然后迭代你想要放置的炸弹数量 - 对于每个炸弹,选择一个随机位置,检查碰撞并重新拾取,直到你有一个没有炸弹的地方前。然后在该单元格中放置一个“炸弹”值,并增加(最多)八个不是炸弹的邻居的计数。这可能比尝试后处理步骤更简单。此外,在 10x10 阵列的中心放置一个 8x8 网格以避免边界复杂化... 【参考方案1】:

检查邻居时复杂的一个主要原因是边界。例如,如果您在第一行的一个单元格中,您不想检查上面的三个邻居,因为它们会在数组之外。

有几种常用的方法可以消除边界检查。假设您有一个具有如下接口的类:

class Board 
  public:
    bool IsBomb(int row, int col) const;
    int GetCount(int row, int col) const;
    ...
;

您可以在IsBomb 方法的实现中隐藏边界检查。例如,如果您调用 IsBomb 时使用的坐标位于运动场之外,它应该返回 false 而不是实际查看数组(或任何您的存储机制)。现在GetCount 可以简单地为所有八个邻居调用 IsBomb,而不必担心这些邻居中的任何一个是否超出了运动场的边缘。这就是数据抽象方法。

另一种方法是让棋盘的四面都变大,但只在内部方块中循环。然后你不需要检查相邻的方块是否在边界内。这将是您隐藏在 Board 方法中的实现细节。它与第一种方法完全兼容。

还有其他一些技巧可以避免循环中的边界检查,例如将棋盘分成九个特殊情况(角、边缘和中间),但这对于像扫雷游戏这样的游戏来说太过分了。而且它不会降低复杂性;这主要是为了在某些极端情况下获得性能。

【讨论】:

我提出了一个非常简单但动态的解决方案,用于在 1 行短代码中检查所有边界。但这是经过 4 个小时的思考后完成的。我什至不需要调用任何函数来让它看起来很优雅。我的代码实际上只有 3-5 行。直到现在我才感到惊讶,即使几年前在 SO 中提出过类似的问题,SO 中也没有人能够提供这种简单的解决方案。 @user3437460:请在答案中分享您的解决方案。【参考方案2】:
for(int x =0; x<numRows; x++)
    for(int y = 0; y<numCols; y++)
        if(array[x][y] != "bomb")
             array[x][y] = number
        
    

最好的方法就是循环遍历每个索引并检查是否有炸弹。如果没有,请添加一个数字。第一个 for 循环遍历每一行,然后下一个 for 循环遍历每一列。因此,您将检查第 1 行与第 1 列、第 2 列、第 3 列等。然后在第 1 行完成后移至第 2 行并检查与第 1 列、第 2 列等,直到搜索完每个位置。

【讨论】:

这不是检查邻居...这只是循环遍历每个数组元素是否是“炸弹”。 那么你想要的是,一旦你在一个特定的索引,检查所有围绕该索引的邻居? 是的。检查特定索引的所有邻居。

以上是关于检查二维数组中相邻方块的值的主要内容,如果未能解决你的问题,请参考以下文章

“拼接”多个二维数组

java如何用图形界面显示二维数组俄罗斯方块

获取二维数组中的相邻元素?

在 Go 中访问二维数组中的相邻元素的最有效方法是啥?

是否有复制存储在二维数组中的相邻像素值的算法?

返回二维数组子数组联通和最大