c-康威游戏-访问越界数据



这是我的康威人生游戏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;init();newgen();printg();对于(i=0;i<HEIGHT;i++){免费(gb[i]);自由(gb2[i]);}}

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++) { 

我还没有测试下面的代码(无论如何它都是不完整的),但您应该循环遍历数组中的所有元素并更新邻居计数。您可以使用在所有相邻单元格上运行的几个循环,并在执行过程中执行边界检查。

当您开始处理每个单元格时,还应该重置相邻单元格的计数。

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可能没有这个选项,或者它是单独配置的。

IntelliSense警告是因为您正在使用Visual C++,并且该警告在C++中是合适的。(当你使用C时,它不是那么"intelli"。你可以通过将malloc的返回值强制转换为(int *)来避免警告,尽管在C中不建议强制转换malloc的返回值。

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

  • 创建一个函数来返回单个单元格的有效/无效值,并检查那里的边界,如果超出边界,则返回0。(或者,你可以将网格包裹到另一边;如果你想制作动画,例如,在小网格上的滑翔机,这很好。)

  • 不要将第一行或最后一行或列包含在循环中,而是将其视为特殊情况,不要访问超出边界的内容。

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

最新更新