如何实现连通房?

pg-*_*ban 2 java data-structures

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

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

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

cle*_*tus 16

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

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

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

Map<String, Direction> exits;
Run Code Online (Sandbox Code Playgroud)

不过我不建议这样做.我建议列举可能的方向:

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); }
}
Run Code Online (Sandbox Code Playgroud)

然后你存储:

private final Map<Direction, Exit> exits =
  new EnumMap<Direction, Exit>(Direction.class);
Run Code Online (Sandbox Code Playgroud)

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

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

Map<String, Room> exits;
Run Code Online (Sandbox Code Playgroud)

密钥是自由形式的方向(北,东,南等).

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

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

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

Verb [[preposition1] object1 [[preposition2] object2]] 
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

所以:

public enum Command { LOOK, HIT, WAVE, OPEN, CLOSE, ... };
Run Code Online (Sandbox Code Playgroud)

(毫无疑问是与这些实例相关的行为)和:

public class GameObject {
  boolean isSupported(Command command);
  boolean trigger(Command command);
}

public class Exit extends GameObject {
  ...
}
Run Code Online (Sandbox Code Playgroud)

GameObjects也可能具有其他状态,例如是否可以看到它们.有趣的是,Direction enum实例也可以说是Commands,它再次改变了抽象.

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