我在Groovy中制作一个Text Adventure游戏作为一种练习,我遇到了一个奇怪的错误。
现在,我有一个enum
表示玩家可以前往的方向,目前包含北,南,东,西,上和下。
我有一个Room
课程,其中包含Map
其他连通房及其路线。当我在某个Room
添加Room
到另一个Direction
时,我希望能够将当前Room
添加到另一个Room
对面方向。
例如:如果我从房间1到房间2向北添加连接,我希望能够在同一时间从房间2到房间1添加连接。
目前,我正在尝试使用enum
名为Direction
的附加实例变量opposite
(类型为Direction
)来实现此目的。这是不允许的?我没有收到编译器错误或其他任何错误,但我似乎无法让它工作。
这里是完整的enum
声明:
public enum Direction {
North(South), South(North), East(West), West(East), Up(Down), Down(Up)
private Direction opposite
Direction(Direction d){
opposite = d
}
public opposite(){
return opposite
}
}
这是我从以下方式调用它的方法:
public void addConnection(Direction d, Spot spot){
connections[d] = spot
spot.connections[d.opposite()] = this
}
其中connections
是public Map<Direction, Spot>
。
在这种情况下,条目会添加到connections
,如下所示:
null:Spot@some_hexadecimal_representation
任何帮助都会很棒。谢谢!
答案 0 :(得分:8)
Groovy似乎绕过Java a compilation error中的内容:
Main.java:2: illegal forward reference
North(South), South(North), East(West), West(East), Up(Down), Down(Up);
^
Main.java:2: illegal forward reference
North(South), South(North), East(West), West(East), Up(Down), Down(Up);
^
Main.java:2: illegal forward reference
North(South), South(North), East(West), West(East), Up(Down), Down(Up);
^
3 errors
groovy编译器没有抱怨,但是将需要前向声明的枚举值初始化为null
:
public enum Direction {
North(South), South(North), East(West), West(East), Up(Down), Down(Up)
Direction(Direction d){
println "opposite of $this is $d"
}
}
Direction.South // Force enum instantiation in GroovyConsole.
opposite of North is null
opposite of South is North
opposite of East is null
opposite of West is East
opposite of Up is null
opposite of Down is Up
一个似乎在Java中运行良好的解决方案是adding a static
block on the Direction
class来初始化opposite
值。转换为Groovy,即:
enum Direction {
North, South, East, West, Up, Down
private Direction opposite
Direction getOpposite() { opposite }
static {
def opposites = { d1, d2 -> d1.opposite = d2; d2.opposite = d1 }
opposites(North, South)
opposites(East, West)
opposites(Up, Down)
}
}
Direction.values().each {
println "opposite of $it is $it.opposite"
}
opposite of North is South
opposite of South is North
opposite of East is West
opposite of West is East
opposite of Up is Down
opposite of Down is Up
Another,也许更直接,解决方案可以使用枚举上的方向索引来找到对立面:
public enum Direction {
North(1), South(0), East(3), West(2), Up(5), Down(4)
private oppositeIndex
Direction getOpposite() {
values()[oppositeIndex]
}
Direction(oppositeIndex) {
this.oppositeIndex = oppositeIndex
}
}
但是我发现第一个更清晰,因为它不需要索引的那些神奇数字呵呵。
现在,我可能会在这里进入高尔夫球场,但是您可以使用枚举值“ordinal()
(他们的索引)来获得相反的方向without the need of an extra field:
enum Direction {
North, South, East, West, Up, Down
Direction getOpposite() {
values()[ordinal() + ordinal() % 2 * -2 + 1]
}
}
它并不像它看起来那么可怕!偶数方向(北,东,上)返回ordinal() + 1
处的方向作为相反方向,而奇数方向(其他方向)返回ordinal() - 1
处的方向。当然,它在很大程度上依赖于枚举中元素的顺序,但是,你不喜欢简洁吗? = d
答案 1 :(得分:2)
您可以通过将其传递给闭包并在需要相反时调用闭包来推迟对相反的评估:
public enum Direction {
North({South}), South({North}), East({West}), West({East}), Up({Down}), Down({Up})
private def opp
Direction(opp) {
this.opp = opp
}
public opposite() {
return opp()
}
}
public static void main(String[] args) {
Direction.each { d ->
println "${d} ... ${d.opposite()}"
}
}
输出:
North ... South South ... North East ... West West ... East Up ... Down Down ... Up
答案 2 :(得分:1)
当调用枚举构造函数时,看起来Directions
的一半未初始化。也就是说,当您致电North(South)
时,南方尚未初始化。这是下一个。
你遇到了鸡/蛋悖论,其中所有的枚举常量必须在一个之前初始化。您似乎需要重新组织一些代码来解决这个问题。我可能会建议:
public enum Direction {
North(1), South(~1), East(2), West(~2), Up(4), Down(~4);
private int value;
Direction(int d){
value = d;
}
private int getValue() {
return value;
}
public Direction opposite(){
for (Direction d : Direction.values()) {
if (value == ~(d.getValue()))
return d;
}
return null;
}
}
这利用按位运算符~
来区分对立面。