康威在C ++问题中的生命游戏

时间:2012-09-22 23:37:56

标签: c++ function vector

我在使用C ++编写Conway的生命游戏时遇到了一些问题。我觉得我有一个良好的开端,我只需要一些方向。首先,当我尝试运行程序时,我一直只是一个空白的控制台。而且我也不确定最好的方法来编写没有完整的八个邻居的电路板上的位置。任何帮助将不胜感激。

规则:

  

您将“硬编码”起始配置。用户不必是   能够提供不同的起始配置(只会   使你的程序复杂化。)

     

建议:寻找稳定的配置。也就是说,寻找   不断重复模式的社区。的数量   重复中的配置称为句点。有   已修复的配置,无需更改即可继续。一个   可能的项目是找到这样的配置。

     

提示:定义一个名为generation的void函数,它接受向量   我们称之为world(通过引用调用或使用指针),其中包含   当前(或初始)配置。该功能扫描矢量   并修改细胞,标记出生和死亡的细胞   符合前面列出的规则。这包括检查每个   反过来,细胞杀死细胞,让它活着,或细胞   是空的,决定一个细胞是否应该诞生。注意游戏   如果您的代码在相同的向量中计算邻居,则无法工作   修改。必须先创建世界矢量的副本   修改,此副本用于计算邻居,而单元格   在原始载体中打开或关闭。

     

应该有一个接受矢量世界的功能显示   在屏幕上显示网格。某种时间延迟是   在生成和显示的调用之间适当。要做到这一点,你的   程序应该在您按下时生成并显示下一代   返回/输入。你可以自动实现这一点(实时投入使用)   延迟,而不是等待用户按键),但自动化是   没有必要的程序。

     

如果您想“延迟”显示您的网格,而不是等待   用户输入内容并在显示下一个之前按Enter键   网格,那么你需要以某种方式暂停或“睡眠”你的程序。如果   您使用的是Microsoft Windows,请执行以下操作:

     

我们将每个单元定义为具有八个相邻单元。一个邻居   细胞是直接在上方,下方,右侧,左侧的细胞,   对角线在右上方和左上方,在斜下方对着   右边和左边。检查边缘邻居时要小心;   你可以决定边缘细胞是否有活着或死亡的邻居   边缘。

     

如果被占用的细胞有零个或一个邻居,它就会死于孤独。   如果一个被占用的小区有三个以上的邻居,它就会死掉   过度拥挤。

     

如果空单元格恰好有三个占用的相邻单元格,则有一个   诞生了一个新细胞来取代空细胞。

     

出生和死亡是瞬间的,并且发生在变化的时候   代。因任何原因死亡的细胞可能有助于分娩,但是   新生的细胞不能复活正在死亡的细胞,也不会复活   细胞的死亡可以通过减少当地人来阻止另一个人的死亡   人口。

我的代码到目前为止:

/*

Filename: main.cpp
Author:
Version: 20120920
Description:

*/

#include<iostream>
#include<vector>
#include<unistd.h>
#include<cstdlib>

using namespace std;

/*Change the values of your world matrix*/
#define ROWS 21
#define COLS 80

/*Change the values for dead or alive*/
#define DEAD  ' '
#define ALIVE '*'

/*Function Prototype for generation*/
void generation (vector< vector<char> > &world, vector< vector<char> > &world_copy);

/*Function Prototype for display*/
void display(vector< vector<char> >);

int main()
{

    vector< vector<char> > world(ROWS, vector<char>(COLS, DEAD));
    vector< vector<char> > world_copy(ROWS, vector<char>(COLS, DEAD));

    /*Set ALIVE cells*/
    world[1][1] = world[1][2] = world[1][3] = ALIVE;

    while(true);
    {
        /*Clear screen and display world*/
        system("cls");
        display(world);

        /*Wait*/
        usleep(8000);

        /*Update World*/
        generation(world, world_copy);

    }
    return 0;
}

/*Copy the contents of world into world_copy*/
void generation (vector< vector<char> > &world, vector< vector<char> > &world_copy)
{
    int ALIVE_count = 0;

    for (int i = 0; i < ROWS; i++)
    {
        for (int j = 0; j < COLS; j++)
        {
            /*Checks neighbors for life*/
            if(world_copy[i-1][j+1] == ALIVE)
            {
                ALIVE_count++;
            }
            if(world_copy[i][j+1] == ALIVE)
            {
                ALIVE_count++;
            }
            if(world_copy[i+1][j+1] == ALIVE)
            {
                ALIVE_count++;
            }
            if(world_copy[i-1][j] == ALIVE)
            {
                ALIVE_count++;
            }
            if(world_copy[i+1][j] == ALIVE)
            {
                ALIVE_count++;
            }
            if(world_copy[i-1][j-1] == ALIVE)
            {
                ALIVE_count++;
            }
            if(world_copy[i][j-1] == ALIVE)
            {
                ALIVE_count++;
            }
            if(world_copy[i+1][j-1])
            {
                ALIVE_count++;
            }

            /*Rule Section*/
            /*Death by loneliness. 0 or 1 neighbors.*/
            if (world_copy[i][j] == ALIVE && (ALIVE_count == 0 || ALIVE_count == 1))
            {
                world[i][j] = world_copy[i][j];
                world[i][j] == DEAD;
            }
            /*Live to next generation. 2 or 3 neighbors.*/
            else if(world_copy[i][j] == ALIVE && (ALIVE_count == 2 || ALIVE_count == 3))
            {
                world[i][j] = world_copy[i][j];
                world[i][j] == ALIVE;
            }
            /*Death by overcrowding. More than 3 neighbors.*/
            else if (world_copy[i][j] == ALIVE && ALIVE_count > 3)
            {
                world[i][j] = world_copy[i][j];
                world[i][j] == DEAD;
            }
            /*Birth. Exactly 3 neighbors.*/
            else if (world_copy[i][j] == ALIVE && ALIVE_count ==3)
            {
                world[i][j] = world_copy[i][j];
                world[i][j] == ALIVE;
            }
        }
    }
}

/*Display the world*/
void display(vector< vector<char> > &world)
{
    for (int i = 0; i < ROWS; i++)
    {
        for (int j = 0; i < COLS; j++)
        {
            cout << world[i][j];
        }

        cout << endl;
    }
}

更新

在main的while语句中发现了一个问题。我曾有一个 ;过了一会儿:

while(true);
{
/*Clear screen and display world*/
system("cls");
display(world);

/*Wait*/
Sleep(800);

/*Update World*/
generation(world, world_copy);
} 

我继续把它拿出来,但现在我得到一个未定义的引用'在while循环中显示。

2 个答案:

答案 0 :(得分:3)

不正确的循环条件

void display(vector< vector<char> > &world)
{
    for (int i = 0; i < ROWS; i++)
    {
        for (int j = 0; i < COLS; j++)
        {
            cout << world[i][j];
        }

        cout << endl;
    }
}

应该是:

void display(vector< vector<char> > &world)
{
    for (int i = 0; i < ROWS; i++)
    {
        for (int j = 0; j < COLS; j++)
        {
            cout << world[i][j];
        }

        cout << endl;
    }
}

注意内部FOR循环的condition子句。

while()循环终止

不正确
while(true);

应该是:

while(true)

不正确的分配操作

此模式在代码中重复多次。保留第一项任务。第二个根本没有完成。这是条件表达式评估。看起来像这样:

world[i][j] = world_copy[i][j];
world[i][j] == DEAD;

应该看起来像这样(注意我猜这个副本是先前的状态。不知道你的意图是什么):

world_copy[i][j] = world[i][j];
world[i][j] = DEAD;
链接期间

未定义的符号显示()

文件顶部的函数原型是:

void display(vector< vector<char> > );

然而,以下实施是:

void display(vector< vector<char> >& )

注意第二个中的参考参数,第一个中的by-val参数。不同的参数列表=不同的签名。可能第二个是你想到的,所以改变原型(第一个)以匹配实现(第二个)。

数组索引超出界限

您的代码中有几个地方(具体是generation()函数),它超出了已分配向量的末尾。例如,

/*Checks neighbors for life*/
if(world_copy[i-1][j+1] == ALIVE)
{
    ALIVE_count++;
}
if(world_copy[i][j+1] == ALIVE)
{
    ALIVE_count++;
}
if(world_copy[i+1][j+1] == ALIVE)

这些[j+1][i+1]索引一旦达到(i==(ROWS-1))(j==(COLS-1))的条件,就会对您的流程(如果您很幸运)提出错误,因为ROWS和COLS是战场的分配大小。同样,当[i-1][j-1]位于其循环的开头({= 0或j = 0)时,ij

有许多方法可以解决这个问题,从逻辑到不检查什么会超出(易于检测)到用永远不会触及的死区构建你的领域(更多涉及,但代码更有趣)

结论:您必须学会有效地调试程序。如果您认为专业工程师只是喷出正确的代码,请再想一想。平均而言,我们花费了一半的时间(字面上)调试编写的代码。如果你发现自己花费更少,那么你可能没有给你的代码提供所需的尽职调查(并且坦率地应得)。

答案 1 :(得分:0)

  

我不确定最好的方法来编写没有完整的八个邻居的电路板上的地方

您应该将这些视为特殊情况。例如,代码i=0与您的循环分开,可以从i = 1开始。