2012-01-21 1 views
0

Это мой код жизни Конуэй.Conways игра - выход из связанных данных

Функция 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 основной() { INT I; init(); newgen(); printg(); для (i = 0; i < HEIGHT; i ++) { free (gb [i]); бесплатно (gb2 [i]); } }

+0

Не могли бы вы рассказать нам, в чем проблема с вашей программой? Для предупреждения вы получите его, потому что вы компилируете с помощью компилятора C++: в C это хорошо, в C++ выведите значение «malloc' return» в 'int *'. – ouah

+0

В 'newgen()' 'j-1' выходит за пределы, это то, что вы хотите исправить? Также вам не хватает 'free'ing' gb2' массива указателей ... AFAIK 'free'ing как раз перед выходом программы не является существенным последствием –

+0

another.anon.coward, где я скучаю бесплатно? GB2? не могли бы вы объяснить больше? – Blondy21

ответ

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

1

В newgen() You цикл от 1 до ВЫСОТЫ - 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++) { 
+0

Я бы предложил цикл по всем элементам в массиве, но обеспечил внутренние циклы, чтобы заменить 8 проверок с помощью некоторой встроенной проверки границ. Таким образом, вы можете обновлять ячейки по краям, которые не начинаются с 1. – tinman

+0

tinman, не могли бы вы показать мне, что вы имеете в виду? – Blondy21

+0

Мартин, я обновил код в соответствии с вашим ответом - мне нужно использовать j = 1 в другом месте, чтобы избежать границ? – Blondy21

0

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

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

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

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

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

+0

, но я уже сдерживал его: int * gb [HEIGHT]; int * gb2 [ВЫСОТА]; – Blondy21

+0

@ Blondy21 Здесь вы определяете переменные 'gb' и' gb2', когда вы назначаете их из 'malloc', вам нужно указать возвращаемое значение в C++ (но не C, но IntelliSense предполагает C++), то есть' gb = (int *) malloc (...) '. В любом случае вы можете просто игнорировать это предупреждение. – Arkku

Смежные вопросы