rogue like 游戏初始化错误

rogue like game initializing error

我正在为简单的 rogue-like 游戏制作一张简单的地图。 因此,我需要通过从字符数组 [i][j] 接收数据,使用为每个数组单元格创建的对象来初始化映射。 建议在其他文件如CWall.cpp、CWall.h中定义这样的CWall、CDoor类,下面是在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);
        }
    }
}

这不是正确的做法。您受制于 object slicing,因为我猜测您的 CObject 是一个对象而不是指向某个对象的指针。您需要在函数中 return 类型为 CObject* 的指针,然后对于每种情况 return 一个 new CMonsternew CPlayer 等。更好的是,使用智能指针代替。

您尝试实现的称为工厂方法模式,参见例如How to implement the factory method pattern in C++ correctly了解更多详情。

嗯,一方面,您实际上并没有初始化任何东西。 CWall* cwall = new CWall; 将是动态分配和初始化新 CWall 对象(当然,假设 CWall 具有默认构造函数)或与此相关的任何对象的正确方法。

您还需要记住的是,对于您使用 new 分配的所有内容,您稍后必须使用 delete 解除分配。因此,您需要考虑如何存储这些已分配的对象,以便确保您的析构函数或清理函数在完成后删除所有这些对象。要考虑的一种设计模式是 Object Pool,尽管很容易有几十种好的方法可以做到这一点。不过,这是您必须自己完成的步法,因为只有您足够了解您的项目才能 select 正确的设计模式。 (我链接到的那本书是一个很好的资源。)

编辑:根据您的评论,还有一个问题,那就是您正在 returning 不同类型的对象。这是一个简单的 inheritance 问题——只要所有这些对象都继承自 CObject 的抽象基础 class (或类似的东西),你可以简单地将 return 类型列为 CObject*。然后,只要您 return 继承自 CObject 的对象(或指向对象的指针),您就是黄金。

编辑 2:无论何时使用 new,您实际上都获得了一个指向动态分配对象的指针。这本身就产生了一些问题,包括如果分配失败,new 可以 return 一个空指针。一定要检查一下!智能指针可以防止其中的许多问题,但是您对智能指针的使用取决于您的设计模式选择。

您应该动态处理数据。你现在做的有几个问题。

更好的方法是:

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

这将利用多态性隐藏通用接口 (CObject) 后面的实际 class(例如 CWall)。正如您编写的那样,每个 "new" 对象(例如 cdoor)实际上将传递给 CObject 的复制构造函数。 None 其中实际上完成了任何有意义的事情。

当然,您需要将这些创作与适当的破坏配对。

虽然其他人正确地指出了如何编码您想要编码的想法,但我将专注于另一件事。即,这里不正确地使用多态性。从无意义的 Object 继承所有东西闻起来像 Java,并且在 C++ 中不受欢迎。 Princess 和 Monster 之间根本没有任何共同点(一个被亲吻,另一个被杀死,并且可以随心所欲地做事),所以当两者都继承自 Object 时,很难编写出合适的游戏机械。您还必须存储实际的对象类型(例如,一个枚举),然后转换为这种类型——因为只有其中一个对象具有方法 kiss()

整个代码将是一堆不安全转换的意大利面条,将无法维护或推理。

相反,请采用强类型方法。永远知道你面前的是什么类型!