From 7ef04711c39ba11cdd79844a93d44f20be51fa84 Mon Sep 17 00:00:00 2001 From: ole Date: Fri, 20 Dec 2024 17:29:37 +0100 Subject: [PATCH 01/10] add getter for Player 1 --- src/GameBoard.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/GameBoard.java b/src/GameBoard.java index a645f9e..b6aa09c 100644 --- a/src/GameBoard.java +++ b/src/GameBoard.java @@ -212,4 +212,14 @@ public class GameBoard extends JPanel { this.ownBoardPanel.refresh(); this.opponentBoardPanel.refresh(); } + + /** + * Getter für Player1 + * @return Player 1 + * @author Peer Ole Wachtel + */ + public Player getP1() { + return p1; + } + } From f4cf28f4bf1c5f04279e7f64ac59fb81f68f11b5 Mon Sep 17 00:00:00 2001 From: ole Date: Fri, 20 Dec 2024 17:30:21 +0100 Subject: [PATCH 02/10] add endScreen machanic --- src/LocalPlayer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/LocalPlayer.java b/src/LocalPlayer.java index f3e434b..6c001e8 100644 --- a/src/LocalPlayer.java +++ b/src/LocalPlayer.java @@ -22,7 +22,7 @@ public class LocalPlayer extends Player { switch (hitResponse.getType()) { case HIT, SUNK -> this.myTurn = false; case MISS -> this.myTurn = true; - case VICTORY -> System.out.println("Game Over"); //TODO Was halt bei victory passiert ist hier wurder verloheren + case VICTORY -> GameController.getMainFrame().showPanelLoose("", this); //TODO Was halt bei victory passiert ist hier wurder verloheren } GameController.getMainFrame().refreshGameBoard(); } @@ -33,7 +33,7 @@ public class LocalPlayer extends Player { switch (hitResponse.getType()) { case HIT, SUNK -> this.myTurn = true; case MISS -> this.myTurn = false; - case VICTORY -> System.out.println("Win"); // TODO was halt beim victory passier ist hier wurde gewonnen + case VICTORY -> GameController.getMainFrame().showPanelWin("", this); // TODO was halt beim victory passier ist hier wurde gewonnen } GameController.getMainFrame().refreshGameBoard(); } From 20732e730cdc9b0860a63b783dc117fefdfd2b8c Mon Sep 17 00:00:00 2001 From: Luca Conte Date: Fri, 20 Dec 2024 17:31:16 +0100 Subject: [PATCH 03/10] some cleanup --- src/HumanPlayer.java | 6 +++++- src/LocalPlayer.java | 9 +++++++-- src/OnlinePlayer.java | 6 ++++++ src/OnlinePlayer_1_1_0.java | 6 ++++-- src/Player.java | 7 +++++++ 5 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/HumanPlayer.java b/src/HumanPlayer.java index ae0e298..4dfdbe1 100644 --- a/src/HumanPlayer.java +++ b/src/HumanPlayer.java @@ -1,4 +1,8 @@ public class HumanPlayer extends LocalPlayer { - + @Override + public void shoot(Point point) { + this.myTurn = false; + enemy.receiveShoot(point); + } } diff --git a/src/LocalPlayer.java b/src/LocalPlayer.java index f3e434b..ab19f20 100644 --- a/src/LocalPlayer.java +++ b/src/LocalPlayer.java @@ -10,6 +10,8 @@ public class LocalPlayer extends Player { @Override public synchronized void receiveShoot(Point point) { + if (!this.enemy.myTurn) return; + HitResponse hitResponse = board.getHitResponseOnPoint(point); if (!(hitResponse == null)){ enemy.receiveHit(hitResponse); @@ -46,10 +48,13 @@ public class LocalPlayer extends Player { } } + /** + * sends shot to enemy player. + * should ONLY be called on HumanPlayer + */ @Override public void shoot(Point point){ - this.myTurn = false; - enemy.receiveShoot(point); + return; } @Override diff --git a/src/OnlinePlayer.java b/src/OnlinePlayer.java index 14f3edb..4f0d56b 100644 --- a/src/OnlinePlayer.java +++ b/src/OnlinePlayer.java @@ -25,4 +25,10 @@ public abstract class OnlinePlayer extends Player implements AsyncSocketListener @Override public abstract void receiveCoin(boolean coin); + @Override + public void destroy() { + super.destroy(); + this.socket.close(); + } + } diff --git a/src/OnlinePlayer_1_1_0.java b/src/OnlinePlayer_1_1_0.java index a9b513d..eab7f1e 100644 --- a/src/OnlinePlayer_1_1_0.java +++ b/src/OnlinePlayer_1_1_0.java @@ -34,8 +34,8 @@ public class OnlinePlayer_1_1_0 extends OnlinePlayer { case "COIN": if(!this.hasReceivedCoinPackage && (p.getData().equals("1") || p.getData().equals("0"))){ this.myCoin = p.getData().equals("1"); - this.ready(); this.hasReceivedCoinPackage = true; + this.ready(); } break; @@ -75,6 +75,7 @@ public class OnlinePlayer_1_1_0 extends OnlinePlayer { @Override public synchronized void receiveShoot(Point point){ + if (!this.enemy.myTurn) return; super.socket.send(new SocketPackage("SHOOT",point.toString())); } @@ -94,6 +95,7 @@ public class OnlinePlayer_1_1_0 extends OnlinePlayer { @Override public synchronized void shoot(Point point) { - super.socket.send(new SocketPackage("SHOOT", point.toString())); + // SHOULD NEVER BE CALLED ON ONLINE PLAYER. ONLY ON HUMAN PLAYER + return; } } \ No newline at end of file diff --git a/src/Player.java b/src/Player.java index f36702d..5ea7ba7 100644 --- a/src/Player.java +++ b/src/Player.java @@ -77,4 +77,11 @@ public abstract class Player { public boolean isReady() { return this.sentCoin; } + + public void destroy() { + this.myTurn = false; + this.gameRunning = false; + this.board = null; + this.enemy = null; + } } From 3370975e579ce73026394845ae429e0eacf948cc Mon Sep 17 00:00:00 2001 From: ole Date: Fri, 20 Dec 2024 17:31:32 +0100 Subject: [PATCH 04/10] change parameta from showPanelWin and loos to check the request --- src/MainFrame.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/MainFrame.java b/src/MainFrame.java index 79454d4..6d0b533 100644 --- a/src/MainFrame.java +++ b/src/MainFrame.java @@ -127,9 +127,13 @@ public class MainFrame extends JFrame { /** * Spezifische ShowPanel für WinScreen Klasse * @param panelName Name des anzuzeigenden Panels - * @author Lucas Bronson + * @param player Player von dem die funktion aufgerufen worden ist + * @author Lucas Bronson, Peer Ole Wachtel */ - public void showPanelWin(String panelName){ + public void showPanelWin(String panelName, Player player){ + if(player != gameBoard.getP1()){ + return; + } WinScreen winScreen = new WinScreen(this); mainPanel.add(winScreen, panelName); mainPanel.revalidate(); @@ -140,9 +144,13 @@ public class MainFrame extends JFrame { /** * Spezifische ShowPanel für LooseScreen Klasse * @param panelName Name des anzuzeigenden Panels - * @author Lucas Bronson + * @param player Player von dem die funktion aufgerufen worden ist + * @author Lucas Bronson, Peer Ole Wachtel */ - public void showPanelLoose(String panelName){ + public void showPanelLoose(String panelName, Player player){ + if(player != gameBoard.getP1()){ + return; + } LooseScreen looseScreen = new LooseScreen(this); mainPanel.add(looseScreen,panelName); mainPanel.revalidate(); From bfb25dfe2c2189d1033ca8c41ad9ffb1ab07a75b Mon Sep 17 00:00:00 2001 From: ole Date: Fri, 20 Dec 2024 17:32:53 +0100 Subject: [PATCH 05/10] disable testButton --- src/startLocalGame.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/startLocalGame.java b/src/startLocalGame.java index 5253c78..1af1fa1 100644 --- a/src/startLocalGame.java +++ b/src/startLocalGame.java @@ -200,7 +200,7 @@ public class startLocalGame extends JPanel { testButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - frame.showPanelWin("WinPanel"); + //frame.showPanelWin("WinPanel"); } }); From 65451d6912b9a11eac523b39483472ca307335e3 Mon Sep 17 00:00:00 2001 From: Luca Conte Date: Fri, 20 Dec 2024 17:55:38 +0100 Subject: [PATCH 06/10] destroy for AI Player --- src/AiPlayer.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/AiPlayer.java b/src/AiPlayer.java index 724233c..d51e41e 100644 --- a/src/AiPlayer.java +++ b/src/AiPlayer.java @@ -35,6 +35,7 @@ public abstract class AiPlayer extends LocalPlayer implements Runnable { } public void aiShoot() { + if (!this.myTurn) return; this.enemy.receiveShoot(RandomPoint()); return; } @@ -93,4 +94,20 @@ public abstract class AiPlayer extends LocalPlayer implements Runnable { this.aiShoot(); } + + @Override + public void destroy() { + super.destroy(); + Iterator i = this.shootThreads.iterator(); + while(i.hasNext()) { + Thread thread = i.next(); + try { + thread.join(); + i.remove(); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } } \ No newline at end of file From b7215db6d98a3d703898c0d67eb1552736af4f66 Mon Sep 17 00:00:00 2001 From: Luca Conte Date: Fri, 20 Dec 2024 17:57:50 +0100 Subject: [PATCH 07/10] destroy players on game end --- src/GameBoard.java | 3 +++ src/MainFrame.java | 2 ++ 2 files changed, 5 insertions(+) diff --git a/src/GameBoard.java b/src/GameBoard.java index b6aa09c..0eaa8d3 100644 --- a/src/GameBoard.java +++ b/src/GameBoard.java @@ -221,5 +221,8 @@ public class GameBoard extends JPanel { public Player getP1() { return p1; } + public Player getP2() { + return p2; + } } diff --git a/src/MainFrame.java b/src/MainFrame.java index 6d0b533..e384f92 100644 --- a/src/MainFrame.java +++ b/src/MainFrame.java @@ -151,6 +151,8 @@ public class MainFrame extends JFrame { if(player != gameBoard.getP1()){ return; } + this.gameBoard.getP1().destroy(); + this.gameBoard.getP2().destroy(); LooseScreen looseScreen = new LooseScreen(this); mainPanel.add(looseScreen,panelName); mainPanel.revalidate(); From a3827d6bd011a08c061aa849772f49303597a426 Mon Sep 17 00:00:00 2001 From: Luca Conte Date: Fri, 20 Dec 2024 18:29:49 +0100 Subject: [PATCH 08/10] add metric shit ton of javadoc comments --- src/AiPlayer.java | 8 +++++ src/AsyncSocket.java | 63 +++++++++++++++++++++++++++++++++++- src/AsyncSocketListener.java | 3 ++ src/Board.java | 6 ++++ src/GameController.java | 56 ++++++++++++++++++++++++++++++++ 5 files changed, 135 insertions(+), 1 deletion(-) diff --git a/src/AiPlayer.java b/src/AiPlayer.java index d51e41e..f3ed2aa 100644 --- a/src/AiPlayer.java +++ b/src/AiPlayer.java @@ -69,6 +69,10 @@ public abstract class AiPlayer extends LocalPlayer implements Runnable { this.shootThreads.add(t); } + /** + * Closes past threads and tries firing a shot. + * @author Luca Conte + */ public void run() { Iterator i = this.shootThreads.iterator(); while(i.hasNext()) { @@ -95,6 +99,10 @@ public abstract class AiPlayer extends LocalPlayer implements Runnable { this.aiShoot(); } + /** + * Closes all running threads and does some cleanup work so the garbage collector will delete the player + * @author Luca Conte + */ @Override public void destroy() { super.destroy(); diff --git a/src/AsyncSocket.java b/src/AsyncSocket.java index a5aa22e..506309f 100644 --- a/src/AsyncSocket.java +++ b/src/AsyncSocket.java @@ -7,6 +7,10 @@ import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; +/** + * Provides an Interface to communicate using a socket asynchronously + * @author Luca Conte + */ public class AsyncSocket { private Socket socket; private Thread checkerThread; @@ -19,6 +23,12 @@ public class AsyncSocket { private BufferedReader in; private BufferedWriter out; + /** + * Creates a socket server and turns the first incoming connection into an AsyncSocket + * @param port the port to listen on for a connection + * @param handler the handler that will be called when a message is received + * @author Luca Conte + */ public AsyncSocket(int port, AsyncSocketListener handler) { this.setHandler(handler); @@ -45,6 +55,12 @@ public class AsyncSocket { this.connectorThread.start(); } + /** + * Connects to the address provided and turns the resulting socket into an AsyncSocket + * @param address the socket address to connect to + * @param handler the handler that will be called when a message is received + * @author Luca Conte + */ public AsyncSocket(InetSocketAddress address, AsyncSocketListener handler) { this.setHandler(handler); @@ -68,11 +84,22 @@ public class AsyncSocket { this.connectorThread.start(); } + /** + * @param socket the socket to be wrapped in an AsyncSocket + * @param handler the handler that will be called when a message is received + * @author Luca Conte + */ public AsyncSocket(Socket socket, AsyncSocketListener handler) throws IOException { this.setHandler(handler); this.initSocket(socket); } + /** + * creates input and ouput writer / readers as well as a checker thread to repeatedly check + * for incoming messages + * @param socket the socket to be wrapped + * @author Luca Conte + */ private void initSocket(Socket socket) throws IOException { System.out.println("Initialising sockets"); this.socket = socket; @@ -122,17 +149,39 @@ public class AsyncSocket { this.flushBuffer(); } + /** + * sets the message handler for the async socket + * @param handler the `AsyncSocketListener` to be set as the new handler + * @author Luca Conte + */ public void setHandler(AsyncSocketListener handler) { this.handler = handler; } + /** + * sends a message through the socket + * @param socketPackage the socket package to be sent + * @author Luca Conte + */ public synchronized void send(SocketPackage socketPackage) { this.sendLine(socketPackage.toString()); } + /** + * sends a message through the socket + * @param packageName the name of the package to be sent + * @author Luca Conte + */ public synchronized void send(String packageName) { this.send(packageName, ""); } + /** + * sends a message through the socket + * @param packageName the name of the package to be sent + * @param packageContent the content of the package to be sent. + * `packageName` and `packageContent` are joined with a space " " + * @author Luca Conte + */ public synchronized void send(String packageName, String packageContent) { if (packageContent.length() > 0) { packageContent = " " + packageContent; @@ -140,11 +189,19 @@ public class AsyncSocket { this.sendLine(packageName + packageContent); } + /** + * sends a string of text into the socket, concatenated with CRLF + * @author Luca Conte + */ public synchronized void sendLine(String message) { sendBuffer = sendBuffer + message + "\r\n"; this.flushBuffer(); } + /** + * flushes the buffers to send all pending messages + * @author Luca Conte + */ private synchronized void flushBuffer() { if (!this.sendBuffer.isEmpty() && this.out != null) { try { @@ -159,12 +216,16 @@ public class AsyncSocket { } } + /** + * closes the socket connection and removes the checker thread + * @author Luca Conte + */ public void close() { this.shouldStop = true; try { this.socket.close(); - this.checkerThread.join(); + if (this.checkerThread != null) this.checkerThread.join(); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { diff --git a/src/AsyncSocketListener.java b/src/AsyncSocketListener.java index a8c78ba..af3594e 100644 --- a/src/AsyncSocketListener.java +++ b/src/AsyncSocketListener.java @@ -1,3 +1,6 @@ +/** + * @author Luca Conte + */ public interface AsyncSocketListener { public void receive(String message); } \ No newline at end of file diff --git a/src/Board.java b/src/Board.java index c91468c..1b7095b 100644 --- a/src/Board.java +++ b/src/Board.java @@ -42,6 +42,12 @@ public class Board { return response; } + /** + * finds adjacened hit responses and sets their type to SUNK if they are currently HIT + * this makes it so that all the points of the ship are marked as SUNK, not just the final hit + * @param p the Point from which to propate the SUNK type + * @author Luca Conte + */ private void propagateSunk(Point p) { HitResponse hit = this.getHitResponseOnPoint(p); diff --git a/src/GameController.java b/src/GameController.java index 35b0764..6a921c9 100644 --- a/src/GameController.java +++ b/src/GameController.java @@ -5,28 +5,63 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +/** + * The central Backend Component + * @author Luca Conte + */ public class GameController { private static MainFrame mainFrame; + /** + * @return the current MainFrame + * @author Luca Conte + */ public static MainFrame getMainFrame() { return GameController.mainFrame; } + /** + * @param mainFrame the current MainFrame + * @author Luca Conte + */ public static void setMainFrame(MainFrame mainFrame) { GameController.mainFrame = mainFrame; } + /** + * converts a semester to be played in into its respective board size + * @param semester the semester to be played in + * @author Luca Conte + */ public static int semesterToBoardSize(int semester) { return semester + 13; } + /** + * converts a board size into its respective semester + * @param size the board size to get the semester of + * @author Luca Conte + */ public static int boardSizeToSemester(int size) { return size - 13; } + /** + * the list of supported versions of the online protocol + * https://github.com/lgc-4/ProgProjekt-Netzwerkstandard + */ public static HashMap> supportedVersions = new HashMap<>(Map.of( "1.1.0", OnlinePlayer_1_1_0.class )); + /** + * Starts a game with one local player and one online player. + * @param localPlayerClass the class of the local player to be instantiated. must extend `LocalPlayer` + * @param localPlayerName the name of the local player. Only necessarry when localPlayerClass is `HumanPlayer` + * @param address the Address of the opposing player. If the hostname of the address is set to be 0.0.0.0, it + * is interpreted that this instance should instead listen on the defined port for incoming connections. + * @param size the board size that it is intended to be played in + * @author Luca Conte + */ public static void startOnlineGame(Class localPlayerClass, String localPlayerName, InetSocketAddress address, int size) throws IOException { AsyncSocket clientSocket; @@ -90,6 +125,7 @@ public class GameController { /** * finds the largest common version in two lists of version strings * @return null if no common versions are found + * @author Luca Conte */ public static String findMostRecentVersion(List versions1, List versions2) { if (versions1 == null || versions2 == null) return null; @@ -114,10 +150,13 @@ public class GameController { /** * compares two version strings + * @param version1 the first version to be compared + * @param version2 the second version to be compared * @return * 0 if versions are equal * 1 if version1 is more recent than version2 * -1 otherwise + * @author Luca Conte */ public static int compareVersions(String version1, String version2) { if (!checkVersionString(version1) || !checkVersionString(version2)) { @@ -143,11 +182,21 @@ public class GameController { /** * checks if a provided string matches the format of a version number + * @param versionString the version String to be checked + * @author Luca Conte */ public static boolean checkVersionString(String versionString) { return versionString != null && versionString.matches("\\d+\\.\\d+\\.\\d+"); } + /** + * Starts a game with two local players + * @param localPlayerClass the class of the local player to be instantiated. must extend `LocalPlayer` + * @param localPlayerName the name of the local player. Only necessarry when localPlayerClass is `HumanPlayer` + * @param enemyClass the class of the enemy player. Must extend `AiPlayer`. For Humans VS Human games use an online game instead. + * @param size the board size that it is intended to be played in + * @author Luca Conte + */ public static void startLocalGame(Class localPlayerClass, String localPlayerName, Class enemyClass, int size) { LocalPlayer localPlayer; @@ -175,6 +224,13 @@ public class GameController { startGameWithInstancedPlayers(localPlayer, aiPlayer, size); } + /** + * switches to the ingame screen + * @param p1 the first player. This player is always shown on the left side of the screen and is expected to be the Human player, if there is one. + * @param p2 the second player + * @param boardSize the board size to be played in + * @author Luca Conte + */ public static void startGameWithInstancedPlayers(LocalPlayer p1, Player p2, int boardSize) { mainFrame.showPanelSLG("GameBoard", boardSizeToSemester(boardSize), p1, p2); From 6909b9417fa28920a9a65e8f604b745ec027990c Mon Sep 17 00:00:00 2001 From: Luca Conte Date: Mon, 23 Dec 2024 00:03:46 +0100 Subject: [PATCH 09/10] FINALLY FIX THE INDENTATION REEEE --- src/Ship.java | 82 ++++++++++++++++++++++++++++----------------------- 1 file changed, 45 insertions(+), 37 deletions(-) diff --git a/src/Ship.java b/src/Ship.java index 7dd7459..37decfd 100644 --- a/src/Ship.java +++ b/src/Ship.java @@ -6,43 +6,51 @@ import java.util.List; record ShipData (int size, String name){} public class Ship { - static List> semeterList = Arrays.asList(Arrays.asList( - new ShipData(2, "PRG 1"), - new ShipData(2, "GDI"), - new ShipData(2, "MAT 1"), - new ShipData(2, "THI"), - new ShipData(4, "STP"), - new ShipData(6, "ENG")), - Arrays.asList( - new ShipData(2, "PRG 2"), - new ShipData(2, "DBS 1"), - new ShipData(2, "MAT 2"), - new ShipData(2, "STA"), - new ShipData(2, "AUD")), - Arrays.asList( - new ShipData(2, "PRG 3"), - new ShipData(2, "DBS 2"), - new ShipData(2, "MAT 3"), - new ShipData(2, "BSN 1"), - new ShipData(4, "PRP"), - new ShipData(6, "BWL")), - Arrays.asList( - new ShipData(2, "WEB"), - new ShipData(2, "SE 1"), - new ShipData(2, "CG 1"), - new ShipData(2, "BSN 2"), - new ShipData(4, "SEM"), - new ShipData(6, "E BWL")), - Arrays.asList( - new ShipData(2, "WPF 1"), - new ShipData(2, "SE 2"), - new ShipData(2, "CG 2"), - new ShipData(2, "PXP 1"), - new ShipData(6, "EF 1")), - Arrays.asList( - new ShipData(2, "WPF 2"), - new ShipData(1, "PXP 2"), - new ShipData(8, "BAA")) + static List> semeterList = + Arrays.asList( + Arrays.asList( + new ShipData(2, "PRG 1"), + new ShipData(2, "GDI"), + new ShipData(2, "MAT 1"), + new ShipData(2, "THI"), + new ShipData(4, "STP"), + new ShipData(6, "ENG") + ), + Arrays.asList( + new ShipData(2, "PRG 2"), + new ShipData(2, "DBS 1"), + new ShipData(2, "MAT 2"), + new ShipData(2, "STA"), + new ShipData(2, "AUD") + ), + Arrays.asList( + new ShipData(2, "PRG 3"), + new ShipData(2, "DBS 2"), + new ShipData(2, "MAT 3"), + new ShipData(2, "BSN 1"), + new ShipData(4, "PRP"), + new ShipData(6, "BWL") + ), + Arrays.asList( + new ShipData(2, "WEB"), + new ShipData(2, "SE 1"), + new ShipData(2, "CG 1"), + new ShipData(2, "BSN 2"), + new ShipData(4, "SEM"), + new ShipData(6, "E BWL") + ), + Arrays.asList( + new ShipData(2, "WPF 1"), + new ShipData(2, "SE 2"), + new ShipData(2, "CG 2"), + new ShipData(2, "PXP 1"), + new ShipData(6, "EF 1") + ), + Arrays.asList( + new ShipData(2, "WPF 2"), + new ShipData(1, "PXP 2"), + new ShipData(8, "BAA") + ) ); private int size; From 8b4b017e85f28e71b809c3b0bec8703354100d16 Mon Sep 17 00:00:00 2001 From: Luca Conte Date: Mon, 23 Dec 2024 00:03:54 +0100 Subject: [PATCH 10/10] MORE javadoc --- src/Board.java | 23 +++++++++++++ src/HumanPlayer.java | 7 ++++ src/LocalPlayer.java | 21 ++++++++++++ src/OnlinePlayer.java | 12 ++++++- src/OnlinePlayer_1_1_0.java | 27 +++++++++++++++ src/Player.java | 62 ++++++++++++++++++++++++++++++++++ src/Point.java | 67 +++++++++++++++++++++++++++++++++++++ 7 files changed, 218 insertions(+), 1 deletion(-) diff --git a/src/Board.java b/src/Board.java index 1b7095b..0587b0c 100644 --- a/src/Board.java +++ b/src/Board.java @@ -61,6 +61,10 @@ public class Board { propagateSunk(new Point(p.getX(), p.getY() - 1)); } + /** + * creates all the ships on a board given a certain semester + * @param semester the semester to be played in + */ private void createShip(int semester){ List shipData = Ship.semeterList.get(semester -1); for (int i = 0; i < shipData.size(); i++) { @@ -68,10 +72,22 @@ public class Board { } } + /** + * @return a list of all the Ships on the board + */ public List getShips() { return ships; } + /** + * adds a HitResponse to the list of Hits on the board + * If a hit response already exists on the same position, the hit response will not be added + * If the hit response is of type `HitResponseType.SUNK` it will propagate this hit response type + * to all adjacened hit responses with type HIT using `propagateSunk`. + * @param hitResponse the HitResponse to be added + * @return true when the hit response was added, otherwise false + * + */ public synchronized boolean addHits(HitResponse hitResponse) { if (this.getHitResponseOnPoint(hitResponse.getPoint()) == null){ this.hits.add(hitResponse); @@ -87,6 +103,10 @@ public class Board { return false; } + /** + * @param point the position to get the hit response from + * @return the hit response at the position `point` + */ public synchronized HitResponse getHitResponseOnPoint(Point point) { for (int i = 0; i < this.hits.size(); i++){ if (this.hits.get(i).getPoint().equals(point)){ @@ -96,6 +116,9 @@ public class Board { return null; } + /** + * @return the size of the board + */ public int getSize() { return this.size; } diff --git a/src/HumanPlayer.java b/src/HumanPlayer.java index 4dfdbe1..6f00dbe 100644 --- a/src/HumanPlayer.java +++ b/src/HumanPlayer.java @@ -1,7 +1,14 @@ public class HumanPlayer extends LocalPlayer { + /** + * shoots a shot onto the provided point on the enemy board + * if it is not the players turn, this method does nothing. + * @param point the location to be shot + * @author Luca Conte + */ @Override public void shoot(Point point) { + if (!this.myTurn) return; this.myTurn = false; enemy.receiveShoot(point); } diff --git a/src/LocalPlayer.java b/src/LocalPlayer.java index af66e53..4da86a6 100644 --- a/src/LocalPlayer.java +++ b/src/LocalPlayer.java @@ -8,6 +8,11 @@ public class LocalPlayer extends Player { this.myCoin = random.nextBoolean(); } + /** + * receives a shot onto a point from the enemy + * @param point the location to be shot + * @author Luca Conte, Peer Ole Wachtel + */ @Override public synchronized void receiveShoot(Point point) { if (!this.enemy.myTurn) return; @@ -29,6 +34,11 @@ public class LocalPlayer extends Player { GameController.getMainFrame().refreshGameBoard(); } + /** + * receives a hit response from the enemy as a response to a receiveShoot call + * @param hitResponse the hitresponse + * @author Peer Ole Wachtel + */ @Override public synchronized void receiveHit(HitResponse hitResponse) { enemy.board.addHits(hitResponse); @@ -40,6 +50,13 @@ public class LocalPlayer extends Player { GameController.getMainFrame().refreshGameBoard(); } + /** + * receives the enemies coin toss result + * this method does nothing if the player has already received the enemies coin + * it will also call `determineCoinToss` + * @param coin the coin of the enemy player + * @author Luca Conte + */ @Override public synchronized void receiveCoin(boolean coin) { if (!this.hasReceivedCoin) { @@ -57,6 +74,10 @@ public class LocalPlayer extends Player { return; } + /** + * marks the player as ready, if all ships have been placed + * @author Luca Conte + */ @Override public synchronized void ready() { for (Ship ship : this.board.getShips()) { diff --git a/src/OnlinePlayer.java b/src/OnlinePlayer.java index 4f0d56b..2db0a90 100644 --- a/src/OnlinePlayer.java +++ b/src/OnlinePlayer.java @@ -1,9 +1,15 @@ -public abstract class OnlinePlayer extends Player implements AsyncSocketListener{ +public abstract class OnlinePlayer extends Player implements AsyncSocketListener { protected AsyncSocket socket; protected int wantedBoardSize; protected boolean hasReceivedCoinPackage; + /** + * Constructor + * @param size the size of the board the enemy player wants to play with + * the actual board size will be determined once the semester of the online partner is known + * @param socket an AsyncSocket to communicate with the enemy through + */ public OnlinePlayer(Integer size, AsyncSocket socket) { this.socket = socket; this.wantedBoardSize = size; @@ -25,6 +31,10 @@ public abstract class OnlinePlayer extends Player implements AsyncSocketListener @Override public abstract void receiveCoin(boolean coin); + /** + * closes the socket and does player cleanup work + * @author Luca Conte + */ @Override public void destroy() { super.destroy(); diff --git a/src/OnlinePlayer_1_1_0.java b/src/OnlinePlayer_1_1_0.java index eab7f1e..b401a6e 100644 --- a/src/OnlinePlayer_1_1_0.java +++ b/src/OnlinePlayer_1_1_0.java @@ -6,6 +6,12 @@ public class OnlinePlayer_1_1_0 extends OnlinePlayer { } + /** + * receives a message from the AsyncSocket + * implemented according to version 1.1.0 of https://github.com/lgc-4/ProgProjekt-Netzwerkstandard + * @param message the message from the socket + * @author Peer Ole Wachtel, Luca Conte + */ @Override public void receive(String message) { SocketPackage p = new SocketPackage(message); @@ -67,23 +73,44 @@ public class OnlinePlayer_1_1_0 extends OnlinePlayer { } } + /** + * sends introduction package IAM to online partner. + * @author Luca Conte + */ @Override public synchronized void sendIAM() { if (this.enemy == null) throw new RuntimeException("enemy has not yet been defined"); socket.send(new SocketPackage("IAM", GameController.boardSizeToSemester(this.wantedBoardSize) + " " + this.enemy.name)); } + /** + * receives a shot from the enemy and sends it to the online partner + * if it is not the enemies turn, this method does nothing. + * @param point the point to be shot + * @author Peer Ole Wachtel + */ @Override public synchronized void receiveShoot(Point point){ if (!this.enemy.myTurn) return; super.socket.send(new SocketPackage("SHOOT",point.toString())); } + /** + * receives a hitresponse from the enemy player and sends it to the online partner + * @param hitResponse the hitresponse to be sent + * @author Peer Ole Wachtel + */ @Override public synchronized void receiveHit(HitResponse hitResponse) { super.socket.send(new SocketPackage("HIT", hitResponse.toString())); } + /** + * receives the coin toss result from the enemy player and sends it to the online partner + * if this player has already received the enemies coin, this method does nothing. + * @param coin the result of the coin toss + * @author Peer Ole Wachtel, Luca Conte + */ @Override public synchronized void receiveCoin(boolean coin) { if (!this.hasReceivedCoin) { diff --git a/src/Player.java b/src/Player.java index 5ea7ba7..4adf76c 100644 --- a/src/Player.java +++ b/src/Player.java @@ -20,6 +20,11 @@ public abstract class Player { this.gameRunning = false; } + /** + * initialises this players board + * @param size the size of the board to be created + * @author Peer Ole Wachtel + */ public void createBoard(int size) { this.board = new Board(size); } @@ -30,25 +35,54 @@ public abstract class Player { public abstract void shoot(Point point); + /** + * only relevant for AI Players. + * starts the first turn + * @author Luca Conte + */ public void beginTurn() { System.out.println("issa my turn-a"); } + /** + * sets the enemy Player + * @author Peer Ole Wachtel + */ public void setEnemy(Player enemy) { this.enemy = enemy; } + /** + * sets the name of this player + * @param name the name of this player + * @author Luca Conte + */ public void setName(String name) { this.name = name; } + /** + * returns the name of this player + * @return the name of this player + * @author Luca Conte + */ public String getName() { return this.name; } + /** + * returns the board of this player + * @return the board of this player + * @author Lucas Bronson + */ public Board getBoard() { return this.board; } + /** + * marks the player as ready by sending their coin to the enemy player + * calls determineCoinToss if the enemy coin has already been received + * @author Luca Conte + */ public void ready() { this.enemy.receiveCoin(this.myCoin); this.sentCoin = true; @@ -57,6 +91,11 @@ public abstract class Player { } }; + /** + * determines the result of the coin toss + * this method does nothing if either player is not ready yet or has not yet sent their coin + * @author Luca Conte, Peer Ole Wachtel + */ protected void determineCoinToss() { if (!this.sentCoin || this.myCoin == null || !this.hasReceivedCoin || this.enemy.myCoin == null) return; boolean result = this.enemy.myCoin ^ this.myCoin; // XOR @@ -68,16 +107,39 @@ public abstract class Player { GameController.getMainFrame().refreshGameBoard(); } + /** + * receives the coin toss from the enemy player + * @param coin the coin of the enemy player + * @author Peer Ole Wachtel + */ public abstract void receiveCoin(boolean coin); + /** + * returns whether the game this player is in has started, meaning both players are ready and have sent their coins + * @return the game's running state + * @author Luca Conte + */ public boolean isGameRunning() { return this.gameRunning; } + /** + * returns whether this player is ready and has sent their coin to the enemy player + * @return the player's ready state + */ public boolean isReady() { return this.sentCoin; } + /** + * removes connections to the enemy and its board as well as setting myTurn and gameRunning to false + * this stops the AI Players from making more moves and allows the garbage collector to remove the boards + * and players + * + * This method should be called at the end of a game + * + * @author Luca Conte + */ public void destroy() { this.myTurn = false; this.gameRunning = false; diff --git a/src/Point.java b/src/Point.java index d5b06ed..301ec1e 100644 --- a/src/Point.java +++ b/src/Point.java @@ -2,10 +2,26 @@ public class Point { private int x; private int y; + /** + * initialises a point using X and Y coordinates starting at 0 + * @param x the x coordinate of the point starting at 0 + * @param y the y coordinate of the point starting at 0 + */ public Point (int x, int y) { this.setX(x); this.setY(y); } + + /** + * initialises a Point using a coordinate provided in the format of a letter followed by a number + * this coordinate is checked using `isValidSyntax` + * If the coordinate is not in a valid syntax, an `IllegalArgumentException` will be thrown, stating as such + * The number part of the coordinate starts at 1 instead of 0 so for example, the + * string A1 will result in the X and Y coordinates of (0, 0) + * @param str the coordinate in alphanumeric format + * @throws IllegalArgumentException if the coordinate is invalid according to `isValidSyntax` + * @author Peer Ole Wachtel, Luca Conte + */ public Point (String str) { if (Point.isValidSyntax(str)) { this.setX(str.charAt(0)); @@ -15,34 +31,78 @@ public class Point { } } + /** + * returns this point as a string in its alphanumeric format + * @return this point as a string in its alphanumeric format + * @author Luca Conte, Peer Ole Wachtel + */ @Override public String toString() { return (char) ('A' + this.x) + String.valueOf(this.y + 1); } + /** + * returns the X coordinate of the point starting at 0 + * @return the X coordinate of the point starting at 0 + * @author Peer Ole Wachtel + */ public int getX() { return x; } + /** + * returns the Y coordinate of the point starting at 0 + * @return the Y coordinate of the point starting at 0 + * @author Peer Ole Wachtel + */ public int getY() { return y; } + /** + * sets the X coordinate of the point starting at 0 + * @param x the X coordinate of the point starting at 0 + * @author Peer Ole Wachtel + */ public void setX(int x) { this.x = x; } + /** + * sets the Y coordinate of the point starting at 0 + * @param y the Y coordinate of the point starting at 0 + * @author Peer Ole Wachtel + */ public void setY(int y) { this.y = y; } + + /** + * sets the X coordinate of the from its character value in alphanumeric form + * @param c the character to be transformed into + * @author Peer Ole Wachtel + */ public void setX(char c) { this.x = c - 'A'; } + /** + * checks whether a string is a valid alphanumeric point coordinate + * @param str the string to be tested + * @return whether the string is valid according to the regular expression `^[A-Z]\\d+$` + * @author Peer Ole Wachtel + */ public static boolean isValidSyntax(String str) { return str.matches("^[A-Z]\\d+$"); } + /** + * returns whether two points are equal + * two points with equivalent coordinates are considered equal + * @param o the other object/Point to compare this one to + * @return whether the objects are equal + * @author Luca Conte + */ @Override public boolean equals(Object o) { if (this == o) return true; @@ -52,6 +112,13 @@ public class Point { return p.getX() == this.getX() && p.getY() == this.getY(); } + /** + * determines whether two points are neighbours + * points are considered neighbours if their positions are equal or within a difference of 1 on both X and Y axis + * @param other the point to check for neighbourship + * @return whether the points are neighbours + * @author Luca Conte + */ public boolean neighbours(Point other) { if (other == null) return false; return (int)Math.abs(this.getX() - other.getX()) <= 1 && (int)Math.abs(this.getY() - other.getY()) <= 1;