0

我看了康威的生命游戏,决定自己做。我有一个布尔数组来表示世界,但边缘(顶部和底部)表现得很奇怪,随机单元格变得活跃。

在这段代码中,它不打印世界的底部和顶部,但这是一个糟糕的解决方案。世界在左右“缠绕”,导致更多问题,但那是另一次了。

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

2 回答 2

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 等于 0 怎么办?

希望有帮助。

于 2013-06-09T21:58:33.573 回答
1

您正在尝试访问数组中的越界索引。

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

所以在generation_pass循环中应该从1until开始height-1

于 2013-06-09T22:02:32.780 回答