1

我正在尝试使用 2D 矢量构建一个简单的扫雷应用程序。首先,我用 1 和 0 填充方块(1 表示地雷,0 表示清除)。

srand(time(NULL));
for (int i = 0; i < battlefield.size(); i++)
{
    for (int j = 0; j < battlefield[i].size(); j++)
    {
        int num = (rand() % 2);
        battlefield[i][j] = num;
    }
}`

然后,我再次遍历向量并计算周围地雷的数量。这就是我遇到问题的地方。我认为当它试图检查一个超出范围的方块时,它会爆炸。但是,如果在任何这些检查之前失败。如果在尝试查看当前平方是否等于 1 时失败。

for (int i = 0; i < battlefield.size(); i++)
{
    for (int j = 0; j < battlefield[i].size(); j++)
    {
        int count = 0;
        if (battlefield[i][j] == 1)//mine square
        {
            if (battlefield[i - 1][j - 1] != 0)
            {
                count++;
            }
            if (battlefield[i][j - 1] != 0)
            {
                count++;
            }
            if (battlefield[i + 1][j - 1] != 0)
            {
                count++;
            }
            if (battlefield[i - 1][j] != 0)
            {
                count++;
            }
            if (battlefield[i + 1][j] != 0)
            {
                count++;
            }
            if (battlefield[i - 1][j + 1] != 0)
            {
                count++;
            }
            if (battlefield[i][j + 1] != 0)
            {
                count++;
            }
            if (battlefield[i + 1][j + 1] != 0)
            {
                count++;
            }
            battlefield[i][j] = count;
        }
    }

我不太确定为什么它在那里失败了,有什么想法吗?

4

3 回答 3

1

制作“CheckTile”功能

bool CheckTile(int i, int j)
{
    // check if both i and j are in the map bounds, return false if not
    if(i < 0 || i >= battlefield.size() || j < 0 || j >= battlefield.size()) 
        return false;

    // return true if the tile is a mine, false if not
    return (battlefield[i - 1][j - 1] != 0);
}

基本上用对 CheckTile 的调用替换所有 if 检查的内部结构。您当前的代码正在中断,因为您没有对数组进行边界检查,所以当它读取时

if(battlefield[i - 1][j - 1] != 0)

第一次,它试图读取分配内存之外的数组位置 (-1,-1),因此出现错误。将其替换为

if(CheckTile(i - 1, j - 1))

它会做同样的事情,但增加了边界检查保护。

于 2017-04-30T06:51:33.883 回答
1

如果您的地雷位于 0,0,您执行的第一次检查将检查 -1,-1 是否超出范围,实际上会炸毁您的程序。

你需要先检查你的界限。

于 2017-04-30T06:52:19.207 回答
1

你确实很幸运。超出边界的访问std::vector是“未定义的行为”,只有在幸运的情况下程序才会停止。

如果您不走运,该程序显然仍然“有效”,并且您一直在添加功能直到发货日……它只会在股东会议期间在客户机器的宽屏幕上爆炸:-)

在我看来,一个更简单的实现将是

int i0 = std::max(0, i-1), i1 = std::min(height-1, i+1);
int j0 = std::max(0, j-1); j1 = std::min(width-1, j+1);
int count = 0;
for (int i=i0; i<=i1; i++) {
    for (int j=j0; j<=j1; j++) {
        if (mine[i][j]) count++;
    }
}

基本上首先计算安全的边界,然后在它们中循环,而不是在代码中单独指定所有邻居。

于 2017-04-30T07:09:31.293 回答