How can I associate an Enum with its opposite value, as in cardinal directions (North - South, East - West, etc)?
I'm still working on my Cell class for my maze game I'm attempting to make. After help in a different thread it was suggested that I use an EnumMap for my Walls/Neighbors and this is working great so far.
Here is what I have thus far:
enum Dir {
NORTH, SOUTH, EAST, WEST
}
class Cell {
public Map<Dir, Cell> neighbors = Collections
.synchronizedMap(new EnumMap<Dir, Cell>(Dir.class));
public Map<Dir, Boolean> walls = Collections
.synchronizedMap(new EnumMap<Dir, Boolean>(Dir.class));
public boolean Visited;
public Cell() {
Visited = false;
for (Dir direction : Dir.values()) {
walls.put(direction, true);
}
}
// Randomly select an unvisited neighbor and tear down the walls
// between this cell and that neighbor.
public Cell removeRandomWall() {
List<Dir> unvisitedDirections = new ArrayList<Dir>();
for (Dir direction : neighbors.keySet()) {
if (!neighbors.get(direction).Visited)
unvisitedDirections.add(direction);
}
Random randGen = new Random();
Dir randDir = unvisitedDirections.get(randGen
.nextInt(unvisitedDirections.size()));
Cell randomNeighbor = neighbors.get(randDir);
// Tear down wall in this cell
walls.put(randDir, false);
// Tear down opposite wall in neighbor cell
randomNeighbor.walls.put(randDir, false); // <--- instead of randDir, it needs to be it's opposite.
return randomNeighbor;
}
}
If you look at that last comment there, I first tear down say the NORTH wall in my current cell. I then take my North neighbor, and now I must tear down my SOU开发者_如何学PythonTH wall, so the walls between the two cells have been removed.
What would be a simple way to extend my enum so I can give it a direction and it return to me it's opposite?
yet another way without switch/case, or having to store state:
public enum Dir {
NORTH { @Override public Dir opposite() { return SOUTH; }},
EAST { @Override public Dir opposite() { return WEST; }},
SOUTH { @Override public Dir opposite() { return NORTH; }},
WEST { @Override public Dir opposite() { return EAST; }},
;
abstract public Dir opposite();
}
Simplest, I think, is just to add a method to it. Note that this only works well if the number of enum constants won't change over time.
enum Dir {
NORTH,
SOUTH,
EAST,
WEST;
public Dir opposite() {
switch(this) {
case NORTH: return Dir.SOUTH;
case SOUTH: return Dir.NORTH;
case EAST: return Dir.WEST;
case WEST: return Dir.EAST;
default: throw new IllegalStateException("This should never happen: " + this + " has no opposite.");
}
}
}
Then, in your code, you could do this:
randomNeighbor.walls.put(randDir.opposite(), false);
You can try this out, the "good" thing about this is that you can actually index the enums like an array, kinda... and since we are dealing with opposites as in there are always pairs, the code supports it as long as you add the new values to the end so you don't mess up the indexing.
enum Directions {
NORTH(1),
SOUTH(0),
WEST(3),
EAST(2);
private final int opposite;
Directions(int opposite) {
this.opposite = opposite;
}
Directions opposite() {
return Directions.values()[this.opposite];
}
}
For example if you wanted to add more directions you would just add this:
NORTH_WEST(7),
NORTH_EAST(6),
SOUTH_WEST(5),
SOUTH_EAST(4)
Easy. :)
public enum Direction
{
NORTH,EAST,SOUTH,WEST;
public Direction opposite()
{
return Direction.values()[ (this.ordinal() + 2) & 3 ];
}
}
精彩评论