【问题标题】:Logic error with Game of Life (C++) [closed]生命游戏(C++)的逻辑错误[关闭]
【发布时间】:2014-12-13 02:54:26
【问题描述】:

正在制作康威的生命游戏,我觉得我非常接近完成它,但我的逻辑存在一些缺陷。我已经为此倾注了好几个小时,我只是觉得第二双眼睛能够比我更快地发现我的错误。我的程序编译得很好,但输出不遵循特定位置的游戏指南(例如 col 0,第 1 行在第二代中有生命,但它不应该但所有第 10 行似乎都按预期工作)。对于不熟悉的人: http://en.wikipedia.org/wiki/Conway%27s_Game_of_Life#Rules

我几乎可以肯定,逻辑错误发生在函数 advGen 中。以下链接包含函数 readGrid 使用的细菌.txt 的内容:http://pastebin.com/6vurFRSB

感谢您抽出宝贵时间阅读并提供帮助。

    //sample setup to start the game of life - startlife.cpp

#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;

const int SIZE = 20;

//initial function prototypes
void initGrid(bool life[][SIZE], bool nextGen[][SIZE]);
void readGrid(bool life[][SIZE], bool nextGen[][SIZE]);
void printGrid(bool life[][SIZE], bool nextGen[][SIZE]);
void advGen(bool life[][SIZE], bool nextGen[][SIZE]);

int main()
{
    bool life[SIZE][SIZE];
    bool nextGen[SIZE][SIZE];

    readGrid(life, nextGen);
   /* for (int count = 0; count < 5; count++){
        determineNextGen(life);
    }*/

    printGrid(life, nextGen);
    advGen(life, nextGen);
    printGrid(life, nextGen);

    return 0;
}


/*-------------------------------------------------------

           readGrid (and related functions)

---------------------------------------------------------*/

void readGrid(bool life[][SIZE], bool nextGen[][SIZE])
{
    ifstream infile("bacteria.txt"); //see class site project#5 for data file

    int numBacteria, row, col;

    initGrid(life, nextGen);

    infile >> row >> col;
    while (infile){
        life[row][col] = true;
        infile >> row >> col;
    }
    infile.close();
}


void initGrid(bool life[][SIZE], bool nextGen[][SIZE])
{
    for (int row = 0; row < SIZE; row++)
    {
        for (int col = 0; col < SIZE; col++){
            life[row][col] = false;
        }
    }
    for (int row = 0; row < SIZE; row++)
    {
        for (int col = 0; col < SIZE; col++){
            nextGen[row][col] = false;
        }
    }
}

void printGrid(bool life[][SIZE], bool nextGen[][SIZE])
{
    cout << "  01234567890123456789" << endl;
    for (int row = 0; row < SIZE; row++)
    {
        cout << setw(2) << row;
        for (int col = 0; col < SIZE; col++)
        {
            if (life[row][col])
            {
                cout << "*";
            }
            else
            {
                cout << " ";
            }
        }
        cout << endl;
    }
}

void advGen(bool life[][SIZE], bool nextGen[][SIZE])
{
    int neighbor = 0;

    for (int row = 0; row < SIZE; row++)
    {
        for (int col = 0; col < SIZE; col++)
        {
            if (row == 0)
            {
                if (col == 0)
                {
                    if (life[row + 1][col] == true)
                        ++neighbor;
                    if (life[row][col + 1] == true)
                        ++neighbor;
                    if (life[row + 1][col + 1] == true)
                        ++neighbor;
                    if ( (life[row][col] == true) && (neighbor < 2 || neighbor > 3))
                    {
                        nextGen[row][col] = false;
                    }
                    else if ( (life[row][col] == false) && (neighbor == 3) )
                    {
                        nextGen[row][col] = true;
                    }
                }
                else if (col == 19)
                {
                    if (life[row + 1][col] == true)
                        ++neighbor;
                    if (life[row][col - 1] == true)
                        ++neighbor;
                    if (life[row + 1][col - 1] == true)
                        ++neighbor;
                    if ( (life[row][col] == true) && (neighbor < 2 || neighbor > 3))
                    {
                        nextGen[row][col] = false;
                    }
                    else if ( (life[row][col] == false) && (neighbor == 3) )
                    {
                        nextGen[row][col] = true;
                    }
                }
                else
                {
                    if (life[row + 1][col] == true)
                        ++neighbor;
                    if (life[row][col + 1] == true)
                        ++neighbor;
                    if (life[row][col - 1] == true)
                        ++neighbor;
                    if (life[row + 1][col + 1] == true)
                        ++neighbor;
                    if (life[row + 1][col - 1] == true)
                        ++neighbor;
                    if ( (life[row][col] == true) && (neighbor < 2 || neighbor > 3))
                    {
                        nextGen[row][col] = false;
                    }
                    else if ( (life[row][col] == false) && (neighbor == 3) )
                    {
                        nextGen[row][col] = true;
                    }
                }
            }
            if (row == 19)
            {
                if (col == 0)
                {
                    if (life[row - 1][col] == true)
                        ++neighbor;
                    if (life[row][col + 1] == true)
                        ++neighbor;
                    if (life[row - 1][col + 1] == true)
                        ++neighbor;
                    if ( (life[row][col] == true) && (neighbor < 2 || neighbor > 3))
                    {
                        nextGen[row][col] = false;
                    }
                    else if ( (life[row][col] == false) && (neighbor == 3) )
                    {
                        nextGen[row][col] = true;
                    }
                }
                else if (col == 19)
                {
                    if (life[row - 1][col] == true)
                        ++neighbor;
                    if (life[row][col - 1] == true)
                        ++neighbor;
                    if (life[row - 1][col - 1] == true)
                        ++neighbor;
                    if ( (life[row][col] == true) && (neighbor < 2 || neighbor > 3))
                    {
                        nextGen[row][col] = false;
                    }
                    else if ( (life[row][col] == false) && (neighbor == 3) )
                    {
                        nextGen[row][col] = true;
                    }
                }
                else
                {
                    if (life[row - 1][col] == true)
                        ++neighbor;
                    if (life[row][col - 1] == true)
                        ++neighbor;
                    if (life[row][col + 1] == true)
                        ++neighbor;
                    if (life[row - 1][col - 1] == true)
                        ++neighbor;
                    if (life[row - 1][col + 1] == true)
                        ++neighbor;
                    if ( (life[row][col] == true) && (neighbor < 2 || neighbor > 3))
                    {
                        nextGen[row][col] = false;
                    }
                    else if ( (life[row][col] == false) && (neighbor == 3) )
                    {
                        nextGen[row][col] = true;
                    }
                }
            }
            if (col == 0)
            {
                if (row == 0)
                {
                    if (life[row + 1][col] == true)
                        ++neighbor;
                    if (life[row][col + 1] == true)
                        ++neighbor;
                    if (life[row + 1][col + 1] == true)
                        ++neighbor;
                    if ( (life[row][col] == true) && (neighbor < 2 || neighbor > 3))
                    {
                        //nothing
                    }
                    else if ( (life[row][col] == false) && (neighbor == 3) )
                    {
                        //nothing
                    }
                }
                else if (row == 19)
                {
                    if (life[row - 1][col] == true)
                        ++neighbor;
                    if (life[row][col + 1] == true)
                        ++neighbor;
                    if (life[row - 1][col + 1] == true)
                        ++neighbor;
                    if ( (life[row][col] == true) && (neighbor < 2 || neighbor > 3))
                    {
                        //nothing
                    }
                    else if ( (life[row][col] == false) && (neighbor == 3) )
                    {
                        //nothing
                    }
                }
                else
                {
                    if (life[row - 1][col] == true)
                        ++neighbor;
                    if (life[row + 1][col] == true)
                        ++neighbor;
                    if (life[row][col + 1] == true)
                        ++neighbor;
                    if (life[row - 1][col + 1] == true)
                        ++neighbor;
                    if (life[row + 1][col + 1] == true)
                        ++neighbor;
                    if ( (life[row][col] == true) && (neighbor < 2 || neighbor > 3))
                    {
                        nextGen[row][col] = false;
                    }
                    else if ( (life[row][col] == false) && (neighbor == 3) )
                    {
                        nextGen[row][col] = true;
                    }
                }
            }
             if (col == 19)
            {
                if (row == 0)
                {
                    if (life[row - 1][col] == true)
                        ++neighbor;
                    if (life[row][col - 1] == true)
                        ++neighbor;
                    if (life[row + 1][col - 1] == true)
                        ++neighbor;
                    if ( (life[row][col] == true) && (neighbor < 2 || neighbor > 3))
                    {
                        //nothing
                    }
                    else if ( (life[row][col] == false) && (neighbor == 3) )
                    {
                        //nothing
                    }
                }
                else if (row == 19)
                {
                    if (life[row - 1][col] == true)
                        ++neighbor;
                    if (life[row][col - 1] == true)
                        ++neighbor;
                    if (life[row - 1][col - 1] == true)
                        ++neighbor;
                    if ( (life[row][col] == true) && (neighbor < 2 || neighbor > 3))
                    {
                        //nothing
                    }
                    else if ( (life[row][col] == false) && (neighbor == 3) )
                    {
                        //nothing
                    }
                }
                else
                {
                    if (life[row][col - 1] == true)
                        ++neighbor;
                    if (life[row - 1][col] == true)
                        ++neighbor;
                    if (life[row + 1][col] == true)
                        ++neighbor;
                    if (life[row + 1][col - 1] == true)
                        ++neighbor;
                    if (life[row - 1][col - 1] == true)
                        ++neighbor;
                    if ( (life[row][col] == true) && (neighbor < 2 || neighbor > 3))
                    {
                        nextGen[row][col] = false;
                    }
                    else if ( (life[row][col] == false) && (neighbor == 3) )
                    {
                        nextGen[row][col] = true;
                    }
                }
            }
            else
                {
                    if (life[row - 1][col] == true)
                        ++neighbor;
                    if (life[row + 1][col] == true)
                        ++neighbor;
                    if (life[row][col - 1] == true)
                        ++neighbor;
                    if (life[row][col + 1] == true)
                        ++neighbor;
                    if (life[row - 1][col - 1] == true)
                        ++neighbor;
                    if (life[row + 1][col + 1] == true)
                        ++neighbor;
                    if (life[row - 1][col + 1] == true)
                        ++neighbor;
                    if (life[row + 1][col - 1] == true)
                        ++neighbor;
                    if ( (life[row][col] == true) && (neighbor < 2 || neighbor > 3))
                    {
                        nextGen[row][col] = false;
                    }
                    else if ( (life[row][col] == false) && (neighbor == 3) )
                    {
                        nextGen[row][col] = true;
                    }
                }neighbor = 0;
        }
    }
    for (int row = 0; row < SIZE; row++)
        {
        for (int col = 0; col < SIZE; col++)
            {
                life[row][col] = nextGen[row][col];
            }
        }

}

【问题讨论】:

  • 你有很多重复的代码,这些代码可以从移动到单独的函数中受益。它会让你的代码更容易阅读。
  • 每一次使用 == true 都是 100% 多余的,除了视觉噪音。如果您将那些bool 转换为int 并将它们加在一起,那么您的巨大 堆栈if(life[...][....]) ++neighbour 可以大大简化为几行。并且为了避免以占用额外内存为代价的边界逻辑,您可以用零填充板的左侧、右侧、顶部和底部,并且永远不要覆盖它们。

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


【解决方案1】:

您的代码重复计算了邻居的数量。这是因为,例如,如果 row 为 0 且 col 为 0,则它在顶部执行 row == 0 大小写,并且在 col == 0 if 语句中向下执行大约 100 行的 row == 0 大小写。

解决此问题的一种方法是使用正确的else 子句。即做类似的事情:

if (row == 0)
{
    ...
}
else if (row == 19)
{
    ...
}
else
{
    ...
}

您也需要对列大小写执行此操作。

更好的解决方案是查看所有这些特殊情况,并尝试将它们合理化为重复代码较少的东西。

您想要实现的是防止读取数组边界之外的内容。

一种简单的方法是使用一个函数来获取row, col 处的数组值,该函数检查rowcol,如果rowcol 超出范围,则返回false界限。然后,您可以为每个位置的 8 个周围块中的每一个调用该函数,而无需为第 0 行和第 19 行以及第 0 和第 19 列设置特殊情况。

我建议尝试编写一个类似上面的函数,而不是我只是在这里为你粘贴。

编辑:另请注意 - 您并不总是将值设置为 nextGen,因此您正在杀死与 2 或 3 个邻居一起生活的单元格,您可能需要在分配给 @ 时重新考虑您的 if/else 语句987654335@

【讨论】:

  • 我会投赞成票,但我太新了。我非常感谢您的解释,我想知道是否有更简单的方法来做到这一点。非常感谢!
  • 我试着写了你建议的函数,但在我用更多的代码让自己难堪之前,你能试着解释一下这个函数的不同之处吗?
  • 该函数需要将life数组作为参数和rowcol的参数。然后它需要检查 rowcol 是否在数组内(即 >=0 和 false,表示边界外没有生命。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多