From 655ac88f4e73b2df532a451aedf5a561ea1b0d2c Mon Sep 17 00:00:00 2001 From: Pacien TRAN-GIRARD Date: Sat, 21 Nov 2015 10:36:18 +0100 Subject: Import project structure --- src/ch/epfl/maze/util/Action.java | 101 +++++ src/ch/epfl/maze/util/Direction.java | 235 ++++++++++++ src/ch/epfl/maze/util/LabyrinthGenerator.java | 533 ++++++++++++++++++++++++++ src/ch/epfl/maze/util/Statistics.java | 197 ++++++++++ src/ch/epfl/maze/util/Vector2D.java | 228 +++++++++++ 5 files changed, 1294 insertions(+) create mode 100644 src/ch/epfl/maze/util/Action.java create mode 100644 src/ch/epfl/maze/util/Direction.java create mode 100644 src/ch/epfl/maze/util/LabyrinthGenerator.java create mode 100644 src/ch/epfl/maze/util/Statistics.java create mode 100644 src/ch/epfl/maze/util/Vector2D.java (limited to 'src/ch/epfl/maze/util') diff --git a/src/ch/epfl/maze/util/Action.java b/src/ch/epfl/maze/util/Action.java new file mode 100644 index 0000000..491627f --- /dev/null +++ b/src/ch/epfl/maze/util/Action.java @@ -0,0 +1,101 @@ +package ch.epfl.maze.util; + +/** + * Immutable action that encapsulates a choice made by an animal and information + * about it, such as if it was successful or not, and if the animal will die + * while performing it. + * + */ + +public final class Action { + + /* variables defining the action */ + private final Direction mDirection; + private final boolean mSuccess; + private final boolean mDies; + + /** + * Constructs a successful action of an animal towards a specified + * direction, that does not die between two squares. + * + * @param dir + * Direction towards which the action needs to be performed + */ + + public Action(Direction dir) { + if (dir != null) { + mDirection = dir; + } else { + mDirection = Direction.NONE; + } + mSuccess = true; + mDies = false; + } + + /** + * Constructs an action of an animal towards a specified direction, with a + * specified success, that does not die between two squares. + * + * @param dir + * Direction towards which the action needs to be performed + * @param successful + * Determines whether this action was successful + */ + + public Action(Direction dir, boolean successful) { + mDirection = dir; + mSuccess = successful; + mDies = false; + } + + /** + * Constructs an action of an animal towards a specified direction, with a + * specified success, and that also specifies if the animal dies between two + * squares. + * + * @param dir + * Direction towards which the action needs to be performed + * @param successful + * Determines whether this action was successful + * @param dies + * Determines whether the action will die between two squares + */ + + public Action(Direction dir, boolean successful, boolean dies) { + mDirection = dir; + mSuccess = successful; + mDies = dies; + } + + /** + * Retrieves the direction towards which the action shall move. + * + * @return Direction of the action + */ + + public Direction getDirection() { + return mDirection; + } + + /** + * Determines if the action was successful or not. + * + * @return true if the action was successful, false otherwise + */ + + public boolean isSuccessful() { + return mSuccess; + } + + /** + * Determines if the animal performing the action dies while moving from a + * square to another. + * + * @return true if the action dies between two squares, false + * otherwise + */ + + public boolean diesBetweenSquares() { + return mDies; + } +} diff --git a/src/ch/epfl/maze/util/Direction.java b/src/ch/epfl/maze/util/Direction.java new file mode 100644 index 0000000..a75ba7f --- /dev/null +++ b/src/ch/epfl/maze/util/Direction.java @@ -0,0 +1,235 @@ +package ch.epfl.maze.util; + +/** + * 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}. + * + */ + +public enum Direction { + DOWN, UP, RIGHT, LEFT, NONE; + + /** + * 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; + } +} diff --git a/src/ch/epfl/maze/util/LabyrinthGenerator.java b/src/ch/epfl/maze/util/LabyrinthGenerator.java new file mode 100644 index 0000000..f0e5f1b --- /dev/null +++ b/src/ch/epfl/maze/util/LabyrinthGenerator.java @@ -0,0 +1,533 @@ +package ch.epfl.maze.util; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.ArrayList; +import java.util.Scanner; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Generates a set of pre-computed labyrinth structures + * + */ + +public final class LabyrinthGenerator { + + /** + * Returns a precomputed labyrinth of small size. + * + * @return A small labyrinth + */ + + public static int[][] getSmall() { + int[][] labyrinth = { + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1 }, + { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1 }, + { 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1 }, + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, + { 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1 }, + { 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1 }, + { 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1 }, + { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1 }, + { 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1 }, + { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1 }, + { 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + }; + + return labyrinth; + } + + /** + * Returns a precomputed labyrinth of medium size. + * + * @return A medium labyrinth + */ + + public static int[][] getMedium() { + int[][] labyrinth = { + { 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, + { 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, + { 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1 }, + { 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1 }, + { 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1 }, + { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1 }, + { 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1 }, + { 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 }, + { 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 }, + { 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1 }, + { 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1 }, + { 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1 }, + { 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1 }, + { 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1 }, + { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 3 }, + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } + }; + + return labyrinth; + } + + public static int[][] getLarge() { + int[][] labyrinth = { + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1 }, + { 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1 }, + { 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1 }, + { 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1 }, + { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1 }, + { 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1 }, + { 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1 }, + { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1 }, + { 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1 }, + { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1 }, + { 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1 }, + { 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1 }, + { 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1 }, + { 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1 }, + { 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1 }, + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1 }, + { 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1 }, + { 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1 }, + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } + }; + + return labyrinth; + } + + // ============================================================== + + // ============================================================== + + /** + * Returns the labyrinth structure of the Pac-Man level. + * + * @return The Pac-Man level + */ + + public static int[][] getPacMan() { + int[][] labyrinth = { + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, + { 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1 }, + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, + { 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1 }, + { 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1 }, + { 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1 }, + { 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1 }, + { 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1 }, + { 0, 0, 0, 0, 0, 0, 0, 1, -1, -1, -1, 1, 0, 0, 0, 0, 0, 0, 0 }, + { 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1 }, + { 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1 }, + { 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1 }, + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, + { 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1 }, + { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1 }, + { 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1 }, + { 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1 }, + { 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1 }, + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } + }; + + return labyrinth; + } + + // ============================================================== + + /** + * Returns the labyrinth structure of one of the Ms. Pac-Man levels. + * + * @return One of the Ms. Pac-Man levels + */ + + public static int[][] getMsPacMan() { + int[][] labyrinth = { + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1 }, + { 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1 }, + { 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1 }, + { 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1 }, + { 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1 }, + { 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0 }, + { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1 }, + { 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1 }, + { 1, 0, 0, 0, 0, 1, 0, 1, -1, -1, -1, 1, 0, 1, 0, 0, 0, 0, 1 }, + { 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1 }, + { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1 }, + { 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1 }, + { 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1 }, + { 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1 }, + { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1 }, + { 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1 }, + { 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1 }, + { 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1 }, + { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 }, + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } + }; + + return labyrinth; + } + + /** + * Returns a hard-coded labyrinth which is multiply connected. + *

+ * If the Monkey algorithm is run on this labyrinth, it will never find the + * solution. + * + * @return A labyrinth multiply connected + */ + + public static int[][] getMultiplyConnected() { + int[][] labyrinth = { + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, }, + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, }, + { 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, }, + { 1, 0, 0, 3, 1, 0, 1, 0, 0, 0, 1, }, + { 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, }, + { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, }, + { 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, }, + { 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, }, + { 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, }, + { 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, }, + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, } + }; + + return labyrinth; + } + + // ============================================================== + + /** + * Returns a hard-coded maze for debugging the Mouse. + * + * @return A maze for debugging the Mouse + */ + + public static int[][] getDebugMouse() { + int[][] labyrinth = { + { 1, 1, 1, 1, 1, 1, 1 }, + { 2, 0, 0, 0, 0, 0, 1 }, + { 1, 1, 1, 1, 1, 0, 1 }, + { 1, 3, 1, 1, 1, 0, 1 }, + { 1, 0, 1, 1, 1, 0, 1 }, + { 1, 0, 0, 0, 0, 0, 1 }, + { 1, 1, 1, 1, 1, 1, 1 } + }; + + return labyrinth; + } + + /** + * Returns a hard-coded maze for debugging the Hamster. + * + * @return A maze for debugging the Hamster + */ + + public static int[][] getDebugHamster() { + int[][] labyrinth = { + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1 }, + { 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1 }, + { 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3 }, + { 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1 }, + { 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1 }, + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } + }; + + return labyrinth; + } + + /** + * Returns a hard-coded maze for debugging the Monkey. + * + * @return A maze for debugging the Monkey + */ + + public static int[][] getDebugMonkey() { + int[][] labyrinth = { + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1 }, + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 }, + { 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1 }, + { 1, 1, 0, 1, 1, 1, 3, 1, 0, 1, 1 }, + { 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1 }, + { 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1 }, + { 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1 } + }; + + return labyrinth; + } + + /** + * Returns a hard-coded maze for debugging the Bear. + * + * @return A maze for debugging the Bear + */ + + public static int[][] getDebugBear1() { + int[][] labyrinth = { + { 1, 1, 1, 2, 1, 1, 1, }, + { 1, 0, 0, 0, 1, 0, 1, }, + { 1, 0, 0, 0, 0, 0, 1, }, + { 1, 0, 0, 0, 0, 0, 1, }, + { 1, 1, 1, 1, 0, 0, 1, }, + { 3, 0, 0, 0, 0, 0, 1, }, + { 1, 1, 1, 1, 1, 1, 1, } + }; + + return labyrinth; + } + + /** + * Returns a hard-coded maze for debugging the Bear. + * + * @return A maze for debugging the Bear + */ + + public static int[][] getDebugBear2() { + int[][] labyrinth = { + { 1, 2, 1, 1 }, + { 1, 0, 1, 1 }, + { 1, 0, 0, 3 }, + { 1, 0, 1, 1 }, + { 1, 0, 1, 1 }, + { 1, 1, 1, 1 } + }; + + return labyrinth; + } + + /** + * Returns a hard-coded maze for debugging the Panda. + * + * @return A maze for debugging the Panda + */ + + public static int[][] getDebugPanda1() { + int[][] labyrinth = { + { 1, 1, 1, 2, 1, 1, 1 }, + { 1, 1, 1, 0, 1, 1, 1 }, + { 1, 0, 0, 0, 0, 0, 1 }, + { 1, 0, 1, 1, 1, 0, 1 }, + { 1, 0, 0, 0, 0, 0, 1 }, + { 1, 1, 1, 1, 1, 1, 1 } + }; + + return labyrinth; + } + + /** + * Returns a hard-coded maze for debugging the Panda. + * + * @return A maze for debugging the Panda + */ + + public static int[][] getDebugPanda2() { + int[][] labyrinth = { + { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 1, 1, 1, 1, 0, 1, 1, 1, 1 }, + { 1, 1, 1, 1, 0, 1, 1, 1, 1 }, + { 1, 1, 1, 1, 0, 1, 1, 1, 1 }, + { 1, 0, 0, 0, 2, 0, 0, 0, 1 }, + { 1, 1, 1, 1, 0, 1, 1, 1, 1 }, + { 1, 1, 1, 1, 0, 1, 1, 1, 1 }, + { 1, 1, 1, 1, 0, 1, 1, 1, 1 }, + { 1, 1, 1, 1, 1, 1, 1, 1, 1 } + }; + + return labyrinth; + } + + // ============================================================== + + /** + * Returns a hard-coded maze that shows the efficiency of the Bear over + * the Monkey. + * + * @return A maze to run with a Bear and a Monkey + */ + + public static int[][] getBearVsMonkey() { + int[][] labyrinth = { + { 1, 1, 1, 3, 1, 1, 1 }, + { 1, 0, 0, 0, 0, 0, 1 }, + { 1, 0, 1, 1, 1, 0, 1 }, + { 1, 0, 0, 2, 0, 0, 1 }, + { 1, 1, 1, 1, 1, 1, 1 } + }; + + return labyrinth; + } + + /** + * Returns a hard-coded maze that shows the efficiency of the Panda over + * the Hamster. + * + * @return A maze to run with a Panda and a Hamster + */ + + public static int[][] getPandaVsHamster() { + int[][] labyrinth = { + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1 }, + { 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 }, + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, + { 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 }, + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, + { 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 }, + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, + { 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 }, + { 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } + }; + + return labyrinth; + } + + // ============================================================== + + /** + * Returns a hard-coded maze for debugging Blinky. + * + * @return A maze for debugging Blinky + */ + + public static int[][] getDebugBlinky() { + int[][] labyrinth = { + { 1, 1, 1, 1, 1, 1, 1, 1 }, + { 1, 0, 0, 0, 0, 0, 0, 1 }, + { 1, 0, 1, 0, 1, 1, 0, 1 }, + { 1, 0, 0, 0, 0, 0, 0, 1 }, + { 1, 0, 1, 0, 1, 1, 0, 1 }, + { 1, 0, 0, 0, 0, 0, 0, 1 }, + { 1, 1, 1, 1, 1, 1, 1, 1 } + }; + + return labyrinth; + } + + /** + * Returns a hard-coded maze for debugging Pinky. + * + * @return A maze for debugging Pinky + */ + + public static int[][] getDebugPinky() { + int[][] labyrinth = { + { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 1, 0, 0, 0, 0, 0, 0, 0, 1 }, + { 1, 0, 1, 0, 1, 1, 1, 0, 1 }, + { 1, 0, 0, 0, 0, 0, 0, 0, 1 }, + { 1, 1, 1, 1, 1, 1, 1, 1, 1 } + }; + + return labyrinth; + } + + /** + * Returns a hard-coded maze for debugging Inky. + * + * @return A maze for debugging Inky + */ + + public static int[][] getDebugInky() { + int[][] labyrinth = { + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, + { 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 }, + { 1, 0, 0, 3, 0, 0, 0, 0, 0, 0, 1 }, + { 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1 }, + { 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1 }, + { 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1 }, + { 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1 }, + { 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1 }, + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } + }; + + return labyrinth; + } + + /** + * Returns a hard-coded maze for debugging Clyde. + * + * @return A maze for debugging Clyde + */ + + public static int[][] getDebugClyde() { + int[][] labyrinth = { + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, }, + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, }, + { 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, }, + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, }, + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, } + }; + + return labyrinth; + } + + // ============================================================== + + /** + * Reads and returns a labyrinth from specified file. + *

+ * The file must be present in the root folder of the project. + * + * @param filename + * The file location + * @return Labyrinth structure parsed from a file + */ + + public static int[][] readFromFile(String filename) { + File file = new File(filename); + int[][] labyrinth = null; + Scanner scanner = null; + + try { + scanner = new Scanner(file); + + // reads one line after the other + ArrayList> lines = new ArrayList>(); + while (scanner.hasNext()) { + String line = scanner.nextLine(); + + // looks for a single number in the line using a Regular Expression + Matcher match = Pattern.compile("-?[0-9]").matcher(line); + ArrayList list = new ArrayList(); + while (match.find()) { + list.add(match.group()); + } + + // gets rid of empty lines + if (!list.isEmpty()) { + lines.add(list); + } + } + + // parses the Strings found into a labyrinth + labyrinth = new int[lines.size()][]; + for (int i = 0; i < labyrinth.length; i++) { + ArrayList line = lines.get(i); + labyrinth[i] = new int[line.size()]; + for (int j = 0; j < line.size(); j++) { + labyrinth[i][j] = Integer.parseInt(line.get(j)); + } + } + + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (NumberFormatException e) { + e.printStackTrace(); + } finally { + if (scanner != null) { + scanner.close(); + } + } + + return labyrinth; + } +} diff --git a/src/ch/epfl/maze/util/Statistics.java b/src/ch/epfl/maze/util/Statistics.java new file mode 100644 index 0000000..0a4e7c6 --- /dev/null +++ b/src/ch/epfl/maze/util/Statistics.java @@ -0,0 +1,197 @@ +package ch.epfl.maze.util; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import ch.epfl.maze.physical.Animal; +import ch.epfl.maze.simulation.Simulation; + +/** + * Utility class that allows to compute statistics on a list of results. + * + */ + +public final class Statistics { + + /* constants for the length of the distribution axis */ + public static final int X_LENGTH = 40; + public static final int Y_LENGTH = 13; + + /** + * Returns the sum of all the numbers in results. + * + * @param results + * List of numbers + * @return The total of the list + */ + + public static int total(List results) { + int total = 0; + for (Integer result : results) { + if (result == Integer.MAX_VALUE) { + return Integer.MAX_VALUE; + } + total += result; + } + return total; + } + + /** + * Returns the mean of the numbers in results. + *

+ * mean(X) = total(X) / N + * + * @param results + * List of numbers + * @return The mean of the results + */ + + public static int mean(List results) { + int total = total(results); + if (total == Integer.MAX_VALUE) { + return Integer.MAX_VALUE; + } + return total / results.size(); + } + + /** + * Returns the variance of the numbers in results. + *

+ * var(X) = (X - mean(X)) / N + * + * @param results + * List of numbers + * @return The variance of the results + */ + + public static double var(List results) { + double mean = mean(results); + if (mean == Integer.MAX_VALUE) { + return Integer.MAX_VALUE; + } + double var = 0; + for (Integer result : results) { + var += (result - mean) * (result - mean); + } + return var / results.size(); + } + + /** + * Returns the standard deviation of the numbers in results. + *

+ * std(X) = sqrt(var(X)) + * + * @param results + * List of numbers + * @return The variance of the results + */ + + public static double std(List results) { + return Math.sqrt(var(results)); + } + + /** + * Computes distribution for each animal in simulation + * + * @param simulation + * Simulation to make statistics on + * @param numberOfSimulations + * The number of simulations + */ + + public static Map> computeStatistics( + Simulation simulation, int numberOfSimulations) { + // maps animals' names with their overall results (which are linked-list) + Map> results = new TreeMap>(); + + for (Animal a : simulation.getWorld().getAnimals()) { + results.put(a.getClass().getSimpleName(), new LinkedList()); + } + + // simulates world a lot of times + for (int i = 0; i < numberOfSimulations; i++) { + + // simulates world until the end + simulation.restart(); + while (!simulation.isOver()) { + simulation.move(null); + } + + // retrieves arrival times and appends them to the results + Map> arrivalTimes = simulation.getArrivalTimes(); + for (Map.Entry> entry : arrivalTimes.entrySet()) { + for (Animal a : entry.getValue()) { + String animalName = a.getClass().getSimpleName(); + List list = results.get(animalName); + list.add(entry.getKey()); + } + } + } + + return results; + } + + /** + * Prints the distribution of all the results. + * + * @param results + * List of numbers + */ + + public static void printDistribution(List results) { + + int min = results.get(0); + int max = results.get(results.size() - 1); + int length = (max - min) / X_LENGTH; + + // counts number of steps inside a range + int lowerBound = Integer.MIN_VALUE; + int upperBound = min + length; + int index = 0; + List boxPlot = new ArrayList<>(); + for (int i = 0; i < X_LENGTH; i++) { + int counter = 0; + + while (index < results.size() + && (results.get(index) > lowerBound && results.get(index) <= upperBound)) { + counter++; + index++; + } + boxPlot.add(counter); + lowerBound = upperBound; + upperBound += length; + } + + // draws plot on string + String[] printPlot = new String[Y_LENGTH]; + for (int i = 0; i < Y_LENGTH; i++) { + printPlot[i] = "| "; + } + + int maxCount = Collections.max(boxPlot); + for (Integer count : boxPlot) { + for (int i = 0; i < Y_LENGTH; i++) { + if (count > (i * maxCount) / Y_LENGTH) { + printPlot[i] += "#"; + } else { + printPlot[i] += " "; + } + } + } + + // prints plot + System.out.println("\n^"); + for (int i = Y_LENGTH - 1; i > 0; i--) { + System.out.println(printPlot[i]); + } + System.out.print("--"); + for (int i = 0; i < X_LENGTH; i++) { + System.out.print("-"); + } + System.out.println(">"); + } +} diff --git a/src/ch/epfl/maze/util/Vector2D.java b/src/ch/epfl/maze/util/Vector2D.java new file mode 100644 index 0000000..5e4b975 --- /dev/null +++ b/src/ch/epfl/maze/util/Vector2D.java @@ -0,0 +1,228 @@ +package ch.epfl.maze.util; + +/** + * Immutable 2-dimensional vector (x, y). + * + */ + +public final class Vector2D { + + /* shift constant to compute the hash */ + private static final int SHIFT = 1000; + + /* 2-dimension coordinates */ + private final int mX, mY; + + /** + * Constructs a 2-dimensional vector. + * + * @param x + * Horizontal coordinate + * @param y + * Vertical coordinate + */ + + public Vector2D(int x, int y) { + mX = x; + mY = y; + } + + /** + * Adds two coordinates to the vector. + * + * @param x + * Horizontal coordinate to add + * @param y + * Vertical coordinate to add + * @return The result of an addition with two coordinates + */ + + public Vector2D add(int x, int y) { + return new Vector2D(mX + x, mY + y); + } + + /** + * Adds a vector to the vector. + * + * @param v + * Vector to add + * @return The result of the addition with the vector + */ + + public Vector2D add(Vector2D v) { + return add(v.mX, v.mY); + } + + /** + * Subtracts two coordinates to the vector. + * + * @param x + * Horizontal coordinate to subtract + * @param y + * Vertical coordinate to subtract + * @return The result of the subtraction with the vector + */ + + public Vector2D sub(int x, int y) { + return new Vector2D(mX - x, mY - y); + } + + /** + * Subtracts a vector to the vector. + * + * @param v + * Vector to subtract + * @return The result of the subtraction with the vector + */ + + public Vector2D sub(Vector2D v) { + return sub(v.mX, v.mY); + } + + /** + * Negates the vector. + * + * @return The negated version of the vector + */ + + public Vector2D negate() { + return new Vector2D(-mX, -mY); + } + + /** + * Multiplies the coordinates of the vector by a scalar. + * + * @param scalar + * Number to multiply the coordinates with + * @return The result of the multiplication with a scalar + */ + + public Vector2D mul(int scalar) { + return new Vector2D(scalar * mX, scalar * mY); + } + + /** + * Divides the coordinates of the vector by a scalar. + * + * @param scalar + * Number to divide the coordinates with + * @return The result of the division with a scalar + */ + + public Vector2D div(int scalar) { + return new Vector2D(scalar / mX, scalar / mY); + } + + /** + * Normalizes the vector. + * + * @return The normalized version of the vector + */ + + public Vector2D normalize() { + double dist = dist(); + return new Vector2D((int) (mX / dist), (int) (mY / dist)); + } + + /** + * The Euclidean distance of the vector. + * + * @return The length of the vector + */ + + public double dist() { + return Math.sqrt(mX * mX + mY * mY); + } + + /** + * Adds a direction to the vector + * + * @param d + * Direction to add + * @return The result of the addition with the direction + */ + + public Vector2D addDirectionTo(Direction d) { + switch (d) { + case UP: + return new Vector2D(mX, mY - 1); + + case DOWN: + return new Vector2D(mX, mY + 1); + + case LEFT: + return new Vector2D(mX - 1, mY); + + case RIGHT: + return new Vector2D(mX + 1, mY); + + case NONE: + default: + return new Vector2D(mX, mY); + } + } + + /** + * Converts the vector to the closest corresponding direction. + * + * @return The closest direction corresponding to the vector + */ + + public Direction toDirection() { + Vector2D normal = this.normalize(); + + if (normal.mX == 0 && normal.mY == 1) { + return Direction.DOWN; + } else if (normal.mX == 0 && normal.mY == -1) { + return Direction.UP; + } else if (normal.mX == 1 && normal.mY == 0) { + return Direction.RIGHT; + } else if (normal.mX == -1 && normal.mY == 0) { + return Direction.LEFT; + } else { + return Direction.NONE; + } + } + + /** + * Returns the horizontal coordinate of the vector. + * + * @return x-coordinate of the vector + */ + + public int getX() { + return mX; + } + + /** + * Returns the vertical coordinate of the vector. + * + * @return y-coordinate of the vector + */ + + public int getY() { + return mY; + } + + @Override + public String toString() { + return "(" + mX + ", " + mY + ")"; + } + + @Override + public int hashCode() { + return mX * SHIFT + mY; + } + + @Override + public boolean equals(Object o) { + if (o == null) { + return false; + } + if (o.getClass() != this.getClass()) { + return false; + } + + return o.hashCode() == this.hashCode(); + } +} -- cgit v1.2.3