我们正在开发一款游戏,并希望开发一种功能,让我们能够以类似“炼金术”游戏的方式混合各种物品。主要思想是我们有许多元素,可以分为三组:基本,中间和最终。基本资源可以合并在一起,形成一个中间资源,中间资源可以与中间资源和基础资源合并,制作最终资源等。
因此,我们正在考虑使用2个HashMaps:一个将指示每个资源可以与哪个组合,第二个将映射每个资源的组成。有一个更好的方法吗?我们不知道的任何数据结构?
由于
答案 0 :(得分:6)
只需像这样编写自己的数据结构
public class Element {
enum Type{BASIC, INTERMEDIATE, FINAL};
private Type type;
private String name;
private List<Element> combinable;
}
答案 1 :(得分:1)
你想要的是一个包含所有元素的枚举,有几种方法。这是一个例子,如果满足您的需求,请随时使用它 如果需要,您还可以为Type创建第二个枚举(如Templar建议的那样)并将其作为Element枚举中的字段添加。
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's 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;
}
}
答案 2 :(得分:0)
您应该使用复合设计模式。 在你的情况下,BasicResource是一个叶类。 中间和最后是复合材料。
答案 3 :(得分:0)
我实际上将元素及其可组合性分开 - 如果每个元素必须包含它可以组合的元素列表,每当你想要添加一个新元素时,你必须返回并将它添加到你想要它的所有旧元素结合。
我将这个概念分为“元素”和“公式” -
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;
}
}
答案 4 :(得分:0)
如果您正在创建游戏,那么在Java源代码中对此数据进行硬编码将会让您感到痛苦。每次要添加新元素,更改关系(由什么组成)等时,您都必须重新编译。
相反,我建议将所有元素信息存储在外部源中,然后从程序中读取/访问它。你可以用数据库做到这一点,但我觉得有点矫枉过正(至少目前为止)。相反,您可以使用一个很好的可读,纯文本,标准化的格式,如JSON来定义您的元素及其关系外部,然后使用库导入所有数据(我是建议GSon)以便在您的计划中轻松访问。
至于数据结构,我认为您选择的HashMaps可以正常工作。由于JSON构建在两种基本类型的数据结构上 - 列表 []
和映射 {}
- 这就是Gson将事物转换为反正的东西。这是一个非常简单的示例,说明我如何设想元素规范:
{
"elements" : {
"iron" : "basic",
"carbon" : "basic",
"steel" : "intermediate"
},
"formulae" : {
"steel" : [ "iron", "carbon" ]
}
}
您可以使用Gson(或您选择的任何JSON库)读取它,然后从中构建您需要的任何其他数据结构。如果你能弄清楚如何让Gson直接创建你想要的数据结构(我知道这是可能的,但我不记得做配置有多难),那就更好了。例如,如果您可以将“公式”值转换为BidiMap(Apache Commons双向图),那么这可能非常有用(但您还需要将组件列表转换为保持与订单无关的一套,例如铁+碳与碳+铁相同。
对于更加动态的行为,您可以在程序中添加一项功能,以便在游戏仍在运行时重新加载所有元素数据! (这可能会使调试变得更容易。)
我知道这不是你要求的,但我希望你能找到有用的建议!