From 626ef9b8801b40e5f18c731dfa46828c4e9726b4 Mon Sep 17 00:00:00 2001 From: Christos Houtouridis Date: Wed, 31 Oct 2018 12:24:40 +0200 Subject: [PATCH] Init commit --- .gitignore | 5 + src/SnakePkg/Apple.java | 88 ++++++++ src/SnakePkg/Board.java | 451 +++++++++++++++++++++++++++++++++++++++ src/SnakePkg/Game.java | 17 ++ src/SnakePkg/Ladder.java | 52 +++++ src/SnakePkg/Snake.java | 46 ++++ 6 files changed, 659 insertions(+) create mode 100644 .gitignore create mode 100755 src/SnakePkg/Apple.java create mode 100755 src/SnakePkg/Board.java create mode 100644 src/SnakePkg/Game.java create mode 100755 src/SnakePkg/Ladder.java create mode 100755 src/SnakePkg/Snake.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3a6e09f --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*bin/* +*.project +*.classpath +*.pdf + diff --git a/src/SnakePkg/Apple.java b/src/SnakePkg/Apple.java new file mode 100755 index 0000000..d433086 --- /dev/null +++ b/src/SnakePkg/Apple.java @@ -0,0 +1,88 @@ +package SnakePkg; + +import java.lang.Math; + +/** + * A class to represent an Apple in the Board + * @author Christos Choutouridis 8997 + */ +public class Apple { + /** @name Constructors */ + /** @{ */ + /** Default ctor */ + Apple () { + appleId = appleTileId= 0; + color = ""; + points = 0; + } + /** Main ctor */ + Apple (int appleId, int appleTileId, String color, int points) { + this.appleId = appleId; + this.appleTileId = appleTileId; + this.color = color; + this.points = points; + } + /** Copy constructor + * @note We don't use clone as long as we don't inherit Cloneable iface + */ + Apple (Apple a) { + appleId = a.getAppleId (); + appleTileId = a.getAppleTileId (); + color = a.getColor (); + points = a.getPoints (); + } + /** @} */ + + /** @name Get/Set interface */ + /** @{ */ + int getAppleId () { return appleId; } + void setAppleId (int appleId) { this.appleId = appleId; } + int getAppleTileId () { return appleTileId; } + void setAppleTileId (int appleTileId) { this.appleTileId = appleTileId; } + + String getColor () { return color; } + /** + * We set color and we update points sign. + * @param color The desired color + * @arg "red" Set color red and mark "points" positive + * @arg "black" Set color black and mark "points" negative + * @arg Otherwise zero + */ + void setColor (String color) { + this.color = color; + if (color == "red") points = Math.abs(points); + else if (color == "black") points = -Math.abs(points); + else points = 0; + } + int getPoints () { return points; } + /** We set the points and update its sign based on color */ + void setPoints (int points) { + if (color == "red") this.points = Math.abs(points); + else this.points = -Math.abs(points); + } + /** @} */ + + /** @name Data members (private) */ + /** @{ */ + private int appleId; //!< Apples's ID + private int appleTileId; //!< Apple's tile location + private String color; //!< Apple's color + /**^ + * @note + * This way of representing color is not preferable by the author. + * An enum Color { red, black } would be better and far less error prone + * In order to support this style we have to strict the color names to + * lower case letters. We also update the points sign to make thinks easier. + * @see setColor + */ + private int points; //!< The points added (algebraically) to the user + /** @} */ +} + + +//class BadColor extends Exception { +// // default constructor +// BadColor() { } +// // parametrized constructor +// BadColor (String str) { super(str); } +//} diff --git a/src/SnakePkg/Board.java b/src/SnakePkg/Board.java new file mode 100755 index 0000000..1758f7e --- /dev/null +++ b/src/SnakePkg/Board.java @@ -0,0 +1,451 @@ +package SnakePkg; + +import java.util.Random; + +/** + * The game's board representation + * @author Christos Choutouridis 8997 + */ +public class Board { + /** @name Constructors */ + /** @{ */ + /** Default ctor */ + Board () { + N = M =0; + tiles = null; + snakes = null; + ladders = null; + apples = null; + } + + /** + * Main constructor + * We make some simple input checking before memory allocation. + * @note + * May throw BadBoardInput + */ + Board (int N, int M, int numOfSnakes, int numOfLadders, int numOfApples) + throws BadBoardInput { + // Input checking + if (numOfApples + numOfLadders*2 + numOfSnakes*2 >= N*M/2) + throw new BadBoardInput("Too many Apples, Snakes and ladders"); + // Init the board object + setN (N); // Input checked version (may throw) + setM (M); // Input checked version (may throw) + tiles = new int[N][M]; + snakes = new Snake[numOfSnakes]; + ladders = new Ladder[numOfLadders]; + apples = new Apple[numOfApples]; + } + + /** + * Copy constructor. We make a deep copy of B and we trust B's + * data to be valid + * @note We don't use clone as long as we don't inherit Cloneable iface + */ + Board (Board B) { + this.N = B.getN(); + this.M = B.getM(); + tiles = new int[N][M]; + snakes = new Snake[B.getSnakes().length]; + ladders = new Ladder[B.getLadders().length]; + apples = new Apple[B.getApples().length]; + // Copy B's guts + for (int i =0 ; i=0 ; --j) + tiles[i][j] = tile++; + } + } + } + + /** + * @brief + * Place the snakes on the board + * The only constrain at this point is that snake tails must be + * below heads and in different tiles + */ + private void _place_snakes () { + int [] head = new int [snakes.length]; // temporary place holder for heads + int [] tail = new int [snakes.length]; // temporary place holder for tails + for (int i =0, tile =0 ; i= 0); + head[i] = tile; + tail[i] = (int)(Math.random() * (head[i] - head[i]%M)); // Don't use heads row and up for tail + snakes[i] = new Snake(i, head[i], tail[i]); // Allocate snake + } + } + + /** + * @brief + * Place apples on the board + * At this point we have snakes. The constrains here are + * that apples have to lie on different tiles and not in some + * snake's head + */ + private void _place_apples () { + int [] apple_tiles = new int [apples.length]; // temporary placeholder for heads + int [] snake_tiles = new int [snakes.length]; // array with snake head tiles + for (int i =0 ; i= 0) || + (_search (snake_tiles, tile) >= 0)); + apple_tiles[i] = tile; + int points = (int)(Math.random() *10) * 5; // get points + boolean red = (boolean)(Math.random() >=0.5); // get color + // Allocate apple + if (red) + apples[i] = new Apple(i, tile, "red", points); + else + apples[i] = new Apple(i, tile, "black", -points); + } + } + + /** + * @brief + * Place ladders on board + * At this point we have snakes and apples. + * @note + * We add a constrain for ladder so its up-setp has to be different from a + * snake's head tile. This ensures the each ladder and snake are independent + */ + private void _place_ladders () { + int [] upstep = new int [ladders.length]; // temporary place holder for up-steps + int [] downstep = new int [ladders.length]; // temporary place holder for down-step + int [] snake_tiles = new int [snakes.length]; // array with snake head tiles + for (int i =0 ; i= 0) || + (_search (snake_tiles, tile) >= 0)); + upstep[i] = tile; + downstep[i] = (int)(Math.random() * (upstep[i] - upstep[i]%M)); + //^ Don't use up-step row and up for down-step + ladders[i] = new Ladder (i, upstep[i], downstep[i]); // Allocate ladder + } + } + + /** + * Make element array of snakes + * @param elemSnakes + */ + private void _makeElementSnakes (String[][] elemSnakes) { + int [] head_tiles = new int [snakes.length]; // array with snake head tiles + int [] tail_tiles = new int [snakes.length]; // array with snake head tiles + int sn =-1; + // Load snake head tiles + for (int i =0 ; i= 0) + elemSnakes[i][j] = "SH" + sn; + else if ((sn = _search (tail_tiles, tiles[i][j])) >= 0) + elemSnakes[i][j] = "ST" + sn; + else + elemSnakes[i][j] = "___"; + } + } + } + + /** + * Make element array of ladders + * @param elemLadders + */ + private void _makeElementLadders (String[][] elemLadders) { + int [] up_tiles = new int [ladders.length]; // array with ladder up-step tiles + int [] down_tiles = new int [ladders.length]; // array with ladder down-step tiles + int sn =-1; + // Load ladder tiles + for (int i =0 ; i= 0) + elemLadders[i][j] = "LU" + sn; + else if ((sn = _search (down_tiles, tiles[i][j])) >= 0) + elemLadders[i][j] = "LD" + sn; + else + elemLadders[i][j] = "___"; + } + } + } + + /** + * Make element array of apples + * @param elemApples + */ + private void _makeElementApples (String[][] elemApples) { + int [] red_tiles = new int [apples.length]; // array with red apple tiles + int [] black_tiles = new int [apples.length]; // array with black apple tiles + int sn =-1; + // Load apple tiles + for (int i =0 ; i= 0) + elemApples[i][j] = "AR" + sn; + else if ((sn = _search (black_tiles, tiles[i][j])) >= 0) + elemApples[i][j] = "AB" + sn; + else + elemApples[i][j] = "___"; + } + } + } + + /** + * Print element array + * @param elem The element array to print + * @param caption The caption + * @note + * As long as we use tiles[0][0] for first tile, this method + * has to print in reverse Y-axis order. For ex: + * 16 15 14 13 + * 09 10 11 12 + * 08 07 06 05 + * 01 02 03 04 + */ + private void _printElement (String[][] elem, String caption) { + System.out.print(caption); + for (int i=N-1 ; i>=0 ; --i) { + System.out.println(""); + System.out.print(" "); + for (int j =0 ; j=0 Element found + */ + private int _search (int[] array, int elem) { + for (int i=0 ; i