The easiest way to achieve a responsive orientation enum? java
我将以"最清晰"的方式快速展示我想要实现的目标:
1 2 3 4 5 | public enum Orientation { NORTH, WEST, SOUTH, EAST } public enum Turn { LEFT, RIGHT } |
因此,我希望这两个枚举可以安全有效地根据移动查找更改的方向:
1 2 3 4 | Orientation orient = Orientation.NORTH; // orient points to NORTH now orient = orient.turn(Turn.LEFT); // orient points to WEST now |
我尝试实现这一目标的第一个方法是创建一个地图:
1 | EnumMap<Orientation, EnumMap<Turn, Orientation>> |
静态地绘制所有方向图,但这是一大块地图。而且可能有点过量,尽管会产生这种预期效果:
1 2 | directionMap.get(NORTH).get(LEFT) // the value would then be WEST |
下一步我要做的是通过一个指南针类把所有的方向连接成一个圆。就像一个LinkedCircuitList…<->North<->East<->South<->West<->North<->所以指南针可以有一个静态函数,调用链接列表中的任何成员,然后向左或向右移动,从而正确地改变方向。但代码并没有按我想要的方式运行。
所以我最后的问题是,有没有人对这种代码有经验,或者有一个想法,如何以一种良好的枚举方式来实现期望的结果?
我看不出地图解决方案有什么问题。如果你想要更贴心的东西:
1 2 3 4 5 6 7 8 9 | public enum Orientation { NORTH, EAST, SOUTH, WEST; private static Orientation[] vals = values(); Orientation turnTo(Turn t) { return vals[(4 + this.ordinal() + (t == Turn.RIGHT ? 1 : -1)) % 4]; } } |
然而,这是不太干净和可维护的(如果有人更改枚举的顺序,它将被破坏)。
稍微干净一点(但考虑不多):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | public enum Orientation { NORTH(0), EAST(1), SOUTH(2), WEST(3); private final int p; Orientation(int p) { this.p = p; } private static Orientation[] vals = new Orientation[4]; static { for( Orientation o : Orientation.values() ) vals[o.p] = o; } Orientation turnTo(Turn t) { return vals[(4 + this.p + (t == Turn.RIGHT ? 1 : -1)) % 4]; } } |
另一种让Java接受这一点的方法是使用方法而不是字段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | enum Orientation { NORTH { Orientation left(){return WEST;} Orientation right(){return EAST;} }, EAST { Orientation left(){return NORTH;} Orientation right(){return SOUTH;} }, SOUTH { Orientation left(){return EAST;} Orientation right(){return WEST;} }, WEST { Orientation left(){return SOUTH;} Orientation right(){return NORTH;} }; abstract Orientation left(); abstract Orientation right(); public Orientation turn(Turn where){ return where == Turn.LEFT ? this.left() : this.right(); } } |
如果你愿意的话,你可以自己保存
不使用序数,且易于理解:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public enum Orientation { NORTH, WEST, EAST, SOUTH; static { NORTH.left = WEST; NORTH.right = EAST; WEST.left = SOUTH; WEST.right = NORTH; EAST.left = NORTH; EAST.right = SOUTH; SOUTH.left = EAST; SOUTH.right = WEST; } private Orientation left; private Orientation right; public Orientation turnTo(Turn t) { return t == Turn.LEFT ? left : right; } } |
我认为你对循环列表的想法非常好:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | public enum Turn { LEFT(-1), RIGHT(1); private final int offset; private Turn(int offset) { this.offset = offset; } public int offset() { return this.offset; } } public enum Orientation { NORTH, EAST, SOUTH, WEST; private static final List<Orientation> orientations = Arrays.asList(NORTH, EAST, SOUTH, WEST); // to not depend on ordinal public Orientation turn(Turn to) { int size = orientations.size(); int myIndex = orientations.indexOf(this); int remainder = (myIndex + to.offset()) % size; int index = remainder < 0 ? size + remainder : remainder; return orientations.get(index); } } |
这似乎是可扩展的,即,硬向左将有一个