在基于文本的游戏中,如何将对象放置在房间内?

How do you place an Object inside a Room in a text-based game?

我是一名编码新手(尽管我的用户名可能暗示我远非专业人士),但我正在尝试编写自己的基于文本的冒险游戏。我有两个问题。

首先,我想实现一个对象class。这些对象具有名称和描述,可以放置在房间中,也可以由玩家拾取和携带。让我感到困惑的是,这些对象应该知道它们最初所在的房间,可以说是它们的 "homeroom"。

我不确定如何让每个房间知道它们中放置了对象。我尝试做的所有事情都无法编译。

我尝试将 Room r 作为私有变量包含在 Object.cpp 中,并将 Room 包含到对象构造函数中。

Object::Object(string name, string description, Room *r)
{
    name_ = name; 
    description_ = description; 
    r_ = r; //assume r_ is a private variable

}

其次,关于指针...这个作业指定我必须有一个对象指针向量。会像这样吗?

vector<Object*>objectsInRoom; 

在main.cpp中,我还需要一个对象向量。房间内的矢量 class 是否跟踪每个房间中的对象?并且是 main.cpp 中的向量,用于跟踪玩家携带的所有物体。为什么房间 class 必须有对象指针的向量?对象向量不够吗?

(如果这听起来含糊不清,我深表歉意;这个游戏基于可以找到的作业 here。如果您向下滚动到 "Extra Credit" 部分并转到第一段块标记为 10 分,你会发现我在上面试图浓缩的更广泛的解释。)

room.cpp

// Room.cpp: implementation of the Room class.
//
//////////////////////////////////////////////////////////////////////

#include "Room.h"


//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

Room::Room()
{
    name_ = "The void";
    description_ = "There is nothing but blackness in every direction.";
    int i;
    for(i = 0; i < 4; i++) // set all exits to "closed"
        exits_.push_back(NULL);


}

Room::Room(string name, string desc)
{
    name_ = name;
    description_ = desc;
    int i;
    for(i = 0; i < 4; i++) // set all exits to "closed"
        exits_.push_back(NULL);


}

Room::~Room()
{
    cout << "Destroying: " << name_ << endl; 
    // make sure all exits to this room are
    // destroyed so that no one can try to enter
    // this room from another location
    if(exits_[NORTH] != NULL)
        disconnect(NORTH);
    if(exits_[EAST] != NULL)
        disconnect(EAST);
    if(exits_[SOUTH] != NULL)
        disconnect(SOUTH);
    if(exits_[WEST] != NULL)
        disconnect(WEST);
}

// --- inspectors ---
Room * Room::north() const
{
    return exits_[NORTH];
}

Room * Room::south() const
{
    return exits_[SOUTH];
}

Room * Room::east() const
{
    return exits_[EAST];
}

Room * Room::west() const
{
    return exits_[WEST];
}


string Room::name() const
{
    return name_;
}

string Room::description() const
{
    return description_;
}

/*
vector<Object> Room::object() const
{
    return roomObjects; 
}
*/

// --- mutators ---
void Room::set_name(string n)
{
    name_ = n;
}

void Room::set_description(string d)
{
    description_ = d;
}

/*
void Room::set_object(Object o)
{
    allObjects.push_back(o); 
}
*/
// --- facilitators ---
bool Room::connect(Direction exit, Room *r, Direction to)
{
    // check that both exits are free
    if (exits_[exit] != NULL or r->exits_[to] != NULL)
        return false;
    // make connection
    exits_[exit] = r;
    r->exits_[to] = this;
    return true;
}

// --- private methods ---

void Room::disconnect(Direction d)
{
    // disconnects ALL exits from another
    // room to this one.  It's sloppy, but
    // that's OK.
    Room * other_room;
    other_room = exits_[d];
    int i;
    for(i = 0; i < 4; i++)  {
        if (other_room->exits_[i] == this)
            other_room->exits_[i] = NULL;
    }
}

// --- operators ---

ostream & operator<<(ostream & out, const Room & r) {
    out << r.name() << endl;
    out << r.description() << endl;
    return out;
}

Object.cpp

#include "Object.h"; 

Object::Object()
{
    name_ = "Object"; 
    description_ = "The object lies in the room"; 

}

Object::Object(string name, string description)
{
    name_ = name; 
    description_ = description; 


}

编辑:所以,如果我简单地在 Room.h 的私有属性下添加 vector<Object*> allObjects,我会得到这些 enter image description here。抱歉,我还不能嵌入图片。

我建议(尽量遵守您提出的架构)定义一个方法 void Room::pushObject(Object* argObject)。在您的构造函数 Object::Object 中,您可以添加一个调用 r->pushObject(this)。然后,您可以在进入房间后遍历向量。

此外,链表 std::deque 将是满足您需求的更好解决方案,因为它专为更快的插入和删除而设计。然后你可以room1.insert(room0.erase(yourObjPtr))移动你的对象。

请注意,答案是理论上的,我没有检查这些是否编译。

编辑 1:

Why must the room class have a vector of pointer of Objects?

您可能还有一个对象实例本身的向量,但是当您希望将对象移动到另一个房间时,程序必须复制所有内容,而不是传递单个指针。此外,它将禁止使用继承(您可能会在不久的将来使用它:))

编辑 2: 我现在也看到我误解了你的设计。您打算使用单个全局向量。我以为您想使用更多 "object-oriented" 方法,可以这么说。我会为每个房间放一个 std::deque,但如果你想保持这种方式,关于你的主要问题

I'm not sure how to let each Room know that they have Objects placed within them.

你可能会这样做(认为效率低下):

void Room::processMyObjects(void)
{
    for (int i = 0; i < globalObjectVector.size(); i++)
    {
        if (globalObjectVector[i]->r_ == myRoomId)
        {
            // do whatever you want here.
        }
    }
}

此外,您要么必须声明 r_ public,编写一个 public getter 函数,要么在 [=19= 中声明 friend class Room ] 这样声明,否则 Room 看不到 Object.

的私有变量

在这种情况下,您有一个 Many-to-May 关系。一个房间不拥有一个对象,一个对象 在一个房间里。您可以使用稀疏映射对 Many-to-May 关系进行建模。说,std::unordered_multimap<Room*, Object*>。使用这种方法,您可以轻松地查询特定房间中的所有对象或通过与不同的键关联将对象移动到另一个房间。如果您想知道哪个房间包含您的物品,您将需要一张反向地图 std::unordered_multimap<Object*, Room*>。此外,智能指针也无济于事,因为您不会经常创建和销毁对象。最好将对象的生命周期与其关联级别的生命周期绑定。