实现响应式方向枚举的最简单方法? java
The easiest way to achieve a responsive orientation enum? java
我会以"clearest"的方式快速展示我想达到的效果:
public enum Orientation {
NORTH, WEST, SOUTH, EAST }
public enum Turn {
LEFT, RIGHT }
所以我希望这两个枚举能够安全有效地根据移动查找更改后的方向:
Orientation orient = Orientation.NORTH;
// orient points to NORTH now
orient = orient.turn(Turn.LEFT);
// orient points to WEST now
我尝试实现此目的的第一种方法是创建地图:
EnumMap<Orientation, EnumMap<Turn, Orientation>>
并静态映射所有方向,但这是 map.get.put.get 的一大块......并且可能有点过量,虽然导致了这种预期的效果:
directionMap.get(NORTH).get(LEFT)
// the value would then be WEST
我的下一个方法是通过指南针 class 将所有方向连接成一个圆圈。像 LinkedCircuitList 一样工作 ...<->NORTH<->EAST<->SOUTH<-> WEST<->NORTH<->... 所以 Compass 可以有一个静态函数调用该链表的任何成员并向左或向右移动,从而导致方向的正确改变。但是代码并没有真正按照我想要的方式运行。
最后我的问题是,有没有人有使用过这种代码的经验,或者知道如何以一种很好的枚举方式实现预期的结果?
我认为 Map 解决方案没有任何问题。如果你想要更简洁的东西:
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];
}
}
然而,这不太干净和可维护(如果有人更改枚举的顺序,它会中断)。
更简洁一点(但不那么简洁):
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];
}
}
我觉得你循环列表的想法很好:
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);
}
}
这似乎是可扩展的,即 HARD_LEFT 将有一个 -2
偏移并且方向的循环列表应该从左到右排序。
不使用序数,简单易懂:
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; }
}
另一种欺骗 java 接受它的方法是使用方法而不是字段:
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();
}
}
如果您愿意,您可以节省 turn()
并只写 Orientation.North.left()
之类的东西。给你非常简洁的语法。
我会以"clearest"的方式快速展示我想达到的效果:
public enum Orientation {
NORTH, WEST, SOUTH, EAST }
public enum Turn {
LEFT, RIGHT }
所以我希望这两个枚举能够安全有效地根据移动查找更改后的方向:
Orientation orient = Orientation.NORTH;
// orient points to NORTH now
orient = orient.turn(Turn.LEFT);
// orient points to WEST now
我尝试实现此目的的第一种方法是创建地图:
EnumMap<Orientation, EnumMap<Turn, Orientation>>
并静态映射所有方向,但这是 map.get.put.get 的一大块......并且可能有点过量,虽然导致了这种预期的效果:
directionMap.get(NORTH).get(LEFT)
// the value would then be WEST
我的下一个方法是通过指南针 class 将所有方向连接成一个圆圈。像 LinkedCircuitList 一样工作 ...<->NORTH<->EAST<->SOUTH<-> WEST<->NORTH<->... 所以 Compass 可以有一个静态函数调用该链表的任何成员并向左或向右移动,从而导致方向的正确改变。但是代码并没有真正按照我想要的方式运行。
最后我的问题是,有没有人有使用过这种代码的经验,或者知道如何以一种很好的枚举方式实现预期的结果?
我认为 Map 解决方案没有任何问题。如果你想要更简洁的东西:
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];
}
}
然而,这不太干净和可维护(如果有人更改枚举的顺序,它会中断)。
更简洁一点(但不那么简洁):
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];
}
}
我觉得你循环列表的想法很好:
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);
}
}
这似乎是可扩展的,即 HARD_LEFT 将有一个 -2
偏移并且方向的循环列表应该从左到右排序。
不使用序数,简单易懂:
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; }
}
另一种欺骗 java 接受它的方法是使用方法而不是字段:
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();
}
}
如果您愿意,您可以节省 turn()
并只写 Orientation.North.left()
之类的东西。给你非常简洁的语法。