2

I am learning java right now and for some practice I am programming an inventory for a little game. You have 3 slots and in each you can put an item.

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;
}

It works, but it feels bad to write down more and more "if" for every single item. Does anyone know a better solution?

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
Painter 21
  • 23
  • 3
  • 2
    use `switch` statement – knightrider Oct 17 '15 at 15:10
  • 1
    The keyword you're looking for is "polymorphism". It's by the way surprising that no one covered that in the answers posted so far, even there are two 10k+ users among them. – BalusC Oct 17 '15 at 15:15
  • @knightrider Actually, no need ;) – Suresh Atta Oct 17 '15 at 15:17
  • @Painter21 I'd advise you to use OOP, probably that might be advanced topic for you right now, but once you build up a bit of knowledge and confidence with the language and it's syntax I strongly believe that should be the next step for you. As #BalusC mentioned I'll through a fancy word just for the sake of being "pro", polymorphism, not sure if that helps though :) – Alex Rashkov Oct 17 '15 at 15:35

4 Answers4

5

Item item = items[place]; // by default you can have an EmptyItem that does nothing in the inventory when the place is empty

now let's imagine you have something like

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
  }
}

then you would implement the logic in the method inside the use

item.use();

I would suggest you to create your inventory as bit more complex object instead of an array (the complex object can be composed itself using an array)

Imagine to have an inventory that can be created this way (passing its size as a parameter):

class Inventory{

    private Item[] items;

    public Inventory(int size){
        items = new Item[size];
        // references are null by default, just making this explicit for op
        for(int i = 0; i<size; i++){
           items[i] = null;
        }
    }

    public void addItem(int space, Item item){
       // check for input params
       // check array boundaries
       // check for item in the selected space
       if(items[space] == null){
           items[space] = item;
       }else{
          // space not empty!
       }
    }

    // I'd like more the approach of using get item -> item.use() :)
    // but this is a bit more inline with op approach
    public void useItem(int space){
       // check array boundaries
       Item item = items[space];
       if(item != null){
           item.use();
       }
    }    

    // keeping the null management inside the class itself
    public Item getItem(int space){
       // check array boundaries           
       Item item = items[space];
       if(item == null){
         item = new EmptyItem();
       }
       return item;
    }     
}

Just imagine what you are modeling to be real life objects, imagine how they intefact one another, and try to model their properties and behaviour accordingly :)

Emanuele Ivaldi
  • 1,332
  • 10
  • 15
1

An alternative to an if else tree is the switch statement.

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

DEMO

Yassin Hajaj
  • 21,337
  • 9
  • 51
  • 89
christopher
  • 26,815
  • 5
  • 55
  • 89
  • @sᴜʀᴇsʜᴀᴛᴛᴀ maybe (s)he doesn't like the thinking of some people, that `switch` is better than `if`, since this isn't true. It might have less lines of code, but shares the same disadvantages. But yes, (s)he should have wrote that, instead of downvoting silently. – Tom Oct 17 '15 at 16:30
  • Always happy to discuss and debate! A Switch does compile down into more efficient byte code (See [here](http://stackoverflow.com/questions/10836055/why-is-the-switch-statement-faster-than-if-else-for-string-in-java-7)) so there is a slight advantage over an if else tree. It is a little more terse in my eyes too. It looks cleaner. – christopher Oct 17 '15 at 18:09
  • 1
    The main problem remains: this code is static. You have to extend it if you have more cases to consider. A "dynamic" approach, like Emanuele Ivaldis solution is much better in this case (even though I haven't checked this answer if it is solid or not; but generally speaking it is the better approach). – Tom Oct 17 '15 at 19:30
  • And the wisdom of the crowds has granted him more up votes. Though there's nothing wrong with a smaller solution if the OP isn't going to need to scale. – christopher Oct 18 '15 at 08:37
1

I'd say use a custom class for items, something like:

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; 
    }
}

What you're doing is not wrong just makes it really hard to mentain in the long run. This is leaking all of the domain model logic outside and thus you have complex functional code that needs to be maintained and aware of the state of the application at any point of time.

Though for testing and learnign purposes I think as other people have proposed use a switch or if check for all possible items in the list.

Alex Rashkov
  • 9,833
  • 3
  • 32
  • 58
0

This can be handled by a switch case. That would look like this:

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;
}
nbokmans
  • 5,492
  • 4
  • 35
  • 59