2

C++でのConwayのGameofLifeのコーディングでいくつか問題が発生しています。私は良いスタートを切ったように感じます、私はただいくつかの方向性が必要です。まず、プログラムを実行しようとすると、空白のコンソールが表示され続けます。また、8つのネイバーが完全に存在しないボード上の場所をコーディングするための最良の方法もよくわかりません。どんな助けでもいただければ幸いです。

ルール:

開始構成を「ハードコーディング」します。ユーザーは、別の開始構成を提供できる必要はありません(プログラムが複雑になるだけです)。

提案:安定した構成を探してください。つまり、パターンを継続的に繰り返すコミュニティを探します。繰り返しの構成の数は期間と呼ばれます。修正された構成があり、変更なしで続行されます。考えられるプロジェクトは、そのような構成を見つけることです。

ヒント:現在の(または初期の)構成を含む、worldと呼ばれるベクトル(参照による呼び出しまたはポインターの使用)をとるgenerationという名前のvoid関数を定義します。この関数は、ベクトルをスキャンしてセルを変更し、前述のルールに従ってセルに出生と死亡のマークを付けます。これには、各セルを順番に調べて、セルを殺すか生きさせるか、セルが空の場合はセルを作成するかどうかを決定することが含まれます。コードが変更しているのと同じベクトル内のネイバーをカウントする場合、ゲームは機能しないことに注意してください。ワールドベクトルのコピーは、変更する前に作成する必要があります。このコピーは、元のベクトルでセルがオンまたはオフになっているときに、ネイバーをカウントするために使用されます。

ベクトルの世界を受け入れ、画面にグリッドを表示する関数表示が必要です。生成と表示の呼び出しの間には、ある種の時間遅延が適切です。これを行うには、Return / Enterキーを押したときに、プログラムが次世代を生成して表示する必要があります。これを自動化するのは自由です(リアルタイムの遅延を入れ、ユーザーがキーを押すのを待たないでください)が、プログラムに自動化は必要ありません。

ユーザーが何かを入力してEnterキーを押してから次のグリッドを表示するのを待つのではなく、グリッドの表示を「遅らせる」場合は、プログラムを一時停止または「スリープ」する必要があります。Microsoft Windowsを使用している場合は、次のようにします。

各セルを8つの隣接セルを持つように定義します。セルの隣接セルは、真上、真下、右、左、対角線上で右と左、斜め下で右と左のセルです。エッジのネイバーをチェックするときは注意してください。エッジセルに、エッジを超えて生存している隣接セルがあるか、死んでいる隣接セルがあるかを判断できます。

占有されたセルに0個または1個の隣接セルがある場合、それは孤独で死にます。占有されているセルに3つ以上の隣接セルがある場合、過密状態で停止します。

空のセルにちょうど3つの隣接セルが占有されている場合、空のセルを置き換える新しいセルが誕生します。

誕生と死は瞬間的であり、世代交代で発生します。何らかの理由で細胞が死ぬと出産に役立つ可能性がありますが、生まれたばかりの細胞は死んでいる細胞を復活させることはできません。

これまでの私のコード:

/*

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ループで'displayへの未定義の参照を取得しています。

4

2 に答える 2

4

不適切なループ状態

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 ループの条件句に注意してください。

while() ループの不適切な終了

while(true);

次のようにする必要があります。

while(true)

不適切な代入操作

このパターンは、コード内で何度も繰り返されます。最初の割り当ては保持されます。2番目はまったく行われていません。条件式の評価です。次のようになります。

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

おそらく次のようになります(コピーが以前の状態であると推測していることに注意してください。ここで何を意図しているのかわかりません):

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

リンク中の未定義シンボル display()

ファイルの先頭にある関数のプロトタイプは次のとおりです。

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

それでも、以下の実装は次のとおりです。

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

2 番目の参照パラメーター、最初の by-val パラメーターに注意してください。異なるパラメーター リスト = 異なる署名。おそらく 2 番目はあなたが考えていたものなので、プロトタイプ (1 番目) を実装 (2 番目) に合わせて変更してください。

範囲外の配列インデックス

コード (具体的には 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)

ROWS と COLS は戦場の割り当てられたサイズであるため、これら[j+1]とインデックスはorの条件に[i+1]達するとすぐにプロセスを失敗させます (運が良ければ) 。同様に forとwhenとare はループの開始点 (i=0 または j=0)(i==(ROWS-1))(j==(COLS-1))[i-1][j-1]ij

これに対処する方法はいくつかあります。たとえば、オーバーランとなるものをチェックしない (検出しやすい) ロジックから、触れられないデッド ゾーンでフィールドをフレーミングする (より複雑ですが、コーディングするのがより楽しい) までです。

結論:プログラムを効果的にデバッグする方法を学ばなければなりません。プロのエンジニアが正しいコードを吐き出すだけだと思っているなら、考え直してください。平均して、書かれたコードのデバッグに (文字通り) 半分の時間を費やしています。支出が少しでも減っていることに気付いた場合は、コードに必要なデューデリジェンスを行っていない可能性があります (率直に言って、それに値します)。

于 2012-09-22T23:44:41.700 に答える
0

完全な 8 つの隣接がないボード上の場所をコーディングする最善の方法がよくわかりません。

おそらく、これらは特別なケースとして扱う必要があります。たとえば、 でi=0開始できるループとは別にコーディングしますi = 1

于 2012-09-22T23:45:47.727 に答える