Как поместить объект в комнату в текстовой игре?

Я новичок в программировании (и, несмотря на то, что мое имя пользователя может означать, что я далеко не профессионал), я пытаюсь написать свою собственную текстовую приключенческую игру. У меня есть два вопроса.

Во-первых, я хочу реализовать класс Object. У этих объектов есть имена и описания, и их можно размещать в комнатах, а также брать и носить с собой игрок. Что меня смущает, так это то, что эти Объекты должны знать, в какой комнате они изначально находились, так сказать, их «классная комната».

Я не уверен, как сообщить каждой комнате, что в них размещены объекты. Все, что я пытался сделать, не удалось скомпилировать.

Я попытался включить 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 мне также нужен вектор объектов. Отслеживает ли вектор внутри класса Room объекты в каждой комнате? И является вектором в main.cpp, отслеживающим все объекты, которые несет игрок. Почему класс комнаты должен иметь вектор указателя на объекты? Не будет ли достаточно иметь вектор объектов?

(Прошу прощения, если это звучит расплывчато; эта игра основана на задании, которое можно найти здесь. Если вы прокрутите вниз до раздела «Дополнительные баллы» и перейдете к первому блоку абзаца, отмеченному 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;
}

Объект.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; 


}

EDIT: Итак, если я просто добавлю vector<Object*> allObjects в частные атрибуты в Room.h, я получу эти введите здесь описание изображения. Извините, мне пока не разрешено вставлять изображения.


person probeginner    schedule 12.01.2018    source источник
comment
Используйте умные указатели, например. std::shared_pointer или std:unique_pointer. Необработанные указатели лучше оставить профессионалам (которые будут стараться их избегать). Это довольно сложное задание для новичка. Требование, чтобы вы использовали указатели, заставляет меня немного подозревать материал курса.   -  person Jive Dadson    schedule 12.01.2018
comment
Спасибо, что сказали мне это. Есть ли у вас какие-либо идеи, как сообщить каждой комнате, что в них размещены объекты? Меня не волнует используемый метод, но первый блок кода (что я и пробовал) не скомпилируется.   -  person probeginner    schedule 12.01.2018
comment
какая ошибка компилятора?   -  person corsel    schedule 12.01.2018
comment
Пожалуйста, посмотрите изменения, которые я внес в свой исходный пост.   -  person probeginner    schedule 12.01.2018


Ответы (2)


Я бы рекомендовал (пытаясь максимально придерживаться предложенной вами архитектуры) определить метод void Room::pushObject(Object* argObject). Внутри вашего конструктора Object::Object вы можете добавить вызов r->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_ общедоступным, написать общедоступную функцию-получатель, либо объявить friend class Room внутри Object объявлений таким образом, иначе Room не сможет увидеть частную переменную Object.

person corsel    schedule 12.01.2018
comment
Что бы вы написали внутри функции pushObject? Я создал вектор указателя объектов с именем vector<Object*>allObjects, а внутри функции pushObject написал: allObjects.push_back(argObject). Я также включаю r->push_Object(this) в свой конструктор объектов, но он не компилируется. Если я ничего не получу с указателями, я попробую связанный список. Класс Room уже был предоставлен мне, поэтому смогу ли я по-прежнему использовать связанный список для класса Object и интегрировать его в свой класс Room? - person probeginner; 12.01.2018
comment
Сделал некоторые правки... Если вы получаете ошибки во время компиляции, может быть, было бы проще, если бы вы разместили свой полный код и вывод ошибок. - person corsel; 12.01.2018
comment
Да, я думаю, что моя основная проблема - это ошибки времени компиляции. Я попытался вставить свой полный код, но он превышает максимально допустимое количество слов. Есть ли способ обойти это? - person probeginner; 12.01.2018
comment
Ссылка есть в моем исходном посте. Я только что решил свою проблему. Спасибо большое за вашу помощь! - person probeginner; 12.01.2018

В этом случае у вас есть отношение Many-to-May. Комната не владеет объектом, объект находится в комнате. Вы можете смоделировать отношение Many-to-May с помощью разреженной карты. Скажем, std::unordered_multimap<Room*, Object*>. При таком подходе вы можете легко запросить все объекты в определенной комнате или переместить объект в другую комнату, связав его с другим ключом. Вам понадобится обратная карта std::unordered_multimap<Object*, Room*>, если вы хотите узнать, в какой комнате находится ваш объект. Кроме того, умные указатели не помогут вам, потому что вы не будете часто создавать и уничтожать объекты. Время жизни объектов лучше связать со временем жизни уровня, с которым они связаны.

person Minor Threat    schedule 12.01.2018