|
- package net.hoo2.auth.dsproject.snake;
-
- import java.util.Arrays;
- import java.lang.Math;
-
- /**
- * @class Player
- * @brief Represent a Player in the Game
- *
- * The players are playing in a round-robin sequence and we keep track
- * for each one of them their playing order, score and place on the board.
- *
- * @author Christos Choutouridis AEM:8997
- * @email cchoutou@ece.auth.gr
- */
- public class Player {
- /** Helper variables to keep track of the move() return values @see move() */
- static final int MOVE_DATA_SIZE = 9; /**< The move return data array size */
- static final int MOVE_TILE_IDX = 0; /**< The index of tile */
- static final int MOVE_INITTILE_IDX = 1; /**< The index of init tile */
- static final int MOVE_STEPS_IDX = 2; /**< The index of steps */
- static final int MOVE_ROLL_IDX = 3; /**< The index of roll */
- static final int MOVE_POINTS_IDX = 4; /**< The index of points */
- static final int MOVE_SNAKES_IDX = 5; /**< The index for number of snakes (Always <= 1) */
- static final int MOVE_LADDERS_IDX = 6; /**< The index for number of ladders (Always <= 1) */
- static final int MOVE_RED_APPLES_IDX = 7; /**< The index for number of red apples (Always <= 1) */
- static final int MOVE_BLACK_APPLES_IDX = 8; /**< The index for number of black apples (Always <= 1) */
-
- /** @name Constructors */
- /** @{ */
- /** Default doing nothing constructor */
- Player () {
- playerId = score = tile = 0;
- name = "";
- lastMove = new int[MOVE_DATA_SIZE];
- dryMove = new int[MOVE_DATA_SIZE];
- }
- /**
- * @brief The main constructor
- *
- * This creates a player for the game
- * @param playerId The player's to create
- * @param name The name of the player
- * @param board Reference to the board the player will play on.
- */
- Player (int playerId, String name) {
- this.playerId = playerId;
- this.name = name;
- score = 0;
- tile = 0;
- lastMove = new int[MOVE_DATA_SIZE];
- dryMove = new int[MOVE_DATA_SIZE];
- }
- /** @} */
-
- /** @name Get/Set interface */
- /** @{ */
- int getPlayerId () { return playerId; }
- void setPlayerId (int playerId) {
- this.playerId = playerId;
- }
- String getName () { return name; }
- void setName (String name) {
- this.name = name;
- }
- int getScore () { return score; }
- void setScore (int score) {
- this.score = score;
- }
-
- /** Get tile */
- int getTile () { return tile; }
- /** Set tile */
- void setTile (int tile) {
- this.tile = tile;
- }
-
- /** Get lastMove */
- int[] getLastMove () { return lastMove; }
- /** Set lastMove */
- void setLastMove (int[] lastMove) {
- this.lastMove = lastMove;
- }
- /** Get dryMove */
- int[] getDryMove () { return dryMove; }
- /** Set dryMove */
- void setDryMove (int[] dryMove) {
- this.dryMove = dryMove;
- }
- /** @} */
-
- /** @name Exposed API members */
- /** @{ */
-
- /**
- * Dice functionality for the players
- * @return An integer in the range [1 .. 6]
- */
- int dice () {
- return (int)(1 + Math.random()*5);
- }
-
- /**
- * Get the next tile after the user's move
- * @param board The board in which we play on
- * @param tile The initial tile
- * @return The the move as an array
- * [0]: Tile after move
- * [1]: The roll of the dice
- * @note
- * We add this move() wrapper in order to provide polymorphism to
- * Player class hierarchy and to be sure that we are not braking the
- * Liskov substitution principle
- * @see https://en.wikipedia.org/wiki/Liskov_substitution_principle
- */
- int[] getNextMove (Board board, int tile) {
- int [] ret = new int[4]; // allocate move memory
- move (board, tile, dice(), true); // make the move
- ret[0] = dryMove[MOVE_TILE_IDX];
- ret[1] = dryMove[MOVE_INITTILE_IDX];
- ret[2] = dryMove[MOVE_POINTS_IDX];
- ret[3] = dryMove[MOVE_ROLL_IDX];
- return ret;
- }
-
- /**
- * @brief Move functionality
- *
- * @param tile The initial tile of the player
- * @param roll The dice roll to play
- * @param run Flag to indicate if we fake the move(dry run) or we do make the move.
- * @return
- * int[MOVE_TILE_IDX (0)] tile after move
- * int[MOVE_INITTILE_IDX (1)] tile before move
- * int[MOVE_STEPS_IDX (2)] number of total steps for the move
- * int[MOVE_ROLL_IDX (3)] the roll of the dice
- * int[MOVE_POINTS_IDX (4)] the points of the move
- * int[MOVE_SNAKES_IDX (5)] number of snake bites
- * int[MOVE_LADDERS_IDX (6)] number of ladders used
- * int[MOVE_RED_APPLES_IDX (7)] number of red apples eaten
- * int[MOVE_BLACK_APPLES_IDX (8)] number of black apples eaten
- * @note
- * Probably a mutable class like: <pre>
- * class MoveData {
- * int tile;
- * int initTile;
- * ...
- * }
- * </pre>
- * for returning value would be better, less error prone, cleaner, etc...
- * We could also had members like: <pre> MoveData previous; </pre> to help us further.
- * We kept this representation just because it was a requirement.
- */
- int [] move (Board board, int tile, int roll, boolean run) {
- int t;
-
- Arrays.fill(dryMove, 0);
- dryMove[MOVE_INITTILE_IDX] = tile;
- dryMove[MOVE_ROLL_IDX] = roll;
-
- tile += roll; // Initial move
- boolean keepGoing;
- do {
- keepGoing = false;
- // Check apples
- //if ((t = board.checkApple(tile, run)) != 0) {
- if ((t = board.checkApple(tile, true)) != 0) {
- dryMove[MOVE_POINTS_IDX] += t;
- if (t > 0)
- ++dryMove[MOVE_RED_APPLES_IDX];
- else
- ++dryMove[MOVE_BLACK_APPLES_IDX];
- }
- // Check ladder
- //if ((t = board.checkLadder(tile, run)) != tile) {
- if ((t = board.checkLadder(tile, true)) != tile) {
- tile = t;
- ++dryMove[MOVE_LADDERS_IDX];
- keepGoing = true;
- }
- // Check snakes
- if ((t = board.checkSnake(tile)) != tile) {
- tile = t;
- ++dryMove[MOVE_SNAKES_IDX];
- keepGoing = true;
- }
- } while (keepGoing);
-
- dryMove[MOVE_TILE_IDX] = tile;
- dryMove[MOVE_STEPS_IDX]= tile - dryMove[MOVE_INITTILE_IDX];
- // Check if we do run the move
- if (run) {
- lastMove = dryMove.clone();
- this.tile = lastMove[MOVE_TILE_IDX];
- score += lastMove[MOVE_POINTS_IDX];
- }
- return dryMove;
- }
-
- /**
- * The base statistics version
- * @param verbose Flag to select the verbosity
- * @param sum Flag to select if we need to print a summarize (not used here)
- * @note
- * We added this function because:
- * 1) we need to keep the "Is a" relationship (Liskov substitution principle)
- * 2) It help us get rid of the move() console output code
- * 3) makes the code smaller
- */
- void statistics (boolean verbose, boolean sum) {
- int begin = lastMove[MOVE_INITTILE_IDX];
- int roll = lastMove[MOVE_ROLL_IDX];
- int last = lastMove[MOVE_TILE_IDX];
- if (verbose)
- System.out.println(name + " +" + roll + "->tile: " + (begin + roll));
- if (lastMove[MOVE_RED_APPLES_IDX] > 0)
- System.out.println(name + " Apple " + lastMove[MOVE_POINTS_IDX] + " points");
- if (lastMove[MOVE_BLACK_APPLES_IDX] > 0)
- System.out.println(name + " Apple " + lastMove[MOVE_POINTS_IDX] + " points");
- if (lastMove[MOVE_LADDERS_IDX] > 0)
- System.out.println(name + " Ladder @" + (begin + roll) + " new position " + last);
- if (lastMove[MOVE_SNAKES_IDX] > 0)
- System.out.println(name + " Ouch!! Snake @" + (begin + roll) + " new position " + last);
- // No use of sum here
- }
- /**@} */
-
- /** @name Data members package access only */
- /** @{ */
- int playerId; /**< Player's ID */
- String name; /**< Player's name */
- int score; /**< Player's score */
- int tile; /**< Player's tile location */
- int[] lastMove; /**< move() return data for statistics. These are only valid after a true move */
- private int [] dryMove; /**< Fake (dry run) move return buffer */
- /** @} */
- }
-
|