Java &引用;如果;对于库存中的每一件物品,看起来都很难看

Java &引用;如果;对于库存中的每一件物品,看起来都很难看,java,Java,我现在正在学习java,为了一些练习,我正在为一个小游戏编写清单。您有3个插槽,每个插槽中可以放置一个项目 public boolean useItem(int place){ //out of array request? if (place > items.length) return false; //empty inventory place? if (items[place] == 0) return false; if (items[p

我现在正在学习java,为了一些练习,我正在为一个小游戏编写清单。您有3个插槽,每个插槽中可以放置一个项目

public boolean useItem(int place){
    //out of array request?
    if (place > items.length) return false;
    //empty inventory place?
    if (items[place] == 0) return false;

    if (items[place] == 1){
        //eat berrys
        items[place] = 0;
        return true;
    }
    if (items[place] == 2){
        //shoot arrow
        items[place] = 0;
        return true;
    }
    //item not there
    return false;
}

它是有效的,但为每一项写下越来越多的“如果”感觉很糟糕。有人知道更好的解决方案吗?

这可以通过
开关处理。看起来是这样的:

public boolean useItem(int place){
    //out of array request?
    if (place > items.length) return false;
    switch (items[place) {
        case 0: //empty
        default:
        return false;
        case 1: //eat berrys
            items[place] = 0;
        return true;
        case 2: //shoot arrow
            items[place] = 0
        return true;
    }
    //item not there
    return false;
}

if-else
树的另一种选择是
switch
语句

switch(items[place]) {
    case 0:
        return false;
    case 1:
        items[place] = 0;
        return true;
    case 2:
        items[place] = 1;
        return true;
    default:
        return false;
}

项目=项目[地点];//默认情况下,当位置为空时,您可以拥有一个不在库存中执行任何操作的EmptyItem

现在让我们想象一下你有

interface Item {
 void use();
}

class Berry implements Item{
  @Override
  public void use(){
     //eating a a barry
  }
}

class EmptyItem implements Item{
  @Override
  public void use(){
     //do nothing
  }
}
然后,您将在use中的方法中实现逻辑

item.use();
我建议您将清单创建为更复杂的对象,而不是数组(复杂对象可以使用数组自行组合)

假设有一个可以通过这种方式创建的库存(将其大小作为参数传递):

类目录{
私人物品[]项;
公共库存(整数大小){
项目=新项目[尺寸];
//默认情况下,引用为null,只是将其显式地用于op

对于(inti=0;i,我会说为项目使用自定义类,类似于:

class InventoryItems {
    private HashMap<Integer, Integer> items = new HashMap<Integer, Integer>();

    public InventoryItems(final HashMap<Integer, Integer> items) {
        this.items = items;
    }

    public boolean hasItem(final Integer index) {
        return items.containsKey(index) && items.get(index) > 0;
    }

    public boolean useItem(final Integer index) {
        if (!hasItem(index)) {
            return false;
        }

        items.put(index, 0);
        return true; 
    }
}
类清单项目{
私有HashMap项=新HashMap();
公共清单项目(最终HashMap项目){
这个项目=项目;
}
公共布尔项(最终整数索引){
返回项目.containsKey(索引)和&items.get(索引)>0;
}
公共布尔useItem(最终整数索引){
如果(!hasItem(索引)){
返回false;
}
项目。投入产出(指数,0);
返回true;
}
}
您所做的并不是错误的,只是从长远来看,这会让您很难实现。这会泄漏所有的域模型逻辑,因此您需要维护复杂的功能代码,并随时了解应用程序的状态


尽管出于测试和学习的目的,我认为正如其他人建议的那样,使用
开关
如果
检查列表中所有可能的项目。

使用
开关
语句你要找的关键字是“多态性”。顺便说一句,令人惊讶的是,到目前为止,没有人在发布的答案中提到这一点,即使其中有两个10k+用户。@knightrider,实际上,没有必要;)@Painter21我建议您使用OOP,这可能是您目前的高级话题,但一旦您对该语言及其语法有了一定的了解和信心,我坚信这应该是您的下一步。正如巴卢斯克所提到的,我将使用一个花哨的词,只是为了“专业”,多态性,但不确定这是否有帮助:)@sᴜʀᴇsʜᴀᴛᴛᴀ 也许他不喜欢某些人的想法,
switch
if
好,因为这不是真的。它的代码行可能更少,但也有同样的缺点。但是是的他应该这样写,而不是默默地投否决票。总是乐于讨论和辩论!开关确实可以编译成更高效的字节码(请参阅)所以在IF树上有一个小的优点。它在我的眼睛里也有点简洁。它看起来更干净。主要的问题仍然是:这个代码是静态的。如果你有更多的情况需要考虑,你必须扩展它。在这种情况下,像Emanuele Ivaldis解决方案这样的“动态”方法要好得多。(尽管我没有检查这个答案是否可靠;但一般来说,这是更好的方法)。群众的智慧让他获得了更多的选票。尽管如果OP不需要扩大规模,较小的解决方案没有什么错。
class InventoryItems {
    private HashMap<Integer, Integer> items = new HashMap<Integer, Integer>();

    public InventoryItems(final HashMap<Integer, Integer> items) {
        this.items = items;
    }

    public boolean hasItem(final Integer index) {
        return items.containsKey(index) && items.get(index) > 0;
    }

    public boolean useItem(final Integer index) {
        if (!hasItem(index)) {
            return false;
        }

        items.put(index, 0);
        return true; 
    }
}