diff --git a/gui/src/controller/Controller.java b/gui/src/controller/Controller.java index b5ef51a072a221e4a1404a6024967b3b3c611d6e..c96d1ebeebc35deab6a79470658b1c7bab676c01 100644 --- a/gui/src/controller/Controller.java +++ b/gui/src/controller/Controller.java @@ -11,6 +11,7 @@ import javafx.scene.layout.BorderPane; import javafx.scene.paint.Color; import javafx.scene.shape.Polygon; import model.GameState; +import model.Move; import model.Player; import model.Tile; import view.TileView; @@ -72,10 +73,6 @@ public class Controller implements Initializable e.printStackTrace(); System.exit(1); } - UpdateThread upT = new UpdateThread(gameProcess, this.gameState, this.board, this.boardView); - upT.setDaemon(true); - upT.start(); - //Choice: who will start? ChoiceDialog<Player> playerChoice = new ChoiceDialog<>(Player.Red, Player.Red, Player.Blue); playerChoice.setTitle("Penguin game!"); @@ -93,6 +90,10 @@ public class Controller implements Initializable else gameInput.println("c"); } + + UpdateThread upT = new UpdateThread(gameProcess, this.gameState, this.board, this.boardView, humanPlayer); + upT.setDaemon(true); + upT.start(); } /** @@ -108,14 +109,12 @@ public class Controller implements Initializable this.tileNumber = tileNumber; } - /** - * Change the tiles' highlighted values to the given value - */ - private void changeTilesHighlightState(List<Integer> tiles, boolean value) + private void unHighlightTiles(List<Integer> tiles) { for (int tile : tiles) { - boardView[tile].setHighlighted(value); + boardView[tile].setHighlighted(false); + boardView[tile].setHighlightMove(null); boardView[tile].update(); } } @@ -129,30 +128,78 @@ public class Controller implements Initializable 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].setSelected(false); boardView[selectedTile].update(); - changeTilesHighlightState(gameState.getReachableTiles(humanPlayer, gameState.getPenguinOnTile(humanPlayer, selectedTile)), false); + unHighlightTiles(gameState.getReachableTiles(humanPlayer, gameState.getPenguinOnTile(humanPlayer, selectedTile))); 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 + if (penguinNb != -1) //There is a penguin on this tile: we want to select it + { + //Unselect previously selected tiles + if (selectedTile != -1) + { + boardView[selectedTile].setSelected(false); + boardView[selectedTile].update(); + unHighlightTiles(gameState.getReachableTiles(humanPlayer, gameState.getPenguinOnTile(humanPlayer, selectedTile))); + } + //Selecting new tile + boardView[tileNumber].setSelected(true); + boardView[tileNumber].update(); + selectedTile = tileNumber; + for (int i = 1; i <= gameState.getNbMoves(humanPlayer, penguinNb, GameState.Direction.A); i++) + { + boardView[selectedTile + i * 7].setHighlighted(true); + boardView[selectedTile + i * 7].setHighlightMove(new Move(GameState.Direction.A, i)); + boardView[selectedTile + i * 7].update(); + } + for (int i = 1; i <= gameState.getNbMoves(humanPlayer, penguinNb, GameState.Direction.B); i++) + { + boardView[selectedTile - i].setHighlighted(true); + boardView[selectedTile - i].setHighlightMove(new Move(GameState.Direction.B, i)); + boardView[selectedTile - i].update(); + } + for (int i = 1; i <= gameState.getNbMoves(humanPlayer, penguinNb, GameState.Direction.C); i++) + { + boardView[selectedTile - i * 8].setHighlighted(true); + boardView[selectedTile - i * 8].setHighlightMove(new Move(GameState.Direction.C, i)); + boardView[selectedTile - i * 8].update(); + } + for (int i = 1; i <= gameState.getNbMoves(humanPlayer, penguinNb, GameState.Direction.D); i++) + { + boardView[selectedTile - i * 7].setHighlighted(true); + boardView[selectedTile - i * 7].setHighlightMove(new Move(GameState.Direction.D, i)); + boardView[selectedTile - i * 7].update(); + } + for (int i = 1; i <= gameState.getNbMoves(humanPlayer, penguinNb, GameState.Direction.E); i++) + { + boardView[selectedTile + i].setHighlighted(true); + boardView[selectedTile + i].setHighlightMove(new Move(GameState.Direction.E, i)); + boardView[selectedTile + i].update(); + } + for (int i = 1; i <= gameState.getNbMoves(humanPlayer, penguinNb, GameState.Direction.F); i++) + { + boardView[selectedTile + i * 8].setHighlighted(true); + boardView[selectedTile + i * 8].setHighlightMove(new Move(GameState.Direction.F, i)); + boardView[selectedTile + i * 8].update(); + } return; - - //There is a penguin on the tile: we want to select this tile - if (selectedTile != -1) //If there was a tile previously selected + } + else if (boardView[tileNumber].isHighlighted()) //There is no penguin but this is a possible move for the penguin on the selected tile { + Move move = boardView[tileNumber].getHighlightMove(); + int moveNb = gameState.getPlayerMoveNumber(humanPlayer, gameState.getPenguinOnTile(humanPlayer, selectedTile), move.getDirection(), move.getSteps()); + //Before playing the move: deselect and de-highlight tiles boardView[selectedTile].setSelected(false); boardView[selectedTile].update(); - changeTilesHighlightState(gameState.getReachableTiles(humanPlayer, gameState.getPenguinOnTile(humanPlayer, selectedTile)), false); + unHighlightTiles(gameState.getReachableTiles(humanPlayer, gameState.getPenguinOnTile(humanPlayer, selectedTile))); + selectedTile = -1; + //Play the move + gameInput.println(moveNb); } - 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 f3ed2a903b6087d56e7b0e059f353fded15cd8c8..5a318f0e6f7bf0b3b29a2fb7edb23a4a5a126f3b 100644 --- a/gui/src/controller/UpdateThread.java +++ b/gui/src/controller/UpdateThread.java @@ -8,23 +8,25 @@ import model.Player; import model.Tile; import view.TileView; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; +import java.io.*; public class UpdateThread extends Thread { BufferedReader reader; + PrintWriter writer; GameState gameState; Tile[] board; TileView[] boardView; + Player humanPlayer; - public UpdateThread(Process program, GameState gameState, Tile[] board, TileView[] boardView) + public UpdateThread(Process program, GameState gameState, Tile[] board, TileView[] boardView, Player humanPlayer) { this.reader = new BufferedReader(new InputStreamReader(program.getInputStream())); + this.writer = new PrintWriter(new OutputStreamWriter(program.getOutputStream()), true); this.gameState = gameState; this.board = board; this.boardView = boardView; + this.humanPlayer = humanPlayer; } @@ -39,6 +41,20 @@ public class UpdateThread extends Thread System.out.println(line); if (line == null) { + Platform.runLater(() -> + { + Player computer = Player.Red; + if (humanPlayer.equals(Player.Red)) + computer = Player.Blue; + Alert alert = new Alert(Alert.AlertType.INFORMATION); + if (gameState.getScore(humanPlayer) > gameState.getScore(computer)) + alert.setHeaderText("You won!!!!"); + else if (gameState.getScore(humanPlayer) == gameState.getScore(computer)) + alert.setHeaderText("That's a draw. Not bad!"); + else + alert.setHeaderText("You just lost the penguin game."); + alert.showAndWait(); + }); gameRunning = false; } else if (line.contains("{")) //Line contains JSON @@ -59,6 +75,19 @@ public class UpdateThread extends Thread //UPDATE VIEW for (int i = 0; i < boardView.length; i++) boardView[i].update(); + + if (gameState.getCurrent_player() == humanPlayer) + { + if (!gameState.getCanPlay(humanPlayer)) + { + Platform.runLater(() -> + { + Alert alert = new Alert(Alert.AlertType.INFORMATION, "You can't play any move!", ButtonType.OK); + alert.showAndWait(); + writer.println("0"); //This pass the turn + }); + } + } } } catch (IOException e) diff --git a/gui/src/model/GameState.java b/gui/src/model/GameState.java index bab409a402b3ae3b94ce8adb937d6d70df5ccdb9..3d3da947e0c4e3f1de933dd5b941de4df5190e63 100644 --- a/gui/src/model/GameState.java +++ b/gui/src/model/GameState.java @@ -11,14 +11,17 @@ import java.util.Map; public class GameState { long[] fish; //Array of three bitboards: one for every fish value - boolean can_play_red, can_play_blue; //If the red(blue) player can play or if it has no moves left Player current_player; + Map<Player, Boolean> can_play; //If the red(blue) player can play or if it has no moves left Map<Player, int[]> penguins; //For every player, the list of his penguins Map<Player, Integer> score; //Score of every player public GameState() { fish = new long[3]; + can_play = new HashMap<>(); + can_play.put(Player.Red, true); + can_play.put(Player.Blue, true); penguins = new HashMap<>(); penguins.put(Player.Red, new int[4]); penguins.put(Player.Blue, new int[4]); @@ -31,8 +34,8 @@ public class GameState { //System.out.println(jsonString); JSONObject json = new JSONObject(jsonString); - can_play_red = json.getJSONObject("can_play").getBoolean("red"); - can_play_blue = json.getJSONObject("can_play").getBoolean("blue"); + can_play.put(Player.Red, json.getJSONObject("can_play").getBoolean("red")); + can_play.put(Player.Blue, json.getJSONObject("can_play").getBoolean("blue")); current_player = Player.valueOf(json.getString("current_player")); fish[0] = json.getJSONObject("bitboards").getLong("onefish"); fish[1] = json.getJSONObject("bitboards").getLong("twofish"); @@ -165,15 +168,7 @@ public class GameState return result; } - public boolean getCan_play_red() - { - return can_play_red; - } - - public boolean getCan_play_blue() - { - return can_play_blue; - } + public boolean getCanPlay(Player player) { return can_play.get(player); } public Player getCurrent_player() { diff --git a/gui/src/model/Move.java b/gui/src/model/Move.java new file mode 100644 index 0000000000000000000000000000000000000000..8dc29ec6bb08fa0e509e0a662d0ccc59028beb77 --- /dev/null +++ b/gui/src/model/Move.java @@ -0,0 +1,27 @@ +package model; + +public class Move +{ + GameState.Direction direction; + int steps; + + public Move(GameState.Direction direction, int steps) + { + this.direction = direction; + this.steps = steps; + } + + @Override + public String toString() + { + return "(" + direction + ", " + steps + ")"; + } + + public GameState.Direction getDirection() { return direction; } + + public void setDirection(GameState.Direction direction) { this.direction = direction; } + + public int getSteps() { return steps; } + + public void setSteps(int steps) { this.steps = steps; } +} diff --git a/gui/src/view/TileView.java b/gui/src/view/TileView.java index 214de4b84e8f3e2dc8ffbd2cc5a359b321fbb5f1..2ebb48993eb6d8ad3a94016dbaa1132a426bdf52 100644 --- a/gui/src/view/TileView.java +++ b/gui/src/view/TileView.java @@ -2,6 +2,7 @@ package view; import javafx.scene.paint.Color; import javafx.scene.shape.Polygon; +import model.Move; import model.Tile; /** @@ -12,6 +13,7 @@ public class TileView private Polygon fxTile; private Tile modelTile; private boolean selected, highlighted; + private Move highlightMove = null; // How do we get here from the selected tile (used when highlighting) public TileView(Polygon fxTile, Tile modelTile) { @@ -69,4 +71,8 @@ public class TileView public void setHighlighted(boolean highlighted) { this.highlighted = highlighted; } + public Move getHighlightMove() { return highlightMove; } + + public void setHighlightMove(Move highlightMove) { this.highlightMove = highlightMove; } + }