Small inventory system Java (Novice)

Started by
5 comments, last by haegarr 10 years, 1 month ago
Hello I am learning JAVA and I am currently practicing arrays. Basically what I am trying to write is a small inventory management system with just arrays for my small RPG(no saves). I am stuck on the part where I have to put items from main table of items that exist in the entire game, into the limited space of the backpack. I cant seem to figure out how to insert items from "Item array" into "Backpack array" just by using reference ID which is also happens to be array index.


Here is my code: http://pastebin.com/wKSu5UD1

[source]

//IMS Main class//

class IMS {
public static void main(String[] arguments) {
Item product = new Item();
Inventory backpack = new Inventory();
product.createItem("Boots", 325, 1);
product.createItem("Sword", 410, 3);
product.createItem("Ring", 110, 2);
product.createItem("Dagger", 240, 2);
product.createItem("Bow", 810, 1);

product.displayItemList();

backpack.setMaxInventory(5);

}
}


// Item class //

class Item {
//Maximum Items allowed
private int maxItems = 5;
Item[] itemDB = new Item[maxItems];

//Item related
private int id;
String name;
int price;
int quantity;

Item(){
id = 0;
}

private Item(String name, int price, int quantity){
this.name = name;
this.price = price;
this.quantity = quantity;
}

private void idAutoIncrement(){
id = id + 1;
}

private void setItemID(){
itemDB[id].id = id;
}

void createItem(String name, int price, int quantity){
if (id < maxItems){
itemDB[id] = new Item(name, price, quantity);
setItemID();
idAutoIncrement();
} else {
System.out.println("You have riched the maximum item limit.");
}
}

void queryItem(int id){
System.out.println(itemDB[id].id + " " + itemDB[id].name + " " +
itemDB[id].price + " " + itemDB[id].quantity);
}

void displayItemList(){
System.out.println("ID " + "Name " + "Price " + "Quantity ");
for (int i = 0; i < id; i++){
System.out.println(itemDB.id + " " + itemDB.name + " " +
itemDB.price + " " + itemDB.quantity);
}
}
}

// Inventory class //

class Inventory {
private int invSize;
Inventory [] backpack;
Item item;

//item related
private int id;
String name;
int itemsInStack;


Inventory(){
invSize = 2;
}

void addItem(int id, String name, int itemsInStack){
// ---- part where i am stuck //
}

void setMaxInventory(int invSize){
this.invSize = invSize;
backpack = new Inventory[invSize];
}

void putInside(int id){
// ---- part where i am stuck //
// backpack[id] = new addItem( );
}

}

[/source]

Can you guys please glance at it and tell me if I am even on the right track? Also, suppose I created a sword class that adds +str +stamina etc properties and I want to put it into an item array. How would I put it into a main item array (is it even possible or I am over thinking it)?

Thanks
Advertisement


Here is my code: http://pastebin.com/wKSu5UD1

It would be more helpful for future readers if you just posted the code instead of a link to the code.

I think, therefore I am. I think? - "George Carlin"
My Website: Indie Game Programming

My Twitter: https://twitter.com/indieprogram

My Book: http://amzn.com/1305076532

I cant seem to figure out how to insert items from "Item array" into "Backpack array" just by using reference ID which is also happens to be array index.

It seems to be a project problem. An "Item" class should be used to implement a general item, not more than one. If you wanted a different class for swords, you could create another class called "Weapon", which inherits "Item", and another one called "Sword". Then, you could create a class to store ANY type of Item, no matter if they are a sword or a jewel or a coin. I'll give you a little example without being too complex about this.

First of all, I've implemented a class called Item:


public class Item extends Object {

	int ID;
	String name;
	int price;
	
	public Item(int itemID, String itemName, int itemPrice) {
		ID = itemID;
		name = itemName;
		price = itemPrice;
	}
	
	public void changeID(int newID) {
		ID = newID;
	}
	
	public void changeName(String newName) {
		name = newName;
	}
	
	public void chagePrice(int newPrice) {
		price = newPrice;
	}
	
	public int getID() {
		return ID;
	}
	
	public String getName() {
		return name;
	}
	
	public int getPrice() {
		return price;
	}
	
}

It has 3 attributes. Their values are defined at the moment you create an Item object. All the 3 attributes have their own access and modifier methods.

Then, you implement a class called "ItemCollection" to store any kind of item, and extend ArrayList. Use the generics for "Item", so that it can be used only for items.


package example;

import java.util.ArrayList;
public class ItemCollection<Item> extends ArrayList<Item> {

	private static final long serialVersionUID = 1L;
	
}

Then, in your main class and method, you create an instance of the ItemCollection, and an instance for every Item, and then add each Item to the ItemCollection:


package example;

public class Main {

	public static ItemCollection<Item> itemCollection;
	
	public static void main(String[] args) {
		
		itemCollection = new ItemCollection<Item>();
		int defaultValue = 50;
		Item boot = new Item(0, "Boot", defaultValue);
		Item sword = new Item(1, "Sword", defaultValue);
		Item ring = new Item(2, "Ring", defaultValue);
		Item dagger = new Item(3, "Dagger", defaultValue);
		Item bow = new Item(4, "Bow", defaultValue);
		
		itemCollection.add(boot); itemCollection.add(sword);
		itemCollection.add(ring); itemCollection.add(dagger);
		itemCollection.add(bow);
	}

}

Then you create another class just like ArrayCollection, for the Backpack, and add to it a method to "addItemByID", passing the ID as an argument.


package example;

import java.util.ArrayList;
public class Backpack<Item> extends ArrayList<Item> {

	private static final long serialVersionUID = 1L;

	public void addItemByID(int itemID) {
		for (example.Item i : Main.itemCollection) {
			if (i!=null) {
				if (i.ID == itemID) {
					add((Item) i);
				}
			}
		}
	}
	
}

And then, in the main method, you just add to the backpack by the ID:


Backpack<Item> backPack = new Backpack<Item>();
		backPack.addItemByID(3); // Add a Dagger.
		System.out.println(backPack.get(0).name); // Print the Dagger Item name.

By the way, try to avoid using "arrays" in Java. They're primitive data types. Try to use ArrayLists instead (They have all these fancy methods that are just beautiful :) ). It's nothing like a list in Python, but much better than an "array".

Creator and only composer at Poisone Wein and Übelkraft dark musical projects:

The design shown in the OP has several problems. I know that you're still learning, so don't see the following as critique but as tips. I also don't know what language constructs are already in your toolbox, so feel free to skip the one or other tip until being prepared to consider it.

First of, class Item is a factory for items, a container for items, and an item itself. That is a bad idea because it burdens the class with 3 different responsibilities. A principle in OOP is the "one responsibility principle" which means that a class should be written so that it does one thing. This is not a hard requirement, but it is usually a good idea to follow it. So it would be a Good Thing (™) to have classes Item, ItemFactory, and ItemContainer. Notice please that Inventory is also a candidate to be an ItemContainer.

Looking at the factory first, it is notable that there is not exactly one factory as would be expected. Even if you had separated the factory functionality into an ItemFactory, you could still instantiate more than one. This is okay in principle, but you want the factory to create unique identifiers. This can be done only if either there is one and only one factory instance, or else all existing factories are synchronized when generating an item identifier. There is a so-called design pattern with the name "Singleton" (you may ask the Internet for it). Singletons are a bit controversial because of their global nature. Nevertheless, an application wide sole factory is IMHO a valid use case. It works so that you cannot instantiate the class ItemFactory directly, but invoke a static function that returns you ever the same object. This object is generated the very first time of invocation, stored internally, and returned as is for every sub-sequent invocation. This is in fact an OOP approach to a class with all static members, what itself is another possibility to make the factory unique.

The class Item itself should hold the attributes that are common to items. Your Item.itemDB array isn't such a thing. Why should, for example, a knife has contained items? The member itemDB and its companion routines are good for the ItemContainer class but not for the Item class. This doesn't mean that a concrete item is not able to hold other items. You can derive the class ItemContainer from the class Item, so it is itself an item and can contain other items. You can search the Internet for a design pattern named "Composite" if you are interested in the nitty-gritty details.

Your Inventory class suffers from some of the above issues as well. More to this later ...


… I cant seem to figure out how to insert items from "Item array" into "Backpack array" just by using reference ID which is also happens to be array index.

The problem with this kind of index addressing is that all containers (counting the array to it) need to have the same number of slots. I'm using this e.g. for resource handling where a resource (of a specific type) is referred to by the resource library as well as the concrete graphic rendering device. It works because on both sides the number of slots needed by the containers is the same. But in your case it isn't. An inventory is usually much smaller (or else you'll wasting memory) than your main table.

Now, in your current implementation the class Inventory has a member that can refer to a single Item instance, but it has an array for references to Inventory instances. This is spurious. I would expect it to have no reference to other inventories but a container (an array in your case) for items! This is because an inventory should be enabled to hold several items! If done so, and the array is chosen big enough to have a slot for each Item.id that can be occur, you can store items within the inventory using Item.id as index as well as done currently in the Item class.


It seems to be a project problem. An "Item" class should be used to implement a general item, not more than one. If you wanted a different class for swords, you could create another class called "Weapon", which inherits "Item", and another one called "Sword". Then, you could create a class to store ANY type of Item, no matter if they are a sword or a jewel or a coin. I'll give you a little example without being too complex about this.

Although this isn't wrong in principle and actually correct to a degree, it should be mentioned that OOP has a second mechanism besides inheritance, and that is composition. I urge the OP to notice this because inheritance, since being kind of innovation in OOP, is somewhat forced by textbooks and internet sources, so it seems to be the magic weapon. This is not true. Relying only on inheritance does not solve problems but leads to unmaintainable code. This becomes clear only after a while, namely if the codebase begins to grow noticeable. Either you end up in spaghetti inheritance or the so-called "God class".

To explain it a bit further, I exaggerate a bit:

Item <= RightHandUseable <= Weapon <= Cutter <= Sword <= MagicSword <= SwordOfKalmahar <= EnhancedSwordOfKalmahar

Or should it better be

Item <= Weapon <= Cutter <= RightHandUseable <= ...

This can be defused a bit when using mix-in inheritance, i.e. inheriting orthogonal functionality, but that is possible only by inheriting interfaces (in Java) so have to implement them each and every time. Now, what is with a Stick? It is inherited from Tool or, specialized, Lever because it is a tool to activate a mechanism when inserted into a slot, or is it a Weapon because it can be used as a Cudgel?

Doing all this is right is probably too much when still learning the language; but don't get trapped by the ideas coming from a single source. Be open.

Although this isn't wrong in principle and actually correct to a degree, it should be mentioned that OOP has a second mechanism besides inheritance, and that is composition. I urge the OP to notice this because inheritance, since being kind of innovation in OOP, is somewhat forced by textbooks and internet sources, so it seems to be the magic weapon. This is not true. Relying only on inheritance does not solve problems but leads to unmaintainable code. This becomes clear only after a while, namely if the codebase begins to grow noticeable. Either you end up in spaghetti inheritance or the so-called "God class".

To explain it a bit further, I exaggerate a bit:

Item <= RightHandUseable <= Weapon <= Cutter <= Sword <= MagicSword <= SwordOfKalmahar <= EnhancedSwordOfKalmahar

Or should it better be

Item <= Weapon <= Cutter <= RightHandUseable <= ...

This can be defused a bit when using mix-in inheritance, i.e. inheriting orthogonal functionality, but that is possible only by inheriting interfaces (in Java) so have to implement them each and every time. Now, what is with a Stick? It is inherited from Tool or, specialized, Lever because it is a tool to activate a mechanism when inserted into a slot, or is it a Weapon because it can be used as a Cudgel?

Doing all this is right is probably too much when still learning the language; but don't get trapped by the ideas coming from a single source. Be open.

First of all, I would like to say that If I was going to develop a "MMORPG" or anything that would require such level of inheritance, I would probably use Python or C++ (And not Java. Java would be the last option.. If I really needed to develop a game like in Android, for example). In Python I would be able to inherit from more than on class, and all this could have a much better project approach. When you mentioned "RightHandUseable", the first thing that came to my mind was interfaces, but, just like you've said, it is too much to consider when learning a language (That's why I did not mention interfaces).

It's necessary to point out that he could do that in C or "procedural Python" and organize his code in a non-OP-way. I started like that at the beginning, because Object Oriented Programming could not enter in my head (It took a lot of time).

Item <= Weapon <= Sword <= SpecificSword1 implements RightHandUseable implements LeftHandUseable <= SpecificSword2 implements RightHandUseable implements LeftHandUseable.

That's probably the approach that I would follow in Java.

Edit: By the way, the biggest problem that I found in his code, was the primitive array. Even if he makes of an "Item" class thousand things and ignores OOP, he could do it to learn more and more.. But.. The array is the problem! haha. He could do anything with an ArrayList, and things like "append to another ArrayList by ID" gets much more easier, and he could do it without being too object-oriented by that.. But, as I've said, he could use C. If he's using Java, it's better to study more and more about object-oriented programming.

Creator and only composer at Poisone Wein and Übelkraft dark musical projects:

I've implemented an example with a more non-object-oriented approach, using a class inside another class (Same file). I've implemented using HashMaps. The only difference is that each category as an ID, not each item (And that's good, considering that your game is much smaller than Tibia, for example).


package example;

import java.util.ArrayList;
import java.util.HashMap;

public class Main {

	// HashMap with arrayLists of items by ID.
	public static HashMap<Integer, ArrayList<String>> items = new HashMap<Integer, ArrayList<String>>();
	// Backpack with a slightly different structure.
	public static HashMap<Integer, String> backpack = new HashMap<Integer, String>();
	
	public static void main(String[] args) {

		// Creating the arrayLists.
		ArrayList<String> boots = new ArrayList<String>();
		ArrayList<String> swords = new ArrayList<String>();
		ArrayList<String> rings = new ArrayList<String>();
		ArrayList<String> daggers = new ArrayList<String>();
		ArrayList<String> bows = new ArrayList<String>();
		
		// Adding content to them...
		for (Integer i = 0; i < 10; i++) {
			boots.add("Boot" + i.toString());
			swords.add("Sword" + i.toString());
			rings.add("Ring" + i.toString());
			daggers.add("Dagger" + i.toString());
			bows.add("Bow" + i.toString());
		}
		
		// Putting the arrayLists to the HashMap of items by their IDs.
		items.put(ID.BOOTS, boots); items.put(ID.SWORDS, swords);
		items.put(ID.RINGS, rings); items.put(ID.DAGGERS, daggers);
		items.put(ID.BOWS, bows);
		
		// Printing all the content in all arrayLists in all IDs.
		for (ArrayList<String> e : items.values()) {
			for (int i = 0; i < e.size(); i++) {
				if (e.get(i)!=null) {
					System.out.println(e.get(i));
				}
			}
		}
		
		// Here you could add any item to the backpack.
		// backpack.put(ID.SWORDS, swords.get(0));
	}

	public class ID {
		
		//Defining constant-IDs.
		public static final int BOOTS = 0;
		public static final int SWORDS = 1;
		public static final int RINGS = 2;
		public static final int DAGGERS = 3;
		public static final int BOWS = 4;
		
	}
	
}

Creator and only composer at Poisone Wein and Übelkraft dark musical projects:


First of all, I would like to say that If I was going to develop a "MMORPG" or anything that would require such level of inheritance, I would probably use Python or C++ (And not Java. Java would be the last option.. If I really needed to develop a game like in Android, for example). In Python I would be able to inherit from more than on class, and all this could have a much better project approach. When you mentioned "RightHandUseable", the first thing that came to my mind was interfaces, but, just like you've said, it is too much to consider when learning a language (That's why I did not mention interfaces).

Sorry, but I need to contradict. That problem is not related to Java. Also C++ allows for multiple inheritance, and most game projects are based on C++. Although not being enough familiar with Python, I argue that it also suffers from this problem, because it is an OOD problem in general.

Look for all the posts here in GDnet, blogs in the internet, and game industry lectures that deal with the component based entity systems. Yes, it is a buzzword these days, but there is a reason for it. In fact, it is an approach where object composition gets a higher attention than usual. This does not mean that inheritance is neglected. It means that one need to know which possibilities exist and then is enabled to apply the best suited method for a given problem.

This topic is closed to new replies.

Advertisement