0

シンプルなローグライク ゲームの簡単なマップを作成しています。そのため、文字配列 [i] [j] からデータを受け取って、配列セルごとに作成されたオブジェクトでマップを初期化する必要があります。このような CWall、CDoor クラスは、CWall.cpp、CWall.h などの他のファイルで定義することをお勧めします。その下には、map.cpp で初期化するコードがあります。

しかし、これは正しいコーディング方法でしょうか? これにより、メモリの割り当ての問題が発生すると思います。

CObject CMap::insertObject(char character){ 
    if (character = '*') {
        CWall cwall;
        return cwall;
    }

    if (character = 'D') {
        CDoor cdoor;
        return cdoor;
    }

    if (character = 'F') {
        CFood cfood;
        return cfood;
    }

    if (character = 'K') {
        CKey ckey;
        return ckey;
    }

    if (character = 'M') {
        CMMonster cmmonster;
        return cmmonster;
    }

    if (character = 'm') {
        CMonster cmonster;
        return cmonster;
    }

    if (character = '@') {
        CPlayer cplayer;
        return cplayer;
    }

    if (character = 'P') {
        CPrincess cprincess;
        return cprincess;
    }

    if (character = '&') {
        CRock crock;
        return crock;
    }

    if (character = 'S') {
        CShield cshield
        return cshield;
    }

    else {
        CShield cshield;
        return cshield;
    }
}

void CMap::initialize(char arr[][COLS]){
    for (int i = 0; i <= 11; i++){
        for (int j = 0; j <= 38; j++){
            char character = arr[i][j];
            insertObject(character);
        }
    }
}
4

4 に答える 4

3

それは正しい方法ではありません。あなたはobject slicingの対象です。私の推測では、あなたCObjectはオブジェクトであり、オブジェクトへのポインターではないからです。CObject*関数でタイプのポインターを返す必要があり、次にそれぞれの場合にnew CMonsterまたはnew CPlayerなどを返す必要があります。さらに良いのは、代わりにスマートポインターを使用することです。

実装しようとしているものは、ファクトリ メソッド パターンと呼ばれます。詳細については、たとえば、C++ でファクトリ メソッド パターンを正しく実装する方法を参照してください。

于 2015-11-30T19:38:54.513 に答える
2

他の人はコード化したいアイデアをコード化する方法を正しく指摘しましたが、私は別のことに焦点を当てます。つまり、ここではポリモーフィズムの不適切な使用です。無意味な Object からすべてを継承するのは Java の匂いがして、C++ では歓迎されません。プリンセスとモンスターには何の共通点もありません (一方がキスされ、もう一方が殺され、好みに応じて何をするか)、両方がオブジェクトから継承される場合、適切なゲームをプログラムすることは非常に困難です。メカニック。実際のオブジェクト タイプ (たとえば、列挙型) も格納する必要があり、このタイプにキャストする必要があります。メソッドを持つのはそのうちの 1 つだけだからkiss()です。

コード全体が安全でないキャストのスパゲッティになり、保守や推論が不可能になります。

代わりに、厳密に型付けされたアプローチを使用してください。目の前にどんなタイプがいるかを常に把握!

于 2015-11-30T19:49:08.620 に答える
0

まず、実際には何も初期化していません。CWall* cwall = new CWall;新しい CWall オブジェクトを動的に割り当てて初期化する適切な方法 (もちろん、CWall には既定のコンストラクターがあると仮定します)、またはそのための任意のオブジェクトです。

また、心に留めておく必要があるのは、 で割り当てたものはすべて、後でnewで割り当てを解除する必要があるということです。deleteしたがって、これらの割り当てられたオブジェクトをどのように格納するかを考える必要があります。そうすれば、完了時にデストラクタまたはクリーンアップ関数がそれらをすべて削除できるようになります。考慮すべき設計パターンの 1 つはObject Poolですが、それを行うための優れた方法は簡単に数十あります。ただし、適切なデザイン パターンを選択するには、プロジェクトについて十分に理解している必要があります。(私がリンクしたその本は素晴らしいリソースです。)

編集:あなたのコメントによると、もう 1 つの問題があります。それは、さまざまな種類のオブジェクトを返すことです。これは継承の単純な問題です。これらのオブジェクトがすべて (または同様のもの) の抽象基本クラスから継承されている限りCObject、戻り値の型を として単純にリストできますCObject*。次に、から継承するオブジェクト (またはオブジェクトへのポインター) を返す限りCObject、あなたはゴールデンです。

編集 2: を使用するたびnewに、動的に割り当てられたオブジェクトへのポインターを実際に取得しています。newこれは、割り当てが失敗した場合に null ポインターを返す可能性があるなど、独自の問題を引き起こします。必ずチェックしてください!スマート ポインターを使用すると、これらの問題の多くを防ぐことができますが、スマート ポインターの使用はデザイン パターンの選択によって異なります。

于 2015-11-30T19:39:18.480 に答える