diff --git a/Client/src/TicTacToe_Client.java b/Client/src/TicTacToe_Client.java index 875d779..ad9b2e8 100644 --- a/Client/src/TicTacToe_Client.java +++ b/Client/src/TicTacToe_Client.java @@ -9,47 +9,45 @@ public class TicTacToe_Client { private Engine renderEngine; private Client client; - private boolean isSingleServer; private static String clientName; + private boolean isPlayerOne; - public TicTacToe_Client(){ + public TicTacToe_Client() { renderEngine = Engine.waitForEngine(); - } - - private void ticTacToe_gameloop(){ - //Setup client = new Client("server", 2589, clientName); client.handshake(); - isSingleServer = client.getServerType(); - if (isSingleServer){ - this.setWindowTitle(client.isPlayerOne()); - client.sendToServer("ready"); - while (client.isConnected() && !renderEngine.isWindowClosed()) { - String message = client.getResponse(); - //Check if message is gamestate - if (message.charAt(0) == 'x' || message.charAt(0) == '-' || message.charAt(0) == 'o') { - this.drawBoard(message); - this.gameFlow("userInput"); - } - //Handle everything else - else { - this.gameFlow(message); - } + isPlayerOne = client.isPlayerOne(); + this.setWindowTitle(isPlayerOne); + client.sendToServer("ready"); + } + + private void ticTacToe_gameloop() { + this.drawBoard(client.getGameState()); + if (isPlayerOne){ + this.userInput(); + } + while (client.isConnected() && !renderEngine.isWindowClosed()) { + String message = client.getResponse(); + //Check if message is gamestate + if (message.charAt(0) == 'x' || message.charAt(0) == '-' || message.charAt(0) == 'o') { + this.drawBoard(message); } - try { - client.exitProcess(); - } catch (Exception e){ - e.printStackTrace(); + //Handle everything else + else { + this.gameFlow(message); } - } else { - this.setWindowTitle(client.isPlayerOne()); + } + try { + client.exitProcess(); + } catch (Exception e) { + e.printStackTrace(); } } - private void gameFlow(String input){ + private void gameFlow(String input) { switch (input) { case "userInput": - while(!renderEngine.isMouseClicked()){ + while (!renderEngine.isMouseClicked()) { try { Thread.sleep(100); } catch (InterruptedException e) { @@ -59,47 +57,62 @@ public class TicTacToe_Client { renderEngine.setMouseClicked(false); this.userInput(); break; + + case "invalidInput": + this.onInvalidInput(); + break; + + case "" } } + private void requestOpponentMove(){ + client.sendToServer("opponentMove"); + } + private void onGameEnd(){ + LinkedList winCoordinates = new LinkedList<>(); + //Get winning fields + String response = client.getResponse(); + for (String s : Arrays.copyOfRange(response.split(";"), 0, 4)) { + winCoordinates.add(Integer.valueOf(s) * 300); + } + //this.drawWinningLine(winCoordinates); + //client.exitProcess(); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + client.resetBoard(); + } + private void onInvalidInput(){ + int column = (int) renderEngine.getCoordinates().getX() / 300; + int row = (int) renderEngine.getCoordinates().getY() / 300; + System.err.printf("You are not allowed to place at %d|%d%n", column, row); + this.userInput(); + } - private void userInput(){ - //Send command - client.sendToServer("clientMove"); - //Send position - client.sendToServer(String.format("%f|%f", renderEngine.getCoordinates().getX(), renderEngine.getCoordinates().getY())); - //Get gameState - String gameState = client.getResponse(); - if (gameState.length() == 9) { - this.drawBoard(gameState); - //Send command - if (!client.getGameEnded()) { - client.sendToServer("computerMove"); - this.drawBoard(client.getResponse()); - } else { - LinkedList winCoordinates = new LinkedList<>(); - //Get winning fields - String response = client.getResponse(); - for (String s : Arrays.copyOfRange(response.split(";"), 0, 4)) { - winCoordinates.add(Integer.valueOf(s) * 300); - } - //this.drawWinningLine(winCoordinates); - //client.exitProcess(); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - client.resetBoard(); - } - } else { - int column = (int) renderEngine.getCoordinates().getX() / 300; - int row = (int) renderEngine.getCoordinates().getY() / 300; - System.err.printf("You are not allowed to place at %d|%d%n", column, row); - } - } + private void userInput() { + client.sendToServer("clientMove"); + client.sendToServer(String.format("%f|%f", renderEngine.getCoordinates().getX(), renderEngine.getCoordinates().getY())); + //Get gameState + String gameState = client.getResponse(); + if (gameState.length() == 9) { + this.drawBoard(gameState); + //Send command + if (!client.getGameEnded()) { + this.requestOpponentMove(); + } else { + this.onGameEnd(); + } + } else { + int column = (int) renderEngine.getCoordinates().getX() / 300; + int row = (int) renderEngine.getCoordinates().getY() / 300; + System.err.printf("You are not allowed to place at %d|%d%n", column, row); + } + } private void drawBoard(String gameState) { Platform.runLater(new Runnable() { @@ -110,8 +123,8 @@ public class TicTacToe_Client { }); } - private void setWindowTitle(boolean isClientOne){ - if (isClientOne){ + private void setWindowTitle(boolean isClientOne) { + if (isClientOne) { Platform.runLater(new Runnable() { @Override public void run() { @@ -129,16 +142,16 @@ public class TicTacToe_Client { } public static void main(String[] args) { - new Thread(){ + new Thread() { @Override - public void run(){ + public void run() { javafx.application.Application.launch(Engine.class); } }.start(); TicTacToe_Client test = new TicTacToe_Client(); - try{ + try { clientName = args[0]; - } catch (Exception e){ + } catch (Exception e) { clientName = "testing"; } test.ticTacToe_gameloop(); diff --git a/Client/src/networking/Client.java b/Client/src/networking/Client.java index 0191535..d6887be 100644 --- a/Client/src/networking/Client.java +++ b/Client/src/networking/Client.java @@ -92,6 +92,16 @@ public class Client { return isClientOne; } + public String getGameState(){ + try { + out.writeUTF("gameState"); + return this.getResponse(); + } catch (IOException e) { + e.printStackTrace(); + } + return "---------"; + } + public boolean getServerType(){ this.sendToServer("serverType"); boolean serverType = this.getBooleanResponse("isSingleServer"); diff --git a/Server/src/networking/TicTacToe_Server.java b/Server/src/networking/TicTacToe_Server.java index 036cdf2..655d889 100644 --- a/Server/src/networking/TicTacToe_Server.java +++ b/Server/src/networking/TicTacToe_Server.java @@ -11,13 +11,12 @@ import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.HashMap; -import java.util.Map; -import java.util.Objects; public class TicTacToe_Server { private ServerSocket serverSocket; private HashMap clients; + private HashMap clientIds; private HashMap clientNames; private HashMap clientMoveAuthorizations; private HashMap outstreams; @@ -25,6 +24,7 @@ public class TicTacToe_Server { private TicTacToe_GameRules ticTacToe_gameRules; private ServerLogger serverLogger; private int requiredConnections; + private boolean[] clientsReady; public TicTacToe_Server(int port, int requiredConnections) { @@ -32,12 +32,14 @@ public class TicTacToe_Server { serverSocket = new ServerSocket(port); clients = new HashMap<>(); clientNames = new HashMap<>(); + clientIds = new HashMap<>(); clientMoveAuthorizations = new HashMap<>(); outstreams = new HashMap<>(); instreams = new HashMap<>(); ticTacToe_gameRules = new TicTacToe_GameRules(); serverLogger = new ServerLogger(); this.requiredConnections = requiredConnections; + clientsReady = new boolean[requiredConnections]; serverLogger.printLog("Server started successfully", LogType.Log); } catch (IOException e) { @@ -46,6 +48,7 @@ public class TicTacToe_Server { } private boolean isSingleServer() { + serverLogger.printLog(""+ requiredConnections + (requiredConnections == 1), LogType.Error); return requiredConnections == 1; } @@ -56,6 +59,7 @@ public class TicTacToe_Server { while (clients.size() < requiredConnections) { Socket momentaryClient = serverSocket.accept(); clients.put(id, momentaryClient); + clientIds.put(clients.get(id), id); outstreams.put(momentaryClient, new DataOutputStream(momentaryClient.getOutputStream())); instreams.put(momentaryClient, new DataInputStream(momentaryClient.getInputStream())); id++; @@ -102,7 +106,7 @@ public class TicTacToe_Server { } } - public String handleInput(Socket client){ + public String handleInput(Socket client) { String message = null; try { message = instreams.get(client).readUTF(); @@ -117,31 +121,22 @@ public class TicTacToe_Server { } public void ticTacToe_gameloop() { - if (isSingleServer()) { - Socket client = clients.get(0); - //SingleServer GameLoop - while (!client.isClosed()) { - //Get instruction - this.gameFlow(handleInput(client), client); + while (clients.size() == requiredConnections) { + for (Socket client : clients.values()) { + gameFlow(handleInput(client), client); } - } else { - //MultiServer GameLoop - gameFlow("gameState"); } } - public void gameFlow(String input){ - this.gameFlow(input, null); - } - public void gameFlow(String input, Socket client) { switch (input) { case "ready": - if (isSingleServer()){ + if (isSingleServer()) { sendGameState(); } else { sendGameState(client); } + clientsReady[clientIds.get(client)] = true; break; case "gameState": @@ -152,14 +147,12 @@ public class TicTacToe_Server { try { //Get position (X|Y) String position = handleInput(client); - boolean moveAllowed = ticTacToe_gameRules.makeClientMove(position); + boolean moveAllowed = ticTacToe_gameRules.makeClientMove(position, clientIds.get(client)); if (moveAllowed) { sendGameState(); } else { - //send " " - outstreams.get(client).writeUTF("userInput"); + outstreams.get(client).writeUTF("invalidInput"); outstreams.get(client).flush(); - serverLogger.printLog("Requested userInput", LogType.Log); serverLogger.printLog(String.format("Move is not allowed!"), clientNames.get(client), LogType.Error); } } catch (IOException e) { @@ -167,21 +160,35 @@ public class TicTacToe_Server { } break; - case "computerMove": - ticTacToe_gameRules.makeComputerMove(); + case "opponentMove": + if (isSingleServer()) { + ticTacToe_gameRules.makeComputerMove(); + serverLogger.printLog("Made computer move", LogType.Log); + } else { + //request move from other player + try { + outstreams.get(1-clientIds.get(client)).writeUTF("userInput"); + outstreams.get(client).flush(); + serverLogger.printLog("Requested opponent userInput", clientNames.get(1-clientIds.get(client)), LogType.Log); + } catch (IOException e) { + e.printStackTrace(); + } + } sendGameState(); - try { - outstreams.get(client).writeUTF("userInput"); - outstreams.get(client).flush(); - serverLogger.printLog("Requested userInput", LogType.Log); - } catch (IOException e) { - e.printStackTrace(); + if (isSingleServer()) { + try { + outstreams.get(client).writeUTF("userInput"); + outstreams.get(client).flush(); + serverLogger.printLog("Requested userInput", LogType.Log); + } catch (IOException e) { + e.printStackTrace(); + } } break; case "serverType": try { - outstreams.get(client).writeBoolean(true); + outstreams.get(client).writeBoolean(isSingleServer()); outstreams.get(client).flush(); serverLogger.printLog("Sent serverType", Boolean.toString(true), clientNames.get(client), LogType.Log); } catch (IOException e) { @@ -190,19 +197,11 @@ public class TicTacToe_Server { break; case "isClientOne": - for (Map.Entry entry : clients.entrySet()) { - if (Objects.equals(client, entry.getValue())) { - try { - boolean isClientOne = entry.getKey() == 0; - outstreams.get(client).writeBoolean(isClientOne); - outstreams.get(client).flush(); - serverLogger.printLog("Sent isPlayerOne", Boolean.toString(isClientOne), clientNames.get(client), LogType.Log); - } catch (IOException e) { - e.printStackTrace(); - } - } else { - serverLogger.printLog("Current client not in clients!", LogType.Error); - } + boolean isClientOne = clientIds.get(client) == 0; + try { + outstreams.get(client).writeBoolean(isClientOne); + } catch (IOException e) { + e.printStackTrace(); } break; diff --git a/Server/src/res/TicTacToe_GameRules.java b/Server/src/res/TicTacToe_GameRules.java index d0ac1d4..310dc14 100644 --- a/Server/src/res/TicTacToe_GameRules.java +++ b/Server/src/res/TicTacToe_GameRules.java @@ -12,7 +12,7 @@ public class TicTacToe_GameRules { Point startWin, endWin; public TicTacToe_GameRules(){ - gameState = "---------"; + gameState = "o--x-o--x"; } public void resetGameState() { @@ -34,13 +34,13 @@ public class TicTacToe_GameRules { board = this.convertToNumbers(gameState); } - public boolean makeClientMove(String input) { + public boolean makeClientMove(String input, int id) { int column = Double.valueOf(input.split("\\|")[0]).intValue() / 300; int row = Double.valueOf(input.split("\\|")[1]).intValue() / 300; int index = column * 3 + row; if (isLegalMove(column, row)) { - makeMoveOnBoard(index, 0); + makeMoveOnBoard(index, id); return true; } else { return false; @@ -144,7 +144,6 @@ public class TicTacToe_GameRules { return horizontalWin() || verticalWin() || diagonalWin(); } - public Point[] getWinCoordinates(){ return new Point[]{startWin, endWin}; }