Инвентарь
От: Sorc17 Россия  
Дата: 09.08.11 13:10
Оценка:
Всем привет. Решил сделать такую простенькую вещь как инвентарь предметов игрока для своей игрушки. Но внезапно на толкнулся на непреодолимые без костылей проблемы. Постараюсь как можно короче изложить саму суть.

Не получается:

1) Написать метод добавления абстрактного предмета
2) Хранить предметы в адекватной коллекции

Первое не получается потому, что вообще говоря каждый предмет добавляется в инвентарь по разному, поэтому для его добавления нужно знать что за предмет мы добавляем.
Второе не получается потому, что из абстрактной коллекции нельзя без костылей достать предмет конкретного типа.

Вот самый минимальны пример, чтобы проиллюстрировать.

Предметы:
abstract class Item {
    int id;
}

class Gold extends Item {
    int count;

    void addCount(int count) {
        this.count += count;
    }
}
class Rune extends Item {
}


Игрок и инвентарь:
class Inventory {
    List<Item> items;

    void addItem(Item i) {
       items.add(i);
    }

    Item getItem() {
        // Как получить конкретный предмет из абстрактной коллекции?
    }
}

class Player {
    Inventory inv;

    void addItem(Item i) {
        // Если добавляем золото, то надо из инвентаря получить золото и увеличить его количество.
        // Если добавляем руну, то нужно просто добавить её в инвентарь.
        // Но как, если мы не знаем что такое i?
    }
}


Думал над двумя вариантами. Первый: добавить в предметы тип, чтобы можно было сделать switch() по типу предмета в addItem и поиск по предметам:
class Gold extends Item {
    int type = ItemTypes::GOLD;
    int count;

    void addCount(int count) {
        this.count += count;
    }
}
class Rune extends Item {
    int type = ItemTypes::RUNE;
}

class Inventory {
    List<Item> items;

    void addItem(Item i) {
       items.add(i);
    }

    Item getItem(int type) {
        foreach (Item i in items) {
            if (i.type == type) {
                return i;
            }
        }
    }
}

class Player {
    Inventory inv;

    void addItem(Item i) {
        switch(i.type) {
            case ItemTypes::GOLD:
                inv.getItem(i.type).addCount(i.count);
                break;
            case ItemTypes::RUNE:
                inv.addItem(i);
                break;
        }
    }
}


А второй вариант ещё хуже. это разнести этот switch() на методы:
class Player {
    Inventory inv;

    void addGold(Gold g) {
        inv.getItem(ItemTypes::GOLD).addCount(g.count);
    }
    void addRune(Rune r) {
        inv.addItem(r);
    }
}


В итоге не знаю как поступить. Сохранять в предмете его тип это вообще не очень. Как и плодить методы для каждого типа.
Для нас [Thompson, Rob Pike, Robert Griesemer] это было просто исследование. Мы собрались вместе и решили, что ненавидим C++ [смех].
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.