package ch.epfl.maze.util; import java.util.Collections; import java.util.EnumSet; import java.util.Set; /** * Directions that an animal can take to move. They represent the four cardinal * points ({@code DOWN, UP, RIGHT, LEFT}) from the frame of reference of the * labyrinth, plus a default one : {@code NONE}. * * @author EPFL * @author Pacien TRAN-GIRARD */ public enum Direction { DOWN, UP, RIGHT, LEFT, NONE; /** * A set of all the possible directions that can be taken. */ public static final Set MOVING_DIRECTIONS = Collections.unmodifiableSet(EnumSet.of( Direction.DOWN, Direction.UP, Direction.RIGHT, Direction.LEFT )); /** * Returns the integer value of the direction * * @return Integer value of the direction */ public int intValue() { switch (this) { case DOWN: return 0; case UP: return 1; case RIGHT: return 2; case LEFT: return 3; case NONE: default: return 4; } } /** * Converts the direction into an orthonormal vector, when possible. * * @return Orthonormal {@code Vector2D} that represents the direction. */ public Vector2D toVector() { switch (this) { case DOWN: return new Vector2D(0, 1); case UP: return new Vector2D(0, -1); case RIGHT: return new Vector2D(1, 0); case LEFT: return new Vector2D(-1, 0); case NONE: default: return new Vector2D(0, 0); } } /** * Reverses the direction. * * @return The opposite direction. */ public Direction reverse() { switch (this) { case DOWN: return UP; case UP: return DOWN; case RIGHT: return LEFT; case LEFT: return RIGHT; case NONE: default: return NONE; } } /** * Determines whether the argument is the opposite of another. * * @param d The direction to compare with * @return true if the direction is the opposite the argument, * false otherwise */ public boolean isOpposite(Direction d) { return this == d.reverse(); } /** * Converts the argument relative to the frame of reference given by the * direction that calls the method. * * @param dir The direction to convert * @return The direction converted to the frame of reference given by the * direction called. */ public Direction relativeDirection(Direction dir) { switch (this) { case DOWN: return dir.reverse(); case UP: return dir; case RIGHT: return dir.rotateLeft(); case LEFT: return dir.rotateRight(); case NONE: default: return NONE; } } /** * Converts the argument back to the frame of reference of the labyrinth * * @param dir The direction to convert back * @return The direction converted back to the frame of reference of the * labyrinth */ public Direction unRelativeDirection(Direction dir) { switch (this) { case DOWN: return dir.reverse(); case UP: return dir; case RIGHT: return dir.rotateRight(); case LEFT: return dir.rotateLeft(); case NONE: default: return NONE; } } /** * Rotates the direction to the right. * * @return The rotated direction to the right */ public Direction rotateRight() { switch (this) { case DOWN: return LEFT; case UP: return RIGHT; case RIGHT: return DOWN; case LEFT: return UP; case NONE: default: return NONE; } } /** * Rotates the direction to the left. * * @return The rotated direction to the left */ public Direction rotateLeft() { switch (this) { case DOWN: return RIGHT; case UP: return LEFT; case RIGHT: return UP; case LEFT: return DOWN; case NONE: default: return NONE; } } /** * Applies the change of coordinates relative to the frame of reference * of the direction that calls the method to all the directions in the * argument. * * @param dir The array of directions to convert * @return The directions converted to the frame of reference given by the * direction which calls the method */ public Direction[] relativeDirections(Direction[] dir) { Direction[] relativeDirections = new Direction[dir.length]; for (int i = 0; i < dir.length; i++) { relativeDirections[i] = this.relativeDirection(dir[i]); } return relativeDirections; } }