4

我们正在开发一款游戏,并希望开发一种功能,使我们能够以类似于“炼金术”游戏的方式混合各种物品。主要思想是我们有许多元素,可以分为三组:基本、中间和最终。基础资源可以合并在一起做成中间资源,中间资源可以和中间基础资源合并做成final等。

因此,我们正在考虑拥有 2 个 HashMap:一个将指示每个资源可与什么组合,第二个将映射每个资源将由什么组成。有一个更好的方法吗?任何我们不知道的数据结构?

谢谢

4

5 回答 5

6

只需像这样编写自己的数据结构

public class Element {
 enum Type{BASIC, INTERMEDIATE, FINAL};
 private Type type;
 private String name;
 private List<Element> combinable;
}
于 2013-06-28T15:31:00.477 回答
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;
    }

}
于 2013-06-28T16:15:10.020 回答
0

您应该使用复合设计模式。在您的情况下, BasicResource 是一个叶类。中间和最终是复合材料。

于 2013-06-28T15:33:25.007 回答
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;
    }
}
于 2013-06-28T16:37:48.367 回答
0

如果您正在创建游戏,将这些数据硬编码到 Java 源代码中会让事情变得很痛苦。每次要添加新元素、更改关系(由什么组成)等时,都必须重新编译。

相反,我建议您将所有元素信息存储在外部源中,然后从您的程序中读取/访问它。您可以使用数据库来执行此操作,但我觉得这有点矫枉过正(至少现在是这样)。相反,您可以使用像JSON这样易于阅读的纯文本标准化格式来定义您的元素及其外部关系,然后使用库(我建议GSon)导入所有数据,以便在您的程序中轻松访问。

至于数据结构,我认为您选择的 HashMaps 可以正常工作。由于 JSON 是建立在两种基本类型的数据结构之上的——<em>列表[]地图 {}——这就是 Gson 无论如何都会转换的东西。这是一个非常简单的示例,说明了我如何设想您的元素规范:

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

您可以使用 Gson(或您选择的任何 JSON 库)读取它,然后从中构建您需要的任何其他数据结构。如果你能弄清楚如何让 Gson 直接创建你想要的数据结构(我知道这是可能的,但我不记得做配置有多难),那就更好了。例如,如果您可以将“公式”值转换为BidiMapApache Commons双向映射),那么这可能非常有用(但您还需要将组件列表转换为一个集合以使其保持有序-不可知论,例如铁+碳与碳+铁相同)。

对于更动态的行为,您可以在程序中添加一个功能,允许您在游戏仍在运行时重新加载所有元素数据!(这可能会使调试更容易。)

我知道这不是你要问的,但我希望我的建议对你有帮助!

于 2013-06-28T17:26:14.160 回答