Какой тип переменной наиболее подходит для этой задачи? - PullRequest
1 голос
/ 22 апреля 2011

В настоящее время я создаю класс для небольшого проекта и столкнулся с интересным сценарием, с которым я раньше не сталкивался.

Моя программа будет просто отображать информацию об определенных элементах в игре.Категория, с которой у меня возникают проблемы, - это стоимость товара.Например, стоимость предмета может быть:

  • 100 Серебро и 300 камней
  • 500 Медь, 300 камней и 2 редких металла
  • 175 Золото

Стоимость может быть любой из этих значений, то есть она может стоить только одного типа «валюты» или может стоить до трех различных типов «валюты».Кроме того, каждый тип валюты будет содержать ее изображение.Так что 100 Silver and 300 Stone будет выглядеть примерно так: 100(Int) Silver(image) and 300(Int) Stone(Image)

Итак, учитывая, что может быть несколько типов валюты и изображений, можно ли хранить их в массиве?Или другой тип переменной?

Просто ищу кого-то, чтобы пролить свет на проблему.Если это нужно объяснить с помощью примера класса, я могу это сделать.

РЕДАКТИРОВАТЬ

Хотя в моем объяснении не было ясности, яполучил много хороших ответов.На самом деле, многие из них подходят для правильного ответа.Я ценю все ответы и проголосовал за каждого из вас, кто имел полезную обратную связь.

Спасибо всем !!!

Ответы [ 6 ]

2 голосов
/ 22 апреля 2011

Кроме того, и это важно, поэтому я помещаю это наверху, даже если это редактирование. Не включайте в это ни одного изображения У вас должны быть только изображения в пользовательском интерфейсе. Теоретически вы можете запустить игру из командной строки, просто набрав свои команды. «Купить меч», «продать мусор», «атаковать гоблина» и т. Д. Когда вы начинаете объединять свой пользовательский интерфейс и «бизнес-логику», вы обнаруживаете, что вам очень трудно разделить их, когда приходит время что-то исправить.

У меня было бы что-то вроде этого

class Cost {
    // use the builder pattern - it makes it VERY easy to add new currency types
    // without breaking existing types
    // it does make it more difficult to remove types, but you would have to
    // modify everywhere a type that used a removed currency anyway, so it's no
    // ADDITIONAL work there.
    class Builder {
        private int copper;
        private int silver;
        private int gold;

        public Builder copper(int cu) { this.copper = cu; return this; }
        public Builder silver(int ag) { this.silver = ag; return this; }
        public Builder gold(int au) { this.gold = au; return this; }

        public Cost complete() {
            return new Cost(this);
        }

    }
    public final int copper;
    public final int silver;
    public final int gold;
    // other costs;

    private Cost(CostBuilder cb) {
        this.copper = cb.copper;
        this.silver = cb.silver;
        this.gold = cb.gold;
    }

}

class Item {
    String name;
    // other stuff

    private Set<Cost> costs;

    public Set<Cost> getCosts() {
        return java.util.Collections.unmodifiableSet(costs);
    }
}

используйте код, подобный следующему:

Cost allGold = new Cost.Builder().gold(175).complete();
Cost goldAndSilver = new Cost.Builder().silver(50).gold(50).complete();
Cost allMaterials = new Cost.Builder().gold(10).silver(30).copper(100).complete();

Set<Cost> costs = new HashSet<Cost>();
costs.add(allGold);
costs.add(goldAndsilver);
costs.add(allMaterials);

Item swordOf1000Truths = new Item("Sword of 1000 truths",costs);

и позже вы можете сделать это

// assume player found allGold by quering for what costs he could use
if(player.canAfford(allGold)) {
    player.spend(allGold);
    player.addItem(swordOf1000Truths);
}
2 голосов
/ 22 апреля 2011

Java - объектно-ориентированный язык; почему бы не иметь класс Item или Commodity, который инкапсулирует желаемое поведение вместо того, чтобы полагаться на примитивы? Вы будете скрывать сложность от клиентов, инкапсулируя ее в класс.

Если у вас есть несколько экземпляров Currency, вы также можете инкапсулировать преобразования между ними, а не встраивать константы по всему коду. Если вы измените конверсию, вам нужно будет сделать это только в одном месте.

2 голосов
/ 22 апреля 2011

Вы можете создать очень простой класс Стоимость

public class Cost {
    int amount;
    String currency;

    public Cost(int amount, String currency) {
        this.amount = amount;
        this.currency = currency;
    }
}

, а затем реализовать стоимость в виде ArrayList

List<Cost> cost = new ArrayList<Cost>();
cost.add (new Cost(100, "Gold"));

Это достаточно просто при сохранении гибкости для добавления новых валют


Пример с перечислением:

public class Cost {
    private int amount;
    private Currency currency;

    public Cost(int amount, Currency currency) {
        this.amount = amount;
        this.currency = currency;
    }
    public enum Currency {
        GOLD { public String toString() { return "gold"; } },
        SILVER { public String toString() { return "silver"; } },
        COPPER { public String toString() { return "copper"; } },
        STONE { public String toString() { return "stone"; } },
        RARE_METAL { public String toString() { return "rare"; } }
    }

    public String getImageName() {
        return new String(currency.toString()+".png");
    }

    public int getAmount() {
    return amount;
    }

    public String getCurrency() {
        return currency.toString();
    }
}

List<Cost> costs = new ArrayList<Cost>();
cost.add (new Cost(100, Cost.Currency.GOLD));
cost.add (new Cost(200, Cost.Currency.COPPER));

for (Cost cost: costs) {
    ImageIcon icon = createImageIcon(cost(i).getImageName());
    JLabel label1 = new JLabel(cost(i).getAmount(), icon, JLabel.CENTER);
}
1 голос
/ 22 апреля 2011

Я бы, наверное, выбрал enum для представления различных типов валют. Примерно так:

public enum Currency {
    GOLD("gold"),
    SILVER("silver"),
    COPPER("copper"),
    STONE("stone");

    private String displayName;

    private Currency(String displayName) {
        this.displayName = displayName;
    }

    public String toString() {
        return displayName;
    }
}

Здесь перечисление фактически имеет поле для хранения удобного для пользователя отображаемого имени валюты; в этом нет необходимости - я просто добавил это, чтобы сделать вывод довольно позже в моем примере. Он также может хранить соответствующее имя файла изображения (или даже фактическое изображение), но его лучше оставить на усмотрение любого пользовательского интерфейса, а не помещать его в модель здесь.

Вашему товару нужен только один Map для хранения его стоимости:

private Map<Currency, Integer> costs;

Пример грубого использования:

Item vorpalSword = new Item();
vorpalSword.getCosts().put(Currency.GOLD, 100);
vorpalSword.getCosts().put(Currency.STONE, 300);

StringBuilder costOutput = new StringBuilder();
for(Map.Entry<Currency, Integer> cost : vorpalSword.getCosts().entrySet()) {
    costOutput.append(cost.getValue() + " " + cost.getKey() + " ");
}
System.out.println(costOutput.toString());
1 голос
/ 22 апреля 2011

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

1 голос
/ 22 апреля 2011

В коде я бы просто сохранил стоимость предмета как одно значение (целое или двойное).Затем при отображении стоимости есть некоторый класс, который переводит внутреннее значение в любую валюту, которую вы хотите показать.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...