Finding a suitable data structure in Java

We are working on a game and hope to develop functionality that will allow us to mix different objects in a manner similar to the game "alchemy". The main idea is that we have a number of elements that can be divided into three groups: basic, intermediate and final. Basic resources can be combined together and make an intermediate resource, intermediate resources can be combined with intermediate and basic resources and make final and so on.

So, we are thinking about the presence of two HashMaps: each could indicate with which each resource can be combined, and the second will display what each resource will be made of. Is there a better way to do this? Any data structure that we donโ€™t know about?

thanks

+4
source share
5 answers

Just write your own datastructure as follows

public class Element { enum Type{BASIC, INTERMEDIATE, FINAL}; private Type type; private String name; private List<Element> combinable; } 
+6
source

What you want is an enumeration containing all of your elements using several methods. Here is an example, feel free to use it if it suits your needs.
If you wish, you can also make a second enumeration for Type (as suggested by the Templar) and add it as a field in your element enumeration.

 import java.util.ArrayList; import java.util.Arrays; import java.util.List; public enum Element { //Example instances, replace with what is appropriate for your game. WATER, // Basic WOOD, // Basic IRON, // Basic STONE, // Basic FIRE, // Basic CARBON(WOOD, FIRE), //Intermediate FORGE(STONE, IRON), // Intermediate STEEL(FORGE, IRON); // Final private Element[] parts; private Element() { //instantiates parts to prevent NullPointerException this.parts = new Element[0]; } private Element(Element... parts) { this.parts = parts; } /** * return all the parts of this Element. * @return */ public List<Element> getParts() { return Arrays.asList(parts); } /** * find all elements that have this Element listed as one of their parts. * * @param part * @return */ public List<Element> getComposites() { List<Element> composites = new ArrayList<Element>(); // Iterate through all Elements for (Element composite : Element.values()) { // Iterate through each Element parts for (Element part : composite.parts) { // If the element has a part equal to the argument, // Add the element to the list of composites. if (part == this) { composites.add(composite); } } } return composites; } } 
+1
source

You must use the Composite composite template. In your case, BasicResource is a leaf class. intermediate and final are composites.

0
source

I would actually separate the elements and their combinability - if each element should contain a list of elements with which it is combined, whenever you want to add a new element, you need to go back and add it to all the old elements that you want to combine with.

I would divide the concept into something like "Elements" and "Formulas" -

 class Element { enum Type{NULL, BASIC, INTERMEDIATE, FINAL}; private Type type; private String name; // .... } class Formula { private List<Element> requires = new ArrayList<Element>(); private Element produces; public Formula(List<Element> requires, Element produces) { Collections.copy(requires, this.requires); this.produces = produces; } public final List<Element> requiredElements() { return Collections.unmodifiableList(requires); } public final boolean applyFormula(List<Element> ingredients) { for (Element e : requires) { if (!ingredients.contains(e)) { // ingredients doesn't contain a required element - return early. return false; } } for (Element e : requires) { ingredients.remove(e); } ingredients.add(produces); return true; } } 
0
source

If you create a game, this data, hard-coded in your Java source code, will be painful. You will have to recompile every time you want to add a new element, change the relationship (which consists of what), etc.

Instead, I would recommend storing all the information about your element in an external source, and then reading it to / from it from your program. You can do this using a database, but I feel like I've gone too far (at least for now). Instead, you can use a readable, plain text, standardized format such as JSON to define your elements and their relationships from the outside, and then import all the data using the library (I suggest GSon ) for easy access to your program.

Regarding the data structure, I think your selection of HashMaps will work fine. Since JSON is built on two main types of list data structures [] and displays {} , that is what Gson converts anyway. Here is a very simple example of how I could present your item specification:

 { "elements" : { "iron" : "basic", "carbon" : "basic", "steel" : "intermediate" }, "formulae" : { "steel" : [ "iron", "carbon" ] } } 

You can read this using Gson (or any other JSON library that you have selected) and then compile any other data structures that you need. If you can figure out how to get Gson to create the data structures you want directly (I know this is possible, but I donโ€™t remember how difficult it is), then it will be even better. For example, if you can turn the value of the โ€œformulaโ€ into a BidiMap ( Bidirectional Apache Commons map ), then this can be very useful (but you will also need to translate the list of components into a set so that it is non-specialized, for example, iron + carbon is something same as carbon + iron).

For more dynamic behavior, you can add a function to your program so that you can reload all the data of your elements during the game. (This may make debugging easier.)

I know that this is not quite what you asked, but I hope you find useful tips anyway!

0
source

Source: https://habr.com/ru/post/1488713/


All Articles