Как проверить всех соседей символа в строковом векторе

#c #vector #c 17

#c #вектор #c 17

Вопрос:

Игра Конвея. Пытаюсь получить доступ ко всем соседям каждой «ячейки», которую я считываю из файла.

Если ячейка живая, она остается живой для следующего поколения, если у нее ровно два или три соседа.

Если ячейка мертва, она становится живой для следующего поколения, если у нее ровно три соседа.

E имеет ровно 8 соседей в обеих ситуациях. У меня возникли проблемы с верхней строкой следующего поколения:

 .........                 F......DE
...ABC...                 I......GH
...DEF...                 .........
...GHI...                 .........
.........                 C......AB
  

файл считывается в currentgen, строковый вектор
nextgen является копией currentgen, которую я изменяю по мере необходимости

 //find neighbors
    for (size_t i=0; i < currentgen.size(); i  ){
                for(size_t j = 0; j < currentgen[0].length(); j  ){ 
                //neighbor count
                int neighborcount = 0;
                //south neighbor
                if(currentgen[(i 1) % currentgen.size()][j] == 'O'){
                    neighborcount  ;
                }
                //north
                if(currentgen[(i-1) % currentgen.size()][j] == 'O'){
                    neighborcount  ;
                }
                
                //left
                if(currentgen[i][(j-1) % currentgen[i].length()] == 'O'){
                    neighborcount  ;
                }
                
                //right
                if(currentgen[i][(j 1) % currentgen[i].length()] == 'O'){
                    neighborcount  ;
                }
                
                //south right
                if(currentgen[(i 1) % currentgen.size()]
                [(j 1) % currentgen[i].length()] == 'O'){
                    neighborcount  ;
                }
                
                //south left
                if(currentgen[(i 1) % currentgen.size()]
                [(j-1) % currentgen[i].length()] == 'O'){
                    neighborcount  ;
                }
                
                //north right
                if(currentgen[(i-1) % currentgen.size()]
                [(j 1) % currentgen[i].length()] == 'O'){
                    neighborcount  ;
                }
                //north left
                if(currentgen[(i-1) % currentgen.size()]
                [(j-1) % currentgen[i].length()] == 'O'){
                    neighborcount  ;
                }
                
                //if cell is alive
                if(currentgen[i][j] == 'O'){
                    nextgen[i][j] = '.';
                    if(neighborcount == 2){
                    nextgen[i][j]= 'O';
                    }
                    if(neighborcount == 3){
                    nextgen[i][j]= 'O';
                    }
                    
                
                }
                
                //if cell is dead
                if(currentgen[i][j] == '.'){
                    if(neighborcount == 3){
                    nextgen[i][j]= 'O';
                
                    }
                }
  

Комментарии:

1. i-1 , j-1 — У вас есть это в нескольких местах. Что, если i или j есть 0 ?

2. если i и j равны 0, они должны проверять противоположную сторону. Я показал выше, как E имеет 8 соседей,

3. Посмотрите на свой код: if(currentgen[(i-1) % currentgen.size()][j] — Итак, вы принимаете модуль отрицательного числа?

Ответ №1:

Проблема с вашим кодом заключается в том, что вы полагаетесь на % обычное значение остатка. Однако в c выполнение % с отрицательными значениями даст вам остаток в направлении 0.

Итак, следующее выражение:

 -1 % 5 // -1 not 4
  

Чтобы правильно выполнить остаток, вы можете добавить значение, которое вы используете в качестве модуля, и тогда вы гарантированно получите положительное число, и вычисление будет работать:

 (-1   5) % 5  // 4 yay!!
  

Кроме того, все эти if условия для проверки соседей очень подробны. Вы могли бы упростить это до:

 for (size_t i=0; i < currentgen.size(); i  ) {
  for(size_t j = 0; j < currentgen[0].length(); j  ) { 
    //neighbor count
    int neighborcount = 0;
    for (int i_offset : {-1, 0, 1})
      for (int j_offset : {-1, 0, 1}) 
        if (i amp;amp; j amp;amp; currentgen[(i   i_offset   currentgen.size()) 
                                 % currentgen.size()]
                                [(j   j_offset   currentgen[i].size()) 
                                 % currentgen[i].size()] == 'O')
          neighborcount  ;
 
    //if cell is alive
    // ... etc
  

Ответ №2:

Вот небольшой совет о том, как избежать жесткого кодирования координат (юг, север, влево, вправо и т.д.). Вы можете использовать 2 массива, а именно dx и dy, которые указывают дельту координат x и y.

Например, начните с северного соседа и двигайтесь по часовой стрелке (см. прилагаемое изображение):

dx и dy описание

 int dx[] = {0, 1, 1, 1, 0, -1, -1, -1};
int dy[] = {-1, -1, 0, 1, 1, 1, 0, -1};
  

Теперь, чтобы перебрать соседей ячейки (x, y), просто добавьте соответствующие записи dx и dy.

Как указано @cigien, вы не должны вычислять оператор остатка для отрицательных значений. Самое простое, что можно сделать, это добавить n и принять по модулю n, где n — размер поля. Это избавит вас от отрицательного значения перед операцией по модулю при сохранении того же результата, поскольку n % n = 0 .

Вот как вы можете перебирать соседей (x, y):

 int x;
int y;

// fill x and y

for(int d = 0; d < 8;   d)
{
    int nx = x   dx[d];
    int ny = y   dy[d];

    nx = (nx   n) % n;
    ny = (ny   n) % n;

    // horray!
}
  

Ответ №3:

Что-то вроде этого:

 #include <iostream>
#include <utility>

int main() {
  char field[5][5]{
      '.', '.', '.', '.', '.',
      '.', '.', 'O', '.', '.',
      '.', 'O', '.', 'O', '.',
      '.', '.', 'O', '.', '.',
      '.', '.', '.', '.', '.'
  };

  int posX = 2, posY = 2, count = 0;
  for (int y = -1; y <= 1;   y)
    for (int x = -1; x <= 1;   x) {
      const char symbol = field[(posY   y   5) % 5][(posX   x   5) % 5];
      count  = static_cast<int>((y != 0 || x != 0) amp;amp; symbol == 'O');
    }
  std::cout << count << 'n';
}
  

или

 const char symbol = field[(posY   y   HEIGHT) amp; (HEIGHT - 1)][(posX   x   WIDTH) amp; (WIDTH - 1)];
  

если размер вашего поля равен степени 2 в направлении x / y