如何实现连通房?

这可能是一个重复的问题,因为我不知道用短语搜索查询。 我正在用Java创建一个类似Zork的文本游戏,角色会移动到彼此连接的不同房间。 我希望能够列出玩家可用于此房间的所有选项。

例如,房间A连接到B的东边,B连接到A的西边,C的南面,D的北面,依此类推。

我应该使用什么数据结构,或者我应该如何尽可能有效地实现它?

首先要决定的是什么构成一个有效的方向:它来自固定列表还是自由forms的文本? 最简单的解决方案是拥有四个基本方向。 有人建议将其作为int数组。 这可能是C / C ++ / C#中的有效解决方案(所有这些中的枚举只是int常量),但没有理由在Java中这样做。

在Java中,您可以使用(类型安全)枚举 – 顺便说一下,它可以具有状态和行为 – 并使用EnumMap ,这是非常高效的。 在内部,它只是一个由枚举序数值索引的数组。 您可能会争辩说它与int数组有什么区别? 答案是EnumMap中的int数组是类型安全随机访问集合的内部实现细节。

如果允许自由格式文本作为退出方向,则结构将如下所示:

 Map exits; 

但是,我不建议这样做。 我建议列举可能的方向:

 public enum Direction { NORTH("north", "n"), NORTHWEST("northwest", "nw"), ... IN("in"), OUT("out"); private final static Map INSTANCES; static { Map map = new HashMap(); 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 exits; Direction(String... exits) { this.exits = Collections.unmodifiableList(Arrays.asList(exits)); } public List getExits() { return exits; } public String getName() { return exits.get(0); } public static Map getInstances() { return INSTANCES; } public static Direction getDirection(String exit) { return INSTANCES.get(exit); } } 

然后你存储:

 private final Map exits = new EnumMap(Direction.class); 

这为您提供了类型安全性,性能和可扩展性。

考虑这个的第一种方式是作为地图:

 Map exits; 

其中关键是自由forms的方向(北,东,南等)。

下一个问题:什么是出口? 在最简单的情况下,退出就是您最终的房间,但随后您开始询问各种问题,例如:

  • 玩家可以看到出口吗?
  • 出口是关闭还是打开?
  • 出口可以关闭,打开,锁定,解锁,推开等吗?
  • 可以使用退出程序(例如你必须携带某个护身符)?
  • 您最终可能是程序化的(例如,您可能陷入陷阱并最终完成其他地方)?
  • 可以使用退出触发一些其他操作(例如,设置警报)?

有必要考虑文本冒险游戏的界面。 玩家以下列forms输入命令:

 Verb [[preposition1] object1 [[preposition2] object2]] 

至少这是一种可能性。 例子包括:

  • 坐(动词=坐);
  • 打开门(动词=打开,对象1 =门)
  • 看书;
  • 用铁键锁住胸部(动词=锁,对象1 =胸部,介词2 =用,对象2 =铁键);
  • 在兽人处投掷火球;
  • 等等

所以上面介绍了一套相当全面的行为。 所有这一切的重点是:

  • 退出将支持许多动词或命令(例如,您可以打开/关闭门但不能通道);
  • 怪物和物品也将支持命令(魔杖可以“挥手”,兽人可以“击中”);
  • 退出,怪物和物品就是所有类型的物体(游戏中的物品可以通过某种方式与之互动)。

所以:

 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枚举实例也可以说是Commands,它再次改变了抽象。

所以希望这有助于指出你正确的方向。 抽象没有“正确”的答案,因为它完全取决于您需要建模和支持的内容。 这应该有希望给你一个起点。

一系列的房间,每个房间的出口列表,参考它通向的房间。

您可以将Room对象存储在List或Set中,或者(如Lars D建议的那样)存储数组。

在Room中,我认为存储出口的一种很好的方式(考虑到它们可能不仅仅是4个基本方向)将在地图中,方向为Enum,相邻房间为值。

这在存储空间非常有效,并且应该足够快速地浏览。

听起来像你需要一个称为多图的数据结构。

这是一个类似哈希的集合,但键可以有多个值。 在Java中没有这样的东西,但它可以通过使用具有两个级别的普通集合轻松构建:在地图中存储列表。 钥匙是门的唯一标记,列表包含门连接的所有房间。 通常这只是两个房间,但也许门有一定的魔力。

大致相同的是拥有自己的类门 ,其中包含您想要的任何内容以及对两个连通房的引用。 这只需要一个普通的地图。

在任何一种情况下,Room类都只有门键,可以在集合中查找。

您当然可以将房间的拓扑结构直接放入房间物体中,其门结构可直接引用其他房间,但我怀疑门将具有自己的状态(打开,关闭,锁定……),无论如何你有一个关于如何创建所有这些链接的鸡与蛋的问题。 使用库集合可以解决所有这些问题。

您可以使用数组实现此目的:

 class Room { private Room[] exits = new Room[4]; } 

在这个例子中, exits[0]可以包含对北方房间的引用,向东exits[1] ,依此类推。 如果元素包含null则表示该方向没有退出。

请注意,您可以使用此方法创建非线性数据结构,例如A – > B – > C – > A.

当我看到这个问题时,首先想到的是制作一个Graph数据结构,但是阅读这些其他注释,Map可能要好得多。 图表太复杂了。

使用正确的图形库比这里的大多数Map方法更强大,更灵活。 Jung库( http://jung.sourceforge.net/ )在Java中提供了许多基于图形的function。 虽然它可能看起来有点复杂,但从长远来看,它可能值得花时间投资。