#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.
Например, начните с северного соседа и двигайтесь по часовой стрелке (см. прилагаемое изображение):
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