diff --git a/gui/src/controller/Controller.java b/gui/src/controller/Controller.java index 865ceca43946b872ae9fdb8d9efac1050ec2a28f..b5ef51a072a221e4a1404a6024967b3b3c611d6e 100644 --- a/gui/src/controller/Controller.java +++ b/gui/src/controller/Controller.java @@ -19,6 +19,7 @@ import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.URL; +import java.util.List; import java.util.ResourceBundle; public class Controller implements Initializable @@ -30,6 +31,7 @@ public class Controller implements Initializable private Tile[] board; private TileView[] boardView; private Player humanPlayer; + private int selectedTile; @FXML private Polygon tile0, tile1, tile2, tile3, tile4, tile5, tile6, tile7, tile8, tile9, tile10, tile11, tile12, tile13, tile14, tile15, tile16, tile17, tile18, tile19, tile20, tile21, tile22, tile23, tile24, tile25, tile26, tile27, tile28, tile29, tile30, tile31, tile32, tile33, tile34, tile35, tile36, tile37, tile38, tile39, tile40, tile41, tile42, tile43, tile44, tile45, tile46, tile47, tile48, tile49, tile50, tile51, tile52, tile53, tile54, tile55, tile56, tile57, tile58, tile59; @@ -46,8 +48,10 @@ public class Controller implements Initializable for (int i = 0; i < fxTiles.length; i++) { board[i] = new Tile(i, Tile.PenguinPresence.NO_PENGUIN); + fxTiles[i].setOnMouseClicked(new TileClickHandler(i)); boardView[i] = new TileView(fxTiles[i], board[i]); } + this.selectedTile = -1; this.gameState = new GameState(); try { @@ -91,14 +95,64 @@ public class Controller implements Initializable } } - - private class MyClickHandler implements EventHandler<MouseEvent> + /** + * Event handler that will listen for a click on a tile. + * It is associated with a TileView + */ + private class TileClickHandler implements EventHandler<MouseEvent> { + private int tileNumber; + + public TileClickHandler(int tileNumber) + { + this.tileNumber = tileNumber; + } + + /** + * Change the tiles' highlighted values to the given value + */ + private void changeTilesHighlightState(List<Integer> tiles, boolean value) + { + for (int tile : tiles) + { + boardView[tile].setHighlighted(value); + boardView[tile].update(); + } + } + @Override public void handle(MouseEvent event) { - Polygon poly = (Polygon) event.getSource(); - poly.setFill(Color.GOLD); + if (!gameState.getCurrent_player().equals(humanPlayer)) + return; + + if (selectedTile == tileNumber) //If we clicked again on the selected tile + { + //UnSelect and un-highlight previously selected and highlighted tiles + boardView[selectedTile].setSelected(true); + boardView[selectedTile].update(); + changeTilesHighlightState(gameState.getReachableTiles(humanPlayer, gameState.getPenguinOnTile(humanPlayer, selectedTile)), false); + selectedTile = -1; + return; + } + + //We clicked on a tile that wasn't previously selected + int penguinNb = gameState.getPenguinOnTile(humanPlayer, tileNumber); + if (penguinNb == -1) //There is no penguin on this tile + return; + + //There is a penguin on the tile: we want to select this tile + if (selectedTile != -1) //If there was a tile previously selected + { + boardView[selectedTile].setSelected(false); + boardView[selectedTile].update(); + changeTilesHighlightState(gameState.getReachableTiles(humanPlayer, gameState.getPenguinOnTile(humanPlayer, selectedTile)), false); + } + boardView[tileNumber].setSelected(true); + boardView[tileNumber].update(); + changeTilesHighlightState(gameState.getReachableTiles(humanPlayer, penguinNb), true); + selectedTile = tileNumber; + return; } } diff --git a/gui/src/controller/UpdateThread.java b/gui/src/controller/UpdateThread.java index 14f84cafc98a8758a61e3c3f938d1fcc0885c02b..f3ed2a903b6087d56e7b0e059f353fded15cd8c8 100644 --- a/gui/src/controller/UpdateThread.java +++ b/gui/src/controller/UpdateThread.java @@ -58,7 +58,7 @@ public class UpdateThread extends Thread //UPDATE VIEW for (int i = 0; i < boardView.length; i++) - boardView[i].updateFromModel(); + boardView[i].update(); } } catch (IOException e) diff --git a/gui/src/model/GameState.java b/gui/src/model/GameState.java index ae3e8df4965c54465940838db10b80de4798fb75..bab409a402b3ae3b94ce8adb937d6d70df5ccdb9 100644 --- a/gui/src/model/GameState.java +++ b/gui/src/model/GameState.java @@ -3,7 +3,9 @@ package model; import org.json.JSONArray; import org.json.JSONObject; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; public class GameState @@ -72,17 +74,12 @@ public class GameState /** * @param player The penguin's owner - * @param i The number of the penguin for this player + * @param i The number of the penguin for this player * @return the total moves that this penguin can do */ public int getPenguinTotalMoves(Player player, int i) { return ((penguins.get(player)[i] >>> 6) & 63); } - public enum Direction - { - A,B,C,D,E,F; - } - /** * Get maximum number of tiles that a penguin can do in one specific direction */ @@ -122,18 +119,52 @@ public class GameState { int[] peng = penguins.get(player); int total = 0; - for(int i = 0; i < penguinNumber; i++) //We add the moves of all preceding penguins + for (int i = 0; i < penguinNumber; i++) //We add the moves of all preceding penguins total += getPenguinTotalMoves(player, i); - for(Direction d : Direction.values()) + for (Direction d : Direction.values()) { - if(d.equals(direction)) - return total+nbSteps-1; + if (d.equals(direction)) + return total + nbSteps - 1; else total += getNbMoves(player, penguinNumber, d); } return -1; } + /** + * @return The number of the penguin of this player that is on tile number tileNumber. Or -1 if there isn't any (note: there could be a penguin of the other player) + */ + public int getPenguinOnTile(Player player, int tileNumber) + { + for (int i = 0; i < penguins.get(player).length; i++) + if (getPenguinPos(player, i) == tileNumber) + return i; + return -1; + } + + /** + * @return The list of all tiles that could be reached by moving penguin penguinNb of player player + */ + public List<Integer> getReachableTiles(Player player, int penguinNb) + { + List<Integer> result = new ArrayList<>(); + int startingTile = getPenguinPos(player, penguinNb); + for (int i = 1; i <= getNbMoves(player, penguinNb, Direction.A); i++) + result.add(startingTile + i * 7); + for (int i = 1; i <= getNbMoves(player, penguinNb, Direction.B); i++) + result.add(startingTile - i); + for (int i = 1; i <= getNbMoves(player, penguinNb, Direction.C); i++) + result.add(startingTile - i * 8); + for (int i = 1; i <= getNbMoves(player, penguinNb, Direction.D); i++) + result.add(startingTile - i * 7); + for (int i = 1; i <= getNbMoves(player, penguinNb, Direction.E); i++) + result.add(startingTile + i); + for (int i = 1; i <= getNbMoves(player, penguinNb, Direction.F); i++) + result.add(startingTile + i * 8); + + return result; + } + public boolean getCan_play_red() { return can_play_red; @@ -154,4 +185,9 @@ public class GameState return score.get(player); } + public enum Direction + { + A, B, C, D, E, F; + } + } diff --git a/gui/src/view/TileView.java b/gui/src/view/TileView.java index f95e80f15bbae519cdefe40ac35059020351a3d0..214de4b84e8f3e2dc8ffbd2cc5a359b321fbb5f1 100644 --- a/gui/src/view/TileView.java +++ b/gui/src/view/TileView.java @@ -11,9 +11,11 @@ public class TileView { private Polygon fxTile; private Tile modelTile; + private boolean selected, highlighted; public TileView(Polygon fxTile, Tile modelTile) { + this.fxTile = fxTile; this.modelTile = modelTile; } @@ -21,30 +23,50 @@ public class TileView /** * Tell the view to update according to the model */ - public void updateFromModel() + public void update() { //TODO: Better tile representation + Color fillColor = null; //FISH NUMBER switch (modelTile.getNbFish()) { case 0: - fxTile.setFill(Color.LIGHTBLUE); + fillColor = Color.LIGHTBLUE; break; case 1: - fxTile.setFill(Color.GREENYELLOW); + fillColor = Color.GREENYELLOW; break; case 2: - fxTile.setFill(Color.GREEN); + fillColor = Color.GREEN; break; case 3: - fxTile.setFill(Color.DARKGREEN); + fillColor = Color.DARKGREEN; break; } //PENGUIN if (modelTile.getPenguinPresence().equals(Tile.PenguinPresence.RED_PENGUIN)) - fxTile.setFill(Color.RED); + fillColor = Color.RED; else if (modelTile.getPenguinPresence().equals(Tile.PenguinPresence.BLUE_PENGUIN)) - fxTile.setFill(Color.BLUE); + fillColor = Color.BLUE; + + //SELECTION/HIGHLIGHT + if (selected) + fillColor = fillColor.deriveColor(0, 1, 0.5, 1); + if (highlighted) + fillColor = fillColor.deriveColor(0, 0.5, 1, 1); + + fxTile.setFill(fillColor); } + + public Tile getModelTile() { return modelTile; } + + public boolean isSelected() { return selected; } + + public void setSelected(boolean selected) { this.selected = selected; } + + public boolean isHighlighted() { return highlighted; } + + public void setHighlighted(boolean highlighted) { this.highlighted = highlighted; } + }