生命游戏阵列边缘表现得很奇怪

时间:2013-06-09 21:52:18

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

我看到康威的生命游戏,并决定自己制作。 我有一个bool数组代表世界,但边缘(顶部和底部)表现得很奇怪,随机单元变为现场。

在此代码中,它不会打印世界的底部和顶部,但这是一个糟糕的解决方案。 世界在右边和左边“包裹”,造成更多问题,但那是另一次。

#include <iostream>

const int height = 20;
const int width  = 20;

bool now_world[height][width];
bool then_world[height][width];

void clear_world();
void place_random_live_cells();
void then_world_initialization();
void print_world();
void generation_pass();
void update_worlds();

int main(int argc, const char * argv[])
{
using namespace std;
srand((unsigned)time(NULL));
int timer = 0;
int generation = 0;
clear_world();
place_random_live_cells();
then_world_initialization();
bool running = true;
while (running) {
    if (timer == 50000000) {
        cout << "Generation #" << generation << endl;
        print_world();
        generation_pass();
        update_worlds();
        ++generation;
        timer = 0;
    }
    ++timer;
}//While (running) ends here
return 0;
}

void place_random_live_cells()
{
int percent = 30;
int max_live_cells = ((height * width) / 100) * percent;
int current_live_cells = 0;
while (current_live_cells < max_live_cells) {
    int ycoords = 0 + (rand() % (height + 1));
    int xcoords = 0 + (rand() % (width  + 1));
    if (now_world[ycoords][xcoords] == false) {
        now_world[ycoords][xcoords] = true;
    } else {
        current_live_cells--;
    }
    ++current_live_cells;
}
}

//A generation pass and cells die and some cells come to life
void generation_pass()
{
using namespace std;
int neighbours = 0;
for (int iii = 0; iii < height; iii++) {
    for (int jjj = 0; jjj < width; jjj++) {
        //Count neighbouring cells that are alive
        if (now_world[iii+1][jjj+1] == true) {
            ++neighbours;
        }
        if (now_world[iii+1][jjj  ] == true) {
            ++neighbours;
        }
        if (now_world[iii+1][jjj-1] == true) {
            ++neighbours;
        }
        if (now_world[iii  ][jjj+1] == true) {
            ++neighbours;
        }
        if (now_world[iii  ][jjj-1] == true) {
            ++neighbours;
        }
        if (now_world[iii-1][jjj+1] == true) {
            ++neighbours;
        }
        if (now_world[iii-1][jjj  ] == true) {
            ++neighbours;
        }
        if (now_world[iii-1][jjj-1] == true) {
            ++neighbours;
        }
        //Apply rules to the cells
        //Dead cells with three live neighbours becomes alive
        if (then_world[iii][jjj] == false && neighbours == 3) {
            then_world[iii][jjj] =  true;
        }
        //Alive with fewer than two, they die
        if (then_world[iii][jjj] == true  && neighbours <  2) {
            then_world[iii][jjj] =  false;
        }
        //Alive with 2 or three live neighbours live on unchanged
        if (then_world[iii][jjj] == true  && neighbours == 2) {
            then_world[iii][jjj] =  true;
        }
        if (then_world[iii][jjj] == true  && neighbours == 3) {
            then_world[iii][jjj] =  true;
        }
        //Alive with more than three, they die
        if (then_world[iii][jjj] == true  && neighbours >  3) {
            then_world[iii][jjj] =  false;
        }
        //Dead cells without exactly three live neighbours remain dead
        //Reset neighbour value to zero
        neighbours = false;
    }
}
}

//Make next generation identical to current
//This is only called once
void then_world_initialization()
{
for (int iii = 0; iii < height; iii++) {
    for (int jjj = 0; jjj < width; jjj++) {
        then_world[iii][jjj] = now_world[iii][jjj];
    }
}
}

//Make the next generation be today
//This is called every generation
void update_worlds()
{
for (int iii = 0; iii < height; iii++) {
    for (int jjj = 0; jjj < width; jjj++) {
        now_world[iii][jjj] = then_world[iii][jjj];
    }
}
}

//Set all cells to dead
void clear_world()
{
for (long iii = 0; iii < height; iii++) {
    for (long jjj = 0; jjj < width; jjj++) {
        now_world[iii][jjj]  = false;
        then_world[iii][jjj] = false;
    }
}
}

//Print world
void print_world()
{
using namespace std;
char live = 'X';
char dead = '.';
for (long iii = height; iii > 0; iii--) {
    for (long jjj = width; jjj > 0; jjj--) {
        if (iii != 0 && iii != height) {
            if (now_world[iii][jjj]) {
                cout << live;
            } else {
                cout << dead;
            }
            cout << " ";
        }
    }
    cout << endl;
}
cout << endl;
}

2 个答案:

答案 0 :(得分:3)

为我过去教过的课程做了这个,我总是看到人们遇到的最常见的问题是超出了他们正在使用的阵列范围。

如果你看看嵌套for循环中的if语句,我想你会发现一些问题。例如,在这种情况下,当iii等于(height-1)或jjj等于(width-1)时会发生什么?

for (int iii = 0; iii < height; iii++) {
    for (int jjj = 0; jjj < width; jjj++) {
        //Count neighbouring cells that are alive
        if (now_world[iii+1][jjj+1] == true) {
            ++neighbours;

你超出了数组的范围,因此你的结果将是未定义的。您可能会遇到段错误,但您可能也会收到虚假数据。 C ++不会强制您保持在您定义的数组的范围内。

确保你也处理这样的案件:

if (now_world[iii-1][jjj+1] == true) {
            ++neighbours;
        }

如果iii等于零怎么办?

希望有所帮助。

答案 1 :(得分:1)

您正尝试访问阵列中的超出边界索引。

我不确定您期望的行为,但一种简单的方法是不计算边缘单元格的更新。

所以在generation_pass中,循环应该从1height-1