Reputation: 23
Game of conway. Trying to access all neighbors of a each "cell" that i read in from a file.
If a cell is alive, it stays alive for the next generation if it has exactly two or three neighbors.
If a cell is dead, then it becomes alive for the next generation if it has exactly three neighbors.
E has exactly 8 neighbors in both situations. Im having issues with the top line of the next generation:
......... F......DE
...ABC... I......GH
...DEF... .........
...GHI... .........
......... C......AB
file is read into currentgen, a string vector nextgen is a copy of currentgen, that I change as needed
//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';
}
}
Upvotes: 1
Views: 284
Reputation: 2038
Something like this:
#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) && symbol == 'O');
}
std::cout << count << '\n';
}
or
const char symbol = field[(posY + y + HEIGHT) & (HEIGHT - 1)][(posX + x + WIDTH) & (WIDTH - 1)];
if your field size is a power of 2 in x/y direction
Upvotes: 0
Reputation: 379
Here is a small piece of advice on how to avoid hard-coding the coordinates (south, north, left, right, etc.). You can use 2 arrays, namely dx and dy, which indicates the delta of x and y coordinates.
For example, start with a north neighbour and go clockwise (see the picture attached):
int dx[] = {0, 1, 1, 1, 0, -1, -1, -1};
int dy[] = {-1, -1, 0, 1, 1, 1, 0, -1};
Now, in order to cycle through the neighbours of a cell (x, y), just add the corresponding dx and dy entries.
As pointed out by @cigien, you should not compute a remainder operator for negative values. The easiest thing to do is to add n and take modulo n, where n is a size of the field. It will save you from having negative value before modulo operation while preserving the same result, since n % n = 0
.
Here is how you can cycle through the neighbours of (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!
}
Upvotes: 0
Reputation: 60238
The issue with your code is that you're relying on %
having the usual meaning of remainder. However, in c++, doing %
on negative values will give you a remainder towards 0.
So the following expression is:
-1 % 5 // -1 not 4
To do the remainder correctly, you can add the value you're using as the modulus, and then you're guaranteed to have a positive number, and the calculation will work:
(-1 + 5) % 5 // 4 yay!!
Also, all those if
conditions to check the neighbors is very verbose. You could simplify that to:
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 && j && currentgen[(i + i_offset + currentgen.size())
% currentgen.size()]
[(j + j_offset + currentgen[i].size())
% currentgen[i].size()] == 'O')
neighborcount++;
//if cell is alive
// ... etc
Upvotes: 1