Game Of Life计划中令人困惑的错误

时间:2014-11-01 02:37:15

标签: c++ conways-game-of-life

我有一些工作生命游戏代码。它将每个群体保存为位图。这是输出的样子(裁剪):

desired output

清理代码时,我发现如果我注释掉或以其他方式删除第60行:

cout << "Survivor: " << x << ", " << y << "\n";

它完全搞砸了程序,而不是像它应该生产滑翔机,它产生了这个:

faulty output

我已经四处寻找,试图找出可能导致这种情况的原因,但我迄今为止都没有成功。这是我目前的代码:

//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;
}

2 个答案:

答案 0 :(得分:6)

这样的事情:

if (population[x-1][y-1] == true && x != 0 && y != 0)

需要重写为:

if ( x > 0 && y > 0 && population[x-1][y-1] == true )

否则当xy0时,您将直接进入未定义的行为区域(因为当您从{{check_neighbors()拨打check_survivors()时,它们会多次出现1}}),你可以期待像这样的奇怪,莫名其妙的错误。您需要在尝试访问这些元素之前检查无效的数组索引

另外,这里:

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;
}

如果survivesneighbors == 2看起来好像population[x][y] == false可能会留下不确定的值,如果您要访问该值,也会导致未定义的行为。从您的代码中可以立即清楚地知道这种情况是否真实,但是如果您仍然处于调试阶段,那么至少值得添加一个条件检查以验证它是否曾经存在。

如果您的程序表现出未定义的行为,那么在修复这些问题之前几乎不可能对其进行推理。

答案 1 :(得分:3)

您并不总是为变量survives分配值,例如如果population[x][y]falseneighbors为2.这会使survives的值为当时内存中的任何值。当您添加cout调用时,可能会将堆栈内存的位设置为0,从而掩盖程序的错误。

在声明时为survives添加初始值。