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