0

I'm creating a simple RPG console game, I'm at the stage of creating an inventory and loot system. Present in the program, both class Player and class Monster have the arrayList Backpack properties, when the program creates an object of the monster class, items in the monster's backpack are also automatically created, after killing the monster, you can take them to your backpack, and this is where my problem begins how to elegantly prevent duplication of items in the backpack, each item is a class too, now this function works by checking in a nested loop each item one by one to see if it is already in the backpack if it is instead of adding it once moreover, it increases its amount property, if I don't have this item in my backpack, it just adds to the list, the solution works, but definitely it is not the right solution, because with many of items this checking mechanism will grow a lot, if anyone has any valuable tips I will be grateful. I also have a second idea to create a boolean Is_it_in_Backpack variable, and somehow connect it with the loot collecting mechanism

Below some code sample

public class Player {
public static ArrayList<Item> Backpack = new ArrayList<>()
}

and the class Skieleton:

public class Skieleton extends Monsters {
 public static ArrayList<Item> Backpack;
 public Skieleton() {
 Backpack = new ArrayList<>();
 Backpack.add(new Weapon("Rusty sword", "Just a rusty sword", 3, 2 ));
 Backpack.add(new Armor("Leather Armor", "Old leather armor", 6, 3));
 }

class item:

public class Item {
 public String ItemName;
 public String Description;
 public int ItemSize;
 public int ItemWeight;
 public int Amount;
 public Item(String ItemName, String Description, int ItemSize, int ItemWeight)
 {
 this.ItemName = ItemName;
 this.Description = Description;
 this.ItemSize = ItemSize;
 this.ItemWeight = ItemWeight;
 }
 public Item() {
 }
}
Thiyagu
18k5 gold badges49 silver badges88 bronze badges
asked Dec 17, 2021 at 18:28
4
  • hmm can u give me some simple example? Commented Dec 17, 2021 at 18:38
  • I take back what I said. Set wouldn't help you merge the items. It will replace them Commented Dec 17, 2021 at 19:04
  • As one of the answers say, you can use a Map. It would be better if you take the amount out of the Item and keep it only in the map Map<Item, Integer> Commented Dec 17, 2021 at 19:08
  • @user7 is there any relationship between monsters and player? are monsters considered player? Since monsters and players are all carry backpacks and have similar properties, you might want to make both extend a common class. Commented Dec 20, 2021 at 19:02

4 Answers 4

3

I recommend you use a class that extends java.util.Set:

  • If order is not important for you, you can use HashSet;
  • If order of insertion is important, you can use LinkedHashSet;
  • If natural order is important (alphabetical by name or other property), you can use TreeSet and implement the interface Comparable onto the class inserted in the collection.

However, regardless of your choice, it's recommended you implement hashCode() (for optimization) and equals() (to let collection identify which item is equal to other and avoid duplication).

answered Dec 17, 2021 at 18:46

1 Comment

The OP doesn't want to replace the items. If the same item is present, its quantity/amount must be increased
3

If you can use third party libraries, I'd recommend using a Bag from Eclipse Collections.

With your Item class implementing equals and hashCode on ItemName field, your example usage could look like:


final MutableBag<Item> backPack = new HashBag<>();
final Item rustySword = new Item("Rusty sword", "Just a rusty sword", 3, 2);
final Item leatherArmour = new Item("Leather Armor", "Old leather armor", 6, 3);
 
backPack.add(rustySword);
backPack.add(leatherArmour);
backPack.add(rustySword);
System.out.println(backPack.toMapOfItemToCount()); // prints {Item[ItemName='Rusty sword']=2, Item[ItemName='Leather Armor']=1}
System.out.println(backPack.occurrencesOf(rustySword)); // prints 2

The API is rich, and provides a lot more: https://www.eclipse.org/collections/javadoc/11.0.0/org/eclipse/collections/api/bag/Bag.html

answered Dec 17, 2021 at 19:42

Comments

1

I would use a Map.

Here's my suggestion:

 import java.util.*;
 class Player {
 public Backpack backpack= new Backpack();
}
class Monster { }
 class Skieleton extends Monster {
 public Backpack backpack= new Backpack();
 public Skieleton() {
 
 backpack.add(new Weapon("Rusty sword", "Just a rusty sword", 3, 2 ));
 backpack.add(new Armor("Leather Armor", "Old leather armor", 6, 3));
 }
}
class Backpack {
 private HashMap<Item,Item> items = new HashMap<>();
 
 public Item add(Item item){
 if (items.containsKey(item)){
 items.get(item).Amount=+ item.Amount;
 return items.get(item);
 } else {
 items.put(item,item);
 return item;
 }
 }
 
 public Item get(Item item){
 return items.getOrDefault(item, null);
 }
}
class Item {
 public String ItemName;
 public String Description;
 public int ItemSize;
 public int ItemWeight;
 public int Amount;
 public Item(String ItemName, String Description, int ItemSize, int ItemWeight)
 {
 this.ItemName = ItemName;
 this.Description = Description;
 this.ItemSize = ItemSize;
 this.ItemWeight = ItemWeight;
 }
 public Item() {
 }
 
 public boolean equals(Object o){
 if (o instanceof Item){
 return ItemName.equals( ((Item)o).ItemName);
 }
 return false;
 }
}
answered Dec 17, 2021 at 19:02

5 Comments

hello could u help me a little bit more? I have never dealt with hashmaps, and I cant do it anyway...
OK. I can suggest a solution without the use of a hashmap. It will just be arraylist.
It can be a HashMap, i want to learn it, but I don't understad ur solution in 100% :D why a HashMap is <Item, Item> , and not for example <Item, Amount>, I;m new in Java its my first project and just "cant see" solution here.... sryy =D
The reason is because the Amount is in the Item object. If it's separate, then you could have <Item, Integer>. I will modify my answer to reflect this.
I think we should stick with ArrayList. I think introducing hashmap would only complicate things. You would need to override methods such as hashCode, equals in many of your item classes.
1

You can use a HashMap for storing the items. First, I would like to change the Item class to not have amount field in it. Let an item denote what an item is (name, description, size and weight).

Here's the updated backpack:

Map<Item, Integer> backpack = new HashMap<>();

To add an item, you can use Map#merge method.

public void addItemToBackpack(Item item, int quantity) {
 backpack.merge(item, quantity, (oldQuantity, newQuantity) -> oldQuantity + newQuantity);
}

We insert the item and its quantity. If the item is not already present, it will be inserted with the passed quantity.

If it is already present, then the BiFunction which is a mapping function will be called with the existing value (oldQuantity) and the new value which we tried to insert (newQuantity). We sum them both, return it and the item's value (quantity) will be updated with this value.

Using method references, we can write the above as,

backpack.merge(item, quantity, Integer::sum);
answered Dec 17, 2021 at 19:15

1 Comment

could u help me a little but more with it? I have never dealt with hashmaps and I have few more questions

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.