I have some working Game of Life code. It saves each population as a bitmap. Here's what the output looks like (cropped):
When cleaning the code, I found that if I commented out or otherwise remove line 60:
cout << "Survivor: " << x << ", " << y << "\n";
It completely messes up the program, and instead of producing a glider like it should, it produces this:
I have poked around, trying to find out what might cause this, but I have been thus far unsuccessful. This is my current code:
//Bitmap Library from http://partow.net/programming/bitmap/
#include "bitmap_image.hpp"
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
using namespace std;
#define WIDTH 160
#define HEIGHT 128
bool population[WIDTH][HEIGHT];
bool survivors[WIDTH][HEIGHT];
int check_survivors();
int check_neighbors(int x, int y);
int write_population(char* file);
int main() {
int i, populations;
cout << "Enter number of populations: ";
cin >> populations;
//Glider
survivors[28][100] = true;
survivors[29][100] = true;
survivors[29][101] = true;
survivors[30][101] = true;
survivors[28][102] = true;
//Initial image generation
write_population("population0.bmp");
//populations
for (i = 0; i < populations; i++) {
char filename[17] = "population";
char ii[3];
sprintf(ii, "%d", i+1);
strcat(filename, ii);
strcat(filename, ".bmp");
check_survivors();
write_population(filename);
}
return 0;
}
int check_survivors() {
//set x and y variables
int x, y;
for (x = 0; x < WIDTH; x++) {
for (y = 0; y < HEIGHT; y++) {
if (check_neighbors(x, y)) {
survivors[x][y] = true;
cout << "Survivor: " << x << ", " << y << "\n";
} else {
survivors[x][y] = false;
}
}
}
return 0;
}
int check_neighbors(int x, int y) {
int neighbors = 0, survives;
//I really need to rewrite this mess
//Neighbors above
if (population[x-1][y-1] == true && x != 0 && y != 0) {
neighbors++;
}
if (population[x][y-1] == true && y != 0) {
neighbors++;
}
if (population[x+1][y-1] == true && x != WIDTH-1 && y != 0) {
neighbors++;
}
//Neighbors next to
if (population[x-1][y] == true && x != 0 ) {
neighbors++;
}
if (population[x+1][y] == true && x != WIDTH-1) {
neighbors++;
}
//Neighbors below
if (population[x-1][y+1] == true && x != 0 && y != HEIGHT-1) {
neighbors++;
}
if (population[x][y+1] == true && y != HEIGHT-1) {
neighbors++;
}
if (population[x+1][y+1] == true && x != WIDTH-1 && y != HEIGHT-1) {
neighbors++;
}
//Determining life or death
if (neighbors < 2 || neighbors > 3) {
//Neighbors less than 2 or more than 3 is dead cell
survives = 0;
} else if (neighbors == 3 && population[x][y] == false) {
//Exactly 3 neighbors re-animates a cell
survives = 1;
} else if (population[x][y] == true) {
//2 or 3 neighbors is survivor
survives = 1;
}
return survives;
}
int write_population(char* file) {
//Create Image
bitmap_image image(WIDTH, HEIGHT);
//Set background to white
image_drawer draw(image);
image.set_all_channels(255,255,255);
//set x and y variables
int x, y;
//For every array point, check to see if it survives,
//and transfer survivors to population
for (x = 0; x < WIDTH; x++) {
for (y = 0; y < HEIGHT; y++) {
if (survivors[x][y] == true) {
draw.pen_width(1);
draw.pen_color(0,0,0);
draw.plot_pixel(x, y);
}
population[x][y] = survivors[x][y];
}
}
//Save image
image.save_image(file);
//return
return 1;
}
Things like this:
if (population[x-1][y-1] == true && x != 0 && y != 0)
need to be rewritten as:
if ( x > 0 && y > 0 && population[x-1][y-1] == true )
otherwise you'll be straight into undefined behavior territory when either x
or y
are 0
(as they will be several times when you call check_neighbors()
from check_survivors()
), and you can expect weird, inexplicable errors like this. You need to check for invalid array indices before you try to access those elements.
Also, here:
if (neighbors < 2 || neighbors > 3) {
//Neighbors less than 2 or more than 3 is dead cell
survives = 0;
} else if (neighbors == 3 && population[x][y] == false) {
//Exactly 3 neighbors re-animates a cell
survives = 1;
} else if (population[x][y] == true) {
//2 or 3 neighbors is survivor
survives = 1;
}
it looks as if survives
could be left with an indeterminate value if neighbors == 2
and population[x][y] == false
, which would also cause undefined behavior if you were to access that value. It's not immediately clear from your code whether that combination of circumstances could ever be true, but if you're still at the debugging stage then at a minimum it's worth adding a condition check to verify whether or not it ever is.
If your program is exhibiting undefined behavior as this one is, then it's pretty much impossible to reason about it until after those issues are fixed.
You don't always assign a value into the variable survives
e.g. if population[x][y]
is false
and neighbors
is 2. This leaves survives
with a value of whatever is in memory at the time. When you add the cout
call it probably happens to set that bit of stack memory to 0, masking your program's error.
Add an intial value to survives
when you declare it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With