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 CMonster
或 new 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()
!
整个代码将是一堆不安全转换的意大利面条,将无法维护或推理。
相反,请采用强类型方法。永远知道你面前的是什么类型!
我正在为简单的 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 CMonster
或 new 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()
!
整个代码将是一堆不安全转换的意大利面条,将无法维护或推理。
相反,请采用强类型方法。永远知道你面前的是什么类型!