c++ - 生命游戏阵列边缘表现怪异

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

最佳答案

在我过去教授的一门类(class)中做过这个,我经常看到人们遇到的最常见问题是超出了他们正在使用的数组的范围。

如果您查看嵌套 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 等于零怎么办?

希望对您有所帮助。

关于c++ - 生命游戏阵列边缘表现怪异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17014537/

相关文章:

c++ - 带有字符串数组的段错误c++

c++ - boost::format 形式的 c 字符串或 std::string

c++ - 是否可以在 .cpp 文件而不是其头文件中定义类的静态成员函数?

c++ - 转到 Vim 中 C++ 函数的末尾

C - 函数返回一个数组

javascript - jQuery - 从 json 对象中获取选定的值

c++ - QSqlDatabase 没有看到表

java - 读取二维数组的问题 - Java

optimization - 调整 MIT 的 bitcount 算法以并行计算单词?

perl - Perl 中的生命游戏——从 C++ 翻译代码时出现问题