Игра Конвейс - доступ из связанных данных - PullRequest
0 голосов
/ 21 января 2012

Это код моей жизни Конвея с кодом 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 (); для (i = 0; i

Ответы [ 3 ]

1 голос
/ 21 января 2012

В newgen() вы выполняете цикл от 1 до ВЫСОТЫ - 2 для строк, что исключает доступ за пределами границ, но для столбцов вы циклически переходите от 0 до ШИРИТЫ - 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++) { 
0 голосов
/ 21 января 2012

Предупреждение IntelliSense вызвано тем, что вы используете Visual C ++, и предупреждение будет уместным в C ++. (Это не так «intelli», когда вы используете C.) Вы можете избежать предупреждения, приведя возвращаемое значение от malloc к (int *), хотя приведение к возвращению malloc не рекомендуется в C .

Что касается предотвращения доступа за пределы: не выходите за пределы. Некоторые возможные решения включают в себя:

  • Создайте функцию, которая возвращает живое / мертвое значение отдельной ячейки и проверяет границы там, возвращая 0, если оно выходит за пределы. (Или вы можете обернуть сетку на другую сторону; это хорошо, если вы хотите анимировать, например, планер на маленькой сетке.)

  • Не включайте первую или последнюю строку или столбец в цикл, вместо этого рассматривайте их как особые случаи и не обращайтесь за пределы.

  • Выделите две дополнительные строки и столбцы, инициализируйте их нулем, а затем не выполняйте итерации по последней строке или столбцу (т. Е. Рассматривайте вашу активную сетку как [1..w] [1..h] но выделите w + 2 столбца и h + 2 строки). Тогда вам не нужен особый случай для краев, но используйте небольшой объем дополнительной памяти.

0 голосов
/ 21 января 2012

Я не проверял приведенный ниже код (и он в любом случае неполон), но вы должны перебрать все элементы в вашем массиве и обновить количество соседей.Вы можете использовать несколько циклов, которые проходят по всем соседним ячейкам и выполняют проверку границ по ходу работы.

Вам также следует сбросить счетчик соседних ячеек, когда вы начнете обрабатывать каждую ячейку.

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 либо не имеет этой опции, либо настроен отдельно.

...