diff --git a/src/net/hoo2/auth/dsproject/snake/Board.java b/src/net/hoo2/auth/dsproject/snake/Board.java index 6f1edc0..b4c3318 100644 --- a/src/net/hoo2/auth/dsproject/snake/Board.java +++ b/src/net/hoo2/auth/dsproject/snake/Board.java @@ -223,11 +223,11 @@ public class Board { * @param tile The tile to check * @return The result tile */ - int checkLadder (int tile) { + int checkLadder (int tile, boolean climb) { for (int i =0 ; i players; /**< A reference to players */ + private ArrayList players; /**< A reference to players */ + private Map playingOrder; /** @} */ /** @name private api */ /** @{ */ - /** - * Dice functionality - * @return An integer in the range [1 .. 6] - */ - private int _dice () { - return (int)(1 + Math.random()*5); - } + /** * Search the players already in the players vector and compare their turn to play * with the result of a dice. If there is another one with the same dice result return true. @@ -59,12 +52,33 @@ public class Game { * @param players Reference to already register players * @return True if there is another player with the same dice result */ - private boolean _search (int die, ArrayList players) { - for (int i =0; i pairs) { + for (int i =0; i pairs) { + Integer[] temp; + for (int i=pairs.size()-1 ; i>0 ; --i) { + for (int j =0 ; j pairs.get(i)[1]) { + temp = pairs.get(i); + pairs.set(i, pairs.get(j)); + pairs.set(j, temp); + } + } + } + } + + private Player _getPlayer(int playerId) { + for (Player p : players) { + if (p.getPlayerId() == playerId) + return p; + } + return null; + } /** @} */ @@ -75,6 +89,8 @@ public class Game { round = 0; board = new Board(); players = new ArrayList<>(); + playingOrder + = new HashMap(); } /** @@ -92,6 +108,8 @@ public class Game { // delegate constructors board = new Board (N, M, numOfSnakes, numOfLadders, numOfApples); players = new ArrayList<>(); + playingOrder + = new HashMap(); } /** @} */ @@ -118,6 +136,11 @@ public class Game { void setPlayers(ArrayList players) { this.players = players; } + + Map getPlayingOrder () { return playingOrder; } + void setPlayingOrder (Map playingOrder) { + this.playingOrder = playingOrder; + } /** @} */ /** @name Public functionality */ @@ -134,26 +157,49 @@ public class Game { players.add(new Player(playerId, name, board)); return true; } + + /** + * Register a player to the game + * @param playerId The player ID to use + * @param name The player name to use + * @return The status of the operation + */ + boolean registerHeuristicPlayer (int playerId, String name) { + if (players.size() >= MAX_PLAYERS) + return false; + players.add(new HeuristicPlayer(playerId, name, board)); + return true; + } + /** * @brief Set the playing order of players * This function emulates the classic roll of dice to decide which player * plays first which second and so on. */ - void playOrder () { - int d; - for (int i =0 ; i setTurns (ArrayList players) { + int[] pairData = new int[2]; + Integer[] PairData; + ArrayList + pairList = new ArrayList<>(); + + for (int d, i =0 ; i - Integer.compare (p1.getTurn(), p2.getTurn()) - ); + // Sort playeingOrger + _sort (pairList); + // Make and return the Map + for (int i =0 ; i= board.getN()*board.getM()) + for (Integer pid : playingOrder.keySet()) { + Player p = _getPlayer(pid); + tile = p.getNextMove (p.getTile()); + p.statistics(verbose, false); + if (tile>= board.getN()*board.getM()) // The first one here is the winner - return players.get(i); + return p; } return null; // No one finished yet } @@ -203,6 +251,7 @@ public class Game { int numOfLadders = 3; int numOfApples = 6; int numOfPlayers = 2; + boolean verbose = false; // Print caption System.out.println("================== Snake Game =================="); @@ -214,14 +263,18 @@ public class Game { Game game = new Game (lines, columns, numOfSnakes, numOfLadders, numOfApples); // game.getBoard().createElementBoard(); // Not explicitly required - // Player registration - for (int i=0 ; i path; + + public HeuristicPlayer() { + super (); + path = new ArrayList(); + } + HeuristicPlayer (int playerId, String name, Board board) { + super (playerId, name, board); + path = new ArrayList(); + } + + + @Override + int dice () { + return 1; + } + + @Override + int getNextMove (int tile) { + Map moves = new HashMap(); + double max = Double.NEGATIVE_INFINITY; + double ev = Double.NEGATIVE_INFINITY; + int roll = 0; + + for (int r=1 ; r<=6 ; ++r) { + moves.put (new Integer(r), evaluate (tile, r)); + if ((ev = moves.get(r)) > max) { + max = ev; + roll = r; + } + } + Integer[] move_data = Arrays.stream(move (tile, roll, true)) + .boxed() + .toArray(Integer[]::new); + path.add(move_data); + return tile + roll; + } + + @Override + void statistics (boolean verbose, boolean sum) { + if (sum) { + int nSnakes =0; + int nLadders =0; + int nRedApples =0; + int nBlackApples =0; + + for (int i=0 ; itile: " + tile); //XXX: Debug only + + 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 - t = board.checkApple(tile); - if (t != 0) { - score += t; - ++ret[3]; - System.out.println(name + " Apple @" + tile + " " + t + " points"); + if ((t = board.checkApple(tile, run)) != 0) { + dryMove[MOVE_POINTS_IDX] += t; + if (t > 0) + ++dryMove[MOVE_RED_APPLES_IDX]; + else + ++dryMove[MOVE_BLACK_APPLES_IDX]; } // Check ladder - t = board.checkLadder(tile); - if (t != tile) { - System.out.println(name + " Ladder @" + tile + " new position " + t); + if ((t = board.checkLadder(tile, run)) != tile) { tile = t; - ++ret[2]; + ++dryMove[MOVE_LADDERS_IDX]; keepGoing = true; } // Check snakes - t = board.checkSnake(tile); - if (t != tile) { - System.out.println(name + " Ouch!! Snake @" + tile + " new position " + t); + if ((t = board.checkSnake(tile)) != tile) { tile = t; - ++ret[1]; + ++dryMove[MOVE_SNAKES_IDX]; keepGoing = true; } } while (keepGoing); - ret[0] = this.tile = tile; - return ret; + + dryMove[MOVE_TILE_IDX] = tile; + dryMove[MOVE_STEPS_IDX]= tile - dryMove[MOVE_INITTILE_IDX]; + if (run) { + lastMove = dryMove.clone(); + this.tile = lastMove[MOVE_TILE_IDX]; + score += lastMove[MOVE_POINTS_IDX]; + } + return dryMove; } - /**@} */ - - /** @name Data members (private) */ + //Liskov substitution principle + 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 */ /** @{ */ - private int playerId; /**< Player's ID */ - private String name; /**< Player's name */ - private int score; /**< Player's score */ - private Board board; /**< Reference to current board */ - private int tile; /**< Player's tile location */ - private int turn; /**< Player's turn of playing */ + int playerId; /**< Player's ID */ + String name; /**< Player's name */ + int score; /**< Player's score */ + Board board; /**< Reference to current board */ + int tile; /**< Player's tile location */ + int[] lastMove; + private int [] dryMove; /** @} */ } +