From c8b3f4f2db0f33273ea9716cf9ff0eb11704b5a7 Mon Sep 17 00:00:00 2001 From: FlorianAlexy Date: Tue, 26 Nov 2024 16:43:25 +0100 Subject: [PATCH 1/8] Schiffe setzen Validierung hinzugefuegt Florian und Florian haben eine schoene Validierung zum setzen der Position eines Schiffes hinzugefuegt. --- src/AiPlayer.java | 8 ++--- src/Board.java | 2 +- src/Ship.java | 78 ++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 76 insertions(+), 12 deletions(-) diff --git a/src/AiPlayer.java b/src/AiPlayer.java index 05fc045..ca8c82d 100644 --- a/src/AiPlayer.java +++ b/src/AiPlayer.java @@ -8,14 +8,14 @@ public abstract class AiPlayer extends Player { } public Point RandomPoint() { Random random = new Random(); // Pseudo Random für zufallszahlen - int posx = random.nextInt(super.board.size); // Generiert 0 - 13 - int posy = random.nextInt(super.board.size); // + int posx = random.nextInt(super.board.getSize()); // Generiert 0 - 13 + int posy = random.nextInt(super.board.getSize()); // return new Point(posx,posy); } public void AiSetShips() { - for(int i = 0; i < super.board.ships.size(); i++) { // Interiert durch alle Shiffe - while(!super.board.ships.get(i).setPosition(RandomPoint())) + for(int i = 0; i < super.board.getShips().size(); i++) { // Interiert durch alle Shiffe + while(!super.board.getShips().get(i).setPosition(RandomPoint(), super.board.getShips(), super.board.getSize())) {} } // Versucht das Aktuelle Shiff zu setzten und wiederholt solange bis es funktioniert return; } diff --git a/src/Board.java b/src/Board.java index 5cec0cd..ae205a3 100644 --- a/src/Board.java +++ b/src/Board.java @@ -68,7 +68,7 @@ public class Board { } public int getSize() { - return size; + return this.size; } } diff --git a/src/Ship.java b/src/Ship.java index 08db6b6..de6cbff 100644 --- a/src/Ship.java +++ b/src/Ship.java @@ -1,10 +1,11 @@ + + import java.awt.Point; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -record ShipData (int size, String name){ -} +record ShipData (int size, String name){} public class Ship { static List> semeterList = Arrays.asList(Arrays.asList( @@ -56,16 +57,79 @@ public class Ship { public Ship (int size, String name) { this.size = size; this.name = name; - this.horizontal = false; + this.horizontal = false; //true = von Punkt aus nach rechts; false = von Punkt aus nach unten this.position = null; this.hitsOnMe = 0; this.sunk = false; } - public boolean setPosition(Point pos) { - //TODO Conte abrfrage ob shif da sein darf - this.position = pos; - return true; + public boolean setPosition(Point pos, List shipsList, int boardSize) { + // ueberpruefe boundaries + if (pos.x < 0 || pos.y < 0 || pos.x >= boardSize || pos.y >= boardSize) { + return false; + } + + // bestimme die Endposition anhand der Ausrichtung + int endX = pos.x; + int endY = pos.y; + + if (this.horizontal) { // rechts links + endX = pos.x + this.size - 1; + if (endX >= boardSize) { + return false; + } + } else { // oben unten + endY = pos.y + this.size - 1; + if (endY >= boardSize) { + return false; + } + } + + // Liste an Punkten die das Schiff einnehmen wuerde + List shipPoints = new ArrayList<>(); + for (int i = 0; i < this.size; i++) { + int x = this.horizontal ? pos.x + i : pos.x; //falls horizontal dann pos.x + i ansonsten pos.x + int y = this.horizontal ? pos.y : pos.y + i; + shipPoints.add(new Point(x, y)); + } + + // ueberlappen mit anderen Schiffen pruefen + for (Ship otherShip : shipsList) { + // eigenes Schiff ueberspringen + if (otherShip == this) { + continue; + } + // ueberspringe falls noch nicht gesetzt + if (otherShip.position == null) { + continue; + } + // Punkte die das andere Schiff besetzt + List otherShipPoints = otherShip.getOccupiedPoints(); + // ueberlappen checken + for (Point p : shipPoints) { + if (otherShipPoints.contains(p)) { + // ueberlappen entdeckt + return false; + } + } + } + + // kein ueberlappen also setze das Schiff + this.position = pos; + return true; + } + + public List getOccupiedPoints() { + List points = new ArrayList<>(); + if (this.position == null) { + return points; + } + for (int i = 0; i < this.size; i++) { + int x = this.horizontal ? this.position.x + i : this.position.x; + int y = this.horizontal ? this.position.y : this.position.y + i; + points.add(new Point(x, y)); + } + return points; } public Point getPosition() { From 11c7dda19be8d76f0f6052b3155a434338ded045 Mon Sep 17 00:00:00 2001 From: Luca Conte Date: Wed, 27 Nov 2024 12:59:55 +0100 Subject: [PATCH 2/8] fix deprecated function calls --- src/GameController.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/GameController.java b/src/GameController.java index 797def8..1d562eb 100644 --- a/src/GameController.java +++ b/src/GameController.java @@ -7,8 +7,15 @@ public class GameController { public void startLocalGame(Class localPlayerClass, Class enemyClass, int size) throws InstantiationException, IllegalAccessException { - LocalPlayer localPlayer = localPlayerClass.newInstance(); - AiPlayer aiPlayer = enemyClass.newInstance(); + LocalPlayer localPlayer; + AiPlayer aiPlayer; + try { + localPlayer = localPlayerClass.getDeclaredConstructor().newInstance(); + aiPlayer = enemyClass.getDeclaredConstructor().newInstance(); + } catch (Exception e) { + e.printStackTrace(); + return; + } localPlayer.setEnemy(aiPlayer); aiPlayer.setEnemy(localPlayer); } From 73add1442b46f2b04760a4896cfdce121ba36892 Mon Sep 17 00:00:00 2001 From: Luca Conte Date: Wed, 27 Nov 2024 13:00:05 +0100 Subject: [PATCH 3/8] fix class names --- src/SpecificAiPlayerEasy.java | 4 ++-- src/SpecificAiPlayerHard.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/SpecificAiPlayerEasy.java b/src/SpecificAiPlayerEasy.java index 0bcce8c..c3ac64f 100644 --- a/src/SpecificAiPlayerEasy.java +++ b/src/SpecificAiPlayerEasy.java @@ -1,7 +1,7 @@ -public class SpecificAiPlayer1 extends AiPlayer{ +public class SpecificAiPlayerEasy extends AiPlayer{ - public SpecificAiPlayer1(int size) { + public SpecificAiPlayerEasy(int size) { super(size); } } diff --git a/src/SpecificAiPlayerHard.java b/src/SpecificAiPlayerHard.java index 0bcce8c..a28fa6c 100644 --- a/src/SpecificAiPlayerHard.java +++ b/src/SpecificAiPlayerHard.java @@ -1,7 +1,7 @@ -public class SpecificAiPlayer1 extends AiPlayer{ +public class SpecificAiPlayerHard extends AiPlayer{ - public SpecificAiPlayer1(int size) { + public SpecificAiPlayerHard(int size) { super(size); } } From b2a26c1f81878b8c283ecfc15024fc5b2a9bd5d2 Mon Sep 17 00:00:00 2001 From: Luca Conte Date: Wed, 27 Nov 2024 13:00:18 +0100 Subject: [PATCH 4/8] fix compiler errors --- src/OnlinePlayer.java | 6 ++++++ src/SpecificAiPlayerMedium.java | 10 +++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/OnlinePlayer.java b/src/OnlinePlayer.java index f53d50d..66316d6 100644 --- a/src/OnlinePlayer.java +++ b/src/OnlinePlayer.java @@ -2,4 +2,10 @@ import java.net.Socket; public abstract class OnlinePlayer extends Player{ private Socket socket; + + public OnlinePlayer(int size, Socket socket) { + super(size); + this.socket = socket; + //TODO Auto-generated constructor stub + } } diff --git a/src/SpecificAiPlayerMedium.java b/src/SpecificAiPlayerMedium.java index b808ff9..c122f43 100644 --- a/src/SpecificAiPlayerMedium.java +++ b/src/SpecificAiPlayerMedium.java @@ -1,3 +1,6 @@ +import java.util.ArrayList; +import java.util.List; +import java.awt.Point; public class SpecificAiPlayerMedium extends AiPlayer{ @@ -13,7 +16,7 @@ public class SpecificAiPlayerMedium extends AiPlayer{ // Shoot at the enemy and receive the hit response enemy.receiveShoot(nextShot); - HitResponse hitResponse = enemy.board.getHitResponsOnPoint(nextShot) + HitResponse hitResponse = enemy.board.getHitResponsOnPoint(nextShot); // If it's a hit or sunk, add adjacent cells to the hitsQueue if (hitResponse.getHitResponse() == HitResponseType.HIT) { addAdjacentPoints(nextShot); @@ -58,6 +61,11 @@ public class SpecificAiPlayerMedium extends AiPlayer{ } } + private boolean alreadyShot(Point p) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'alreadyShot'"); + } + private boolean isValidPoint(Point point) { return point.x >= 0 && point.x < board.getSize() && point.y >= 0 && point.y < board.getSize(); From c92b3b355164336e54c54fccfe986b52d44eb5a9 Mon Sep 17 00:00:00 2001 From: Luca Conte Date: Sat, 30 Nov 2024 13:45:06 +0100 Subject: [PATCH 5/8] networking basis --- src/AsyncSocket.java | 80 ++++++++++++++++++++++++++++++++++++ src/AsyncSocketListener.java | 3 ++ src/GameController.java | 42 +++++++++++++++++-- src/OnlinePlayer.java | 11 ++--- src/OnlinePlayer_1_1_0.java | 13 ++++++ src/SocketPackage.java | 55 +++++++++++++++++++++++++ 6 files changed, 195 insertions(+), 9 deletions(-) create mode 100644 src/AsyncSocket.java create mode 100644 src/AsyncSocketListener.java create mode 100644 src/OnlinePlayer_1_1_0.java create mode 100644 src/SocketPackage.java diff --git a/src/AsyncSocket.java b/src/AsyncSocket.java new file mode 100644 index 0000000..e91019d --- /dev/null +++ b/src/AsyncSocket.java @@ -0,0 +1,80 @@ +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.net.Socket; + +public class AsyncSocket { + private Socket socket; + private Thread checkerThread; + private AsyncSocketListener handler; + private boolean shouldStop = false; + + private BufferedReader in; + private PrintWriter out; + + public AsyncSocket(Socket socket, AsyncSocketListener handler) throws IOException { + this.socket = socket; + + this.in = new BufferedReader(new InputStreamReader(this.socket.getInputStream())); + this.out = new PrintWriter(new OutputStreamWriter(this.socket.getOutputStream())); + + this.handler = handler; + + this.checkerThread = new Thread(() -> { + while (!this.shouldStop) { + try { + if (!this.in.ready()) continue; + if (this.handler == null) continue; + + String message = this.in.readLine(); + if (message.length() <= 0) continue; + + this.handler.receive(message); + } catch (IOException e) { + e.printStackTrace(); + } + + try { + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + }); + this.checkerThread.start(); + } + + public void setHandler(AsyncSocketListener handler) { + this.handler = handler; + } + + + public void send(SocketPackage socketPackage) { + this.sendLine(socketPackage.toString()); + } + public void send(String packageName) { + this.send(packageName, ""); + } + public void send(String packageName, String packageContent) { + if (packageContent.length() > 0) { + packageContent = " " + packageContent; + } + this.sendLine(packageName + packageContent); + } + + public void sendLine(String message) { + this.out.print(message + "\r\n"); + } + + public void close() { + this.shouldStop = true; + + try { + this.socket.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/src/AsyncSocketListener.java b/src/AsyncSocketListener.java new file mode 100644 index 0000000..a8c78ba --- /dev/null +++ b/src/AsyncSocketListener.java @@ -0,0 +1,3 @@ +public interface AsyncSocketListener { + public void receive(String message); +} \ No newline at end of file diff --git a/src/GameController.java b/src/GameController.java index 1d562eb..5b3aa88 100644 --- a/src/GameController.java +++ b/src/GameController.java @@ -1,11 +1,45 @@ +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.util.Arrays; +import java.util.HashMap; + public class GameController { + // TODO: fix syntax i guess + public HashMap> supportedVersions = [{ "1.1.0" : OnlinePlayer_1_1_0.class }]; - public void startOnlineGame() { - // fuck you Luca and Ole von Florian und nicht von Florian - } + public void startOnlineGame(Class localPlayerClass, InetSocketAddress address) { + if (address.getHostName() == null) { + // SERVER MODE + try { + ServerSocket serverSocket = new ServerSocket(address.getPort()); - public void startLocalGame(Class localPlayerClass, Class enemyClass, int size) throws InstantiationException, IllegalAccessException { + System.out.println("Waiting for client connection..."); + + AsyncSocket clientSocket = new AsyncSocket(serverSocket.accept(), null); + clientSocket.send("VERSION", "Gruppe03 1.1.0"); // TODO: adjust versioning list + clientSocket.setHandler((message) -> { + + new OnlinePlayer_1_1_0(0, clientSocket); + + try { + serverSocket.close(); + } catch (IOException e) { + e.printStackTrace(); + } + }); + + } catch (IOException e) { + e.printStackTrace(); + return; + } + } else { + // CLIENT MODE + } + } + + public void startLocalGame(Class localPlayerClass, Class enemyClass, int size) { LocalPlayer localPlayer; AiPlayer aiPlayer; diff --git a/src/OnlinePlayer.java b/src/OnlinePlayer.java index 66316d6..f3aaaf8 100644 --- a/src/OnlinePlayer.java +++ b/src/OnlinePlayer.java @@ -1,11 +1,12 @@ -import java.net.Socket; +public abstract class OnlinePlayer extends Player implements AsyncSocketListener{ + private AsyncSocket socket; -public abstract class OnlinePlayer extends Player{ - private Socket socket; - - public OnlinePlayer(int size, Socket socket) { + public OnlinePlayer(int size, AsyncSocket socket) { super(size); this.socket = socket; //TODO Auto-generated constructor stub } + + public abstract void receive(String message); + } diff --git a/src/OnlinePlayer_1_1_0.java b/src/OnlinePlayer_1_1_0.java new file mode 100644 index 0000000..916b294 --- /dev/null +++ b/src/OnlinePlayer_1_1_0.java @@ -0,0 +1,13 @@ +public class OnlinePlayer_1_1_0 extends OnlinePlayer { + public OnlinePlayer_1_1_0(int size, AsyncSocket socket) { + super(size, socket); + } + + @Override + public void receive(String message) { + SocketPackage p = new SocketPackage(message); + + // TODO: parse package + } + +} \ No newline at end of file diff --git a/src/SocketPackage.java b/src/SocketPackage.java new file mode 100644 index 0000000..8f7e6ca --- /dev/null +++ b/src/SocketPackage.java @@ -0,0 +1,55 @@ +import java.util.Arrays; +import java.util.List; +public class SocketPackage { + + private String name; + private String data; + + public SocketPackage(String name, String data) { + this.setName(name); + this.setData(data); + } + public SocketPackage() { + this("",""); + } + public SocketPackage(String message) { + if (message.length() <= 0) { + throw new IllegalArgumentException("Socket message cannot be empty."); + } + String[] components = message.split(" "); + this.setName(components[0]); + if (components.length > 1) { + this.data = message.substring(components[0].length() + 1); + } else { + this.data = null; + } + } + + public void setName(String name) { + this.name = name.toUpperCase(); + } + + public void setData(String data) { + this.data = data; + } + + public String getName() { + return this.name; + } + + public String getData() { + return this.data; + } + + public String toString() { + if (this.data == null || this.data.length() == 0) { + return this.name; + } else { + return this.name + " " + this.data; + } + } + + public List splitData() { + return Arrays.asList(this.data.split(" ")); + } +} From 7303f49d0d84a3ad31eda65f5b6be7da7537332d Mon Sep 17 00:00:00 2001 From: Luca Conte Date: Sat, 30 Nov 2024 14:13:01 +0100 Subject: [PATCH 6/8] avoid nulls --- src/SocketPackage.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/SocketPackage.java b/src/SocketPackage.java index 8f7e6ca..0dabd58 100644 --- a/src/SocketPackage.java +++ b/src/SocketPackage.java @@ -2,8 +2,8 @@ import java.util.Arrays; import java.util.List; public class SocketPackage { - private String name; - private String data; + private String name = ""; + private String data = ""; public SocketPackage(String name, String data) { this.setName(name); @@ -19,17 +19,19 @@ public class SocketPackage { String[] components = message.split(" "); this.setName(components[0]); if (components.length > 1) { - this.data = message.substring(components[0].length() + 1); + this.setData(message.substring(components[0].length() + 1)); } else { - this.data = null; + this.setData(""); } } public void setName(String name) { + if (name == null) name = ""; this.name = name.toUpperCase(); } public void setData(String data) { + if (data == null) data = ""; this.data = data; } From ff9ffbd628434320700f99884808aa542bc0cc17 Mon Sep 17 00:00:00 2001 From: Luca Conte Date: Sat, 30 Nov 2024 14:13:15 +0100 Subject: [PATCH 7/8] sleep first in loop to avoid skipping sleep with continue --- src/AsyncSocket.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/AsyncSocket.java b/src/AsyncSocket.java index e91019d..7f1c535 100644 --- a/src/AsyncSocket.java +++ b/src/AsyncSocket.java @@ -24,6 +24,11 @@ public class AsyncSocket { this.checkerThread = new Thread(() -> { while (!this.shouldStop) { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } try { if (!this.in.ready()) continue; if (this.handler == null) continue; @@ -31,16 +36,11 @@ public class AsyncSocket { String message = this.in.readLine(); if (message.length() <= 0) continue; + // TODO: remove \r\n this.handler.receive(message); } catch (IOException e) { e.printStackTrace(); } - - try { - Thread.sleep(100); - } catch (InterruptedException e) { - e.printStackTrace(); - } } }); this.checkerThread.start(); From 8bc64bd9ba4a7150be26434ab2f1d760fe036bd6 Mon Sep 17 00:00:00 2001 From: Luca Conte Date: Sat, 30 Nov 2024 14:14:29 +0100 Subject: [PATCH 8/8] move joined logic out of if statement --- src/GameController.java | 52 ++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/src/GameController.java b/src/GameController.java index 5b3aa88..dfa6803 100644 --- a/src/GameController.java +++ b/src/GameController.java @@ -1,42 +1,46 @@ import java.io.IOException; import java.net.InetSocketAddress; import java.net.ServerSocket; -import java.util.Arrays; +import java.net.Socket; import java.util.HashMap; +import java.util.Map; public class GameController { - // TODO: fix syntax i guess - public HashMap> supportedVersions = [{ "1.1.0" : OnlinePlayer_1_1_0.class }]; + public HashMap> supportedVersions = new HashMap<>(Map.of( + "1.1.0", OnlinePlayer_1_1_0.class + )); - public void startOnlineGame(Class localPlayerClass, InetSocketAddress address) { + public void startOnlineGame(Class localPlayerClass, InetSocketAddress address) throws IOException { + AsyncSocket clientSocket; if (address.getHostName() == null) { // SERVER MODE - try { - ServerSocket serverSocket = new ServerSocket(address.getPort()); + ServerSocket serverSocket = new ServerSocket(address.getPort()); - System.out.println("Waiting for client connection..."); + System.out.println("Waiting for client connection..."); - AsyncSocket clientSocket = new AsyncSocket(serverSocket.accept(), null); - clientSocket.send("VERSION", "Gruppe03 1.1.0"); // TODO: adjust versioning list - clientSocket.setHandler((message) -> { + clientSocket = new AsyncSocket(serverSocket.accept(), null); - new OnlinePlayer_1_1_0(0, clientSocket); - - try { - serverSocket.close(); - } catch (IOException e) { - e.printStackTrace(); - } - }); - - } catch (IOException e) { - e.printStackTrace(); - return; - } + serverSocket.close(); } else { - // CLIENT MODE + Socket socket = new Socket(); + socket.connect(address); + + clientSocket = new AsyncSocket(socket, null); } + + clientSocket.send("VERSION", "Gruppe03 " + String.join(" ", supportedVersions.keySet())); + clientSocket.setHandler((message) -> { + + SocketPackage socketPackage = new SocketPackage(message); + if (socketPackage.getName().equals("VERSION")) { + // TODO: check version matches - instantiate online player + } else { + // TODO: received invalid package / package out of order + } + }); + // TODO: instantiate local player, set server / client roles + } public void startLocalGame(Class localPlayerClass, Class enemyClass, int size) {