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

Posted

技术标签:

【中文标题】在基于文本的游戏中,如何将对象放置在房间内?【英文标题】:How do you place an Object inside a Room in a text-based game? 【发布时间】:2018-01-12 08:27:43 【问题描述】:

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

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

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

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

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 中,我还需要一个对象向量。 Room 类中的向量是否跟踪每个 Room 中的对象?并且是 main.cpp 中的向量,用于跟踪玩家携带的所有对象。为什么房间类必须有一个对象指针向量?没有对象的向量就足够了吗?

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

房间.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;

对象.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&lt;Object*&gt; allObjects,我会得到这些 enter image description here。抱歉,我还不能嵌入图片。

【问题讨论】:

使用智能指针,例如std::shared_pointer 或 std:unique_pointer。原始指针最好留给专业人士(他们往往会避免使用它们)。这是一个相当高级的任务。你“使用指针”的要求让我有点怀疑课程材料。 谢谢你告诉我这个。你知道如何让每个房间知道他们有放置在其中的对象吗?我并不真正关心使用的方法,但第一块代码(这是我尝试过的)不会编译。 什么是编译器错误? 请查看我对原帖所做的修改。 【参考方案1】:

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

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

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

编辑 1:

为什么房间类必须有一个对象指针向量?

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

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

我不知道如何让每个房间知道他们在其中放置了对象。

你可能会做这样的事情(思考效率低下):

void Room::processMyObjects(void)

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

另外你要么必须声明r_ public,编写一个公共getter函数,或者以这种方式在Object声明中声明friend class Room,否则Room看不到Object的私有变量。

【讨论】:

你会在pushObject 函数中写什么?我创建了一个名为vector&lt;Object*&gt;allObjects 的对象指针向量,并在pushObject 函数内写道:allObjects.push_back(argObject)。我还在我的 Object 构造函数中包含了r-&gt;push_Object(this),但它没有编译。如果我的指针无处可去,我会尝试链表。 Room 类已经为我提供了,那么我是否仍然可以使用 Object 类的链表并将其集成到我的 Room 类中? 进行了一些编辑...如果您遇到编译时错误,发布完整代码和错误输出可能会更容易。 是的,我认为我最重要的问题是编译时错误。我尝试粘贴我的完整代码,但它超过了最大字数。有什么办法可以解决吗? 链接在我原来的帖子里。我刚刚解决了我的问题。非常感谢您的帮助!【参考方案2】:

在这种情况下,您有一个多对五月的关系。一个房间不拥有一个对象,一个对象在一个房间里。您可以使用稀疏映射对多对五关系进行建模。说,std::unordered_multimap&lt;Room*, Object*&gt;。使用这种方法,您可以轻松查询特定房间中的所有对象或通过关联不同的键将对象移动到另一个房间。如果您想知道哪个房间包含您的对象,您将需要一个反向地图std::unordered_multimap&lt;Object*, Room*&gt;。此外,智能指针不会帮助您,因为您不会经常创建和销毁对象。最好将对象的生命周期与它们关联的级别的生命周期绑定。

【讨论】:

以上是关于在基于文本的游戏中,如何将对象放置在房间内?的主要内容,如果未能解决你的问题,请参考以下文章

基于文本的游戏。主功能

如何使用 socket.io-p2p 在房间内建立对等连接?

如何在完全基于精灵的游戏中渲染文本? (动作脚本 3)

如何基于声网互动白板实现一个多人数独游戏

Unity 知识点 - 2D游戏 - 透明屋顶

如何在 XAML 中的 Rectangle BoxView 内放置文本