这可能是一个重复的问题,因为我不知道用短语搜索查询。我正在Java中创建一个类似Zork的文本游戏,角色移动到彼此连接的不同房间。我希望能够列出玩家可用于此房间的所有选项。
例如,A室连接到B的东边,B连接到A的西边,C的南面,D的北面,依此类推。
我应该使用哪种数据结构,或者我应该如何尽可能有效地实现它?
答案 0 :(得分:16)
要决定的第一件事是什么构成一个有效的方向:是来自固定列表还是自由形式的文本?最简单的解决方案是拥有四个基本方向。有人建议将其作为int数组。这可能是C / C ++ / C#中的有效解决方案(所有这些中的枚举只是int常量),但没有理由用Java来实现。
在Java中,您可以使用(类型安全)枚举 - 顺便提一下,它可以具有状态和行为 - 并使用EnumMap
,这是高度高效。在内部,它只是一个由枚举序数值索引的数组。您可能会争辩说它与int数组有什么区别?答案是EnumMap
中的int数组是类型安全随机访问集合的内部实现细节。
如果允许自由格式文本作为退出方向,则结构将如下所示:
Map<String, Direction> exits;
但我不建议这样做。我建议列举可能的方向:
public enum Direction {
NORTH("north", "n"),
NORTHWEST("northwest", "nw"),
...
IN("in"),
OUT("out");
private final static Map<String, Direction> INSTANCES;
static {
Map<String, Direction> map = new HashMap<String, Direction>();
for (Direction direction : values()) {
for (String exit : direction.exits) {
if (map.containsKey(exit)) {
throw new IllegalStateException("Exit '" + exit + "' duplicated");
}
map.put(exit, direction);
}
}
INSTANCES = Collections.unmodifiableMap(map);
}
private final List<String> exits;
Direction(String... exits) {
this.exits = Collections.unmodifiableList(Arrays.asList(exits));
}
public List<String> getExits() { return exits; }
public String getName() { return exits.get(0); }
public static Map<String, Direction> getInstances() { return INSTANCES; }
public static Direction getDirection(String exit) { return INSTANCES.get(exit); }
}
然后存储:
private final Map<Direction, Exit> exits =
new EnumMap<Direction, Exit>(Direction.class);
这为您提供了类型安全性,性能和可扩展性。
第一种思考方式是地图:
Map<String, Room> exits;
其中键是自由形式的方向(北,东,南等)。
下一个问题:什么是退出?在最简单的情况下,退出就是您最终的房间,但随后您开始询问各种问题,如:
有必要考虑文本冒险游戏的界面。玩家以下列形式输入命令:
Verb [[preposition1] object1 [[preposition2] object2]]
这至少是一种可能性。例子包括:
所以上面介绍了一套相当全面的行为。所有这一切的重点是:
这样:
public enum Command { LOOK, HIT, WAVE, OPEN, CLOSE, ... };
(毫无疑问是与这些实例相关的行为)和:
public class GameObject {
boolean isSupported(Command command);
boolean trigger(Command command);
}
public class Exit extends GameObject {
...
}
GameObjects也可能有其他状态,例如是否可以看到它们。有趣的是,Direction enum实例也可以说是Commands,它再次改变了抽象。
所以希望这有助于指出你正确的方向。抽象没有“正确”的答案,因为它完全取决于您需要建模和支持的内容。这应该有希望给你一个起点。
答案 1 :(得分:1)
一系列房间,每个房间都有一个出口列表,参考它所通过的房间。
答案 2 :(得分:1)
您可以将Room对象存储在List或Set中,或者(如Lars D建议的那样)存储数组。
在Room中,我认为存储出口的好方法(考虑到它们可能不仅仅是4个基本方向)将在地图中,方向为Enum,相邻房间为值。
这在存储空间非常有效,并且应该足够快速地浏览。
答案 3 :(得分:1)
听起来我需要一种称为 multimap 的数据结构。
这是一个类似哈希的集合,但键可以有多个值。在Java中没有这样的东西,但它可以通过使用具有两个级别的普通集合轻松构建:在地图中存储列表。钥匙是门的唯一标记,列表包含门连接的所有房间。通常这只是两个房间,但也许门有一定的魔力。
大致相同的是拥有自己的类门,其中包含您想要的任何内容以及对两个连通房的引用。这只需要一张普通的地图。
在任何一种情况下,Room类都有门钥匙,可以在集合中查找。
你当然可以将房间的拓扑结构直接放入房间的物体中,门的结构直接引用其他房间,但我怀疑门会有自己的状态(打开,关闭,锁定......)和在任何情况下,你都有一个关于如何创建所有这些链接的鸡与蛋的问题。使用库集合可以解决所有这些问题。
答案 4 :(得分:0)
您可以使用数组实现此目的:
class Room {
private Room[] exits = new Room[4];
}
在此示例中,exits[0]
可以包含对北方房间的引用,exits[1]
到东方的房间,依此类推。如果一个元素包含null
,则表示该方向没有退出。
请注意,您可以使用此方法创建非线性数据结构,例如A - &gt; B - &gt; C - &gt;甲
答案 5 :(得分:0)
当我看到这个问题时想到的第一件事就是创建一个Graph数据结构,但是阅读这些其他注释,Map可能要好得多。图表太复杂了。
答案 6 :(得分:0)
使用正确的图形库比这里的大多数Map方法更强大,更灵活。 Jung库(http://jung.sourceforge.net/)在Java中提供了许多基于图形的功能。虽然它可能看起来有点复杂,但从长远来看,它可能值得投入时间。