Conways游戏 - 访问超出范围的数据

时间:2012-01-21 13:09:47

标签: c conways-game-of-life

这是我康威的生命游戏C代码。

函数 newgen 检查相邻单元格,所有八个单元格,即使单元格位于矩阵的边缘。如何以不会导致访问超出绑定数据和未定义行为的方式更改它?

我也有这个错误:

1   IntelliSense: a value of type "void *" cannot be assigned to an entity of type "int *"  

代码是:

void copy() {
  int i, j;
  for (i = j = 0; i < HEIGHT; i++) {
    for (; j < WIDTH; j++) {
      gb2[i][j] = gb[i][j];
    }
  }
}

void init() {
  int i, j;
  for (i = 0; i < HEIGHT; i++) {
    gb [i] = malloc(sizeof(int)*WIDTH);
    gb2[i] = malloc(sizeof(int)*WIDTH);
  }
  for (i = 0 ; i < HEIGHT; i++) {
    for (j = 0 ; j < WIDTH; j++) {
      gb [i][j] = 0;
    }
  }
  gb[0][0] = 1;
  gb[0][1] = 1;
  gb[1][0] = 1;
  gb[1][1] = 1;
  copy();
}

...     int main(){       int i;       在里面();       NEWGEN();       printg();       for(i = 0; i&lt; HEIGHT; i ++){         自由(GB [I]);         自由(GB2 [I]);       }     }

3 个答案:

答案 0 :(得分:1)

newgen()中,您从1循环到HEIGHT - 2循环,这样可以避免越界访问,但是对于从0循环到WIDTH - 2的列,所以每次都有超出范围的访问权限当你在第一列时,访问j - 1的行。即,

for (j = 0; j < WIDTH-1; j++) {
   if (gb[i][j+1]) n++;
   if (gb[i+1][j]) n++;
   if (gb[i+1][j+1]) n++;
   if (gb[i-1][j-1]) n++; // <- Here,
   if (gb[i][j-1]) n++;   // <- here,
   if (gb[i-1][j]) n++;
   if (gb[i+1][j-1]) n++; // <- ...and here.
   if (gb[i-1][j+1]) n++; 

当你开始循环遍历列时,以j等于1而不是0开始:

for (j = 1; j < WIDTH-1; j++) { 

答案 1 :(得分:0)

我没有测试下面的代码(并且它仍然是不完整的)但你应该遍历数组中的所有元素并更新邻居计数。您可以使用几个遍历所有相邻单元格的循环,并在进行边界检查时执行边界检查。

开始处理每个单元格时,还应重置相邻单元格数。

void newgen()
{
    for (int i = 0; i < HEIGHT; i++)
    {
        for (int j = 0; j < WIDTH; j++)
        {
            int n = 0;

            for (int test_y = i - 1; test_y <= (i + 1); ++test_y)
            {
                for (int test_x = j - 1; test_x <= (j + 1); ++test_x)
                {
                    if ((test_x != test_y) &&
                        (test_x >= 0) && (test_x < WIDTH) &&
                        (test_y >= 0) && (test_y < HEIGHT))
                    {
                        if (gb[test_y][test_x])
                        {
                            n++;
                        }
                    }
                }
            }

            /* Process the n value here */
        }
    }
}

您可能只是使用静态数组而不是沿一个维度分配,或沿两个维度分配。目前它是静态和动态尺寸的混合,这不是一个问题,它似乎不一致。

您的Intellisense错误听起来像Intellisense只处理C ++代码,而不是C代码,但这只是猜测。你可以配置编译器(我假设MSVC在这里)编译为C或C ++,但也许Intellisense没有那个选项或者它是单独配置的。

答案 2 :(得分:0)

IntelliSense警告是因为您使用的是Visual C ++,并且该警告适用于C ++。 (当你使用C时,它不是那么“智能”。)你可以通过将malloc的返回值转换为(int *)来避免警告,尽管casting the return of malloc is not recommended in C

至于避免越界访问:不要访问越界。一些可能的解决方案包括:

  • 创建一个函数来返回单个单元格的实时/死亡值,并检查那里的边界,如果它超出范围则返回0。 (或者你可以将网格环绕到另一边;如果你想要动画,例如在小网格上glider,这很好。)

  • 不要在循环中包含第一行或最后一行或列,而应将其视为特殊情况,并且不要超出边界。

  • 分配两个额外的行和列,将它们初始化为零,然后不迭代最后一行或列(即将您的活动网格视为[1..w] [1..h]但是分配w + 2列和h + 2行)。然后你不需要边缘的特殊情况,但使用少量的额外内存。