Compare commits

..

No commits in common. "43545afb45ec75ccba8345571f646ce31ba4f8d0" and "b1273e759de13f4a4befa13037c1072dfe8df851" have entirely different histories.

12 changed files with 40 additions and 242 deletions

View File

@ -1,8 +1,10 @@
import java.util.Random; import java.util.Random;
public abstract class AiPlayer extends LocalPlayer { public abstract class AiPlayer extends Player {
public AiPlayer() {} public AiPlayer(int size) {
super(size);
}
public Point RandomPoint() { public Point RandomPoint() {
Random random = new Random(); // Pseudo Random für zufallszahlen Random random = new Random(); // Pseudo Random für zufallszahlen
int posx = random.nextInt(super.board.getSize()); // Generiert 0 - 13 int posx = random.nextInt(super.board.getSize()); // Generiert 0 - 13

View File

@ -36,7 +36,7 @@ public class AsyncSocket {
String message = this.in.readLine(); String message = this.in.readLine();
if (message.length() <= 0) continue; if (message.length() <= 0) continue;
message = message.strip(); // TODO: remove \r\n
this.handler.receive(message); this.handler.receive(message);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();

View File

@ -2,33 +2,19 @@ import java.io.IOException;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.ServerSocket; import java.net.ServerSocket;
import java.net.Socket; import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
public class GameController { public class GameController {
// Connection timeout for client sockets in milliseconds
public static final int CONNECTION_TIMEOUT = 10 * 1000;
public static int semesterToBoardSize(int semester) {
return semester + 13;
}
public HashMap<String, Class<? extends OnlinePlayer>> supportedVersions = new HashMap<>(Map.of( public HashMap<String, Class<? extends OnlinePlayer>> supportedVersions = new HashMap<>(Map.of(
"1.1.0", OnlinePlayer_1_1_0.class "1.1.0", OnlinePlayer_1_1_0.class
)); ));
public void startOnlineGame(Class<? extends LocalPlayer> localPlayerClass, InetSocketAddress address, int size) throws IOException { public void startOnlineGame(Class<? extends LocalPlayer> localPlayerClass, InetSocketAddress address) throws IOException {
AsyncSocket clientSocket; AsyncSocket clientSocket;
if (address.getHostName() == null) {
boolean localPlayerIsServer = address.getHostName() == null;
if (localPlayerIsServer) {
// SERVER MODE // SERVER MODE
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...");
@ -37,21 +23,10 @@ public class GameController {
serverSocket.close(); serverSocket.close();
} else { } else {
// CLIENT MODE
Socket socket = new Socket(); Socket socket = new Socket();
socket.connect(address);
try {
socket.connect(address, CONNECTION_TIMEOUT);
clientSocket = new AsyncSocket(socket, null); clientSocket = new AsyncSocket(socket, null);
} catch (SocketTimeoutException e) {
e.printStackTrace();
throw new RuntimeException("Connection timed out");
} finally {
socket.close();
}
} }
clientSocket.send("VERSION", "Gruppe03 " + String.join(" ", supportedVersions.keySet())); clientSocket.send("VERSION", "Gruppe03 " + String.join(" ", supportedVersions.keySet()));
@ -59,101 +34,15 @@ public class GameController {
SocketPackage socketPackage = new SocketPackage(message); SocketPackage socketPackage = new SocketPackage(message);
if (socketPackage.getName().equals("VERSION")) { if (socketPackage.getName().equals("VERSION")) {
// TODO: check version matches - instantiate online player
List<String> opponentSupportedVersions = socketPackage.splitData();
String usedVersion = findMostRecentVersion(new ArrayList<String>(supportedVersions.keySet()), opponentSupportedVersions);
if (usedVersion == null) {
throw new RuntimeException("No common versions found");
}
// instantiate players
Class<? extends OnlinePlayer> onlinePlayerClass = supportedVersions.get(usedVersion);
LocalPlayer localPlayer;
OnlinePlayer onlinePlayer;
try {
localPlayer = localPlayerClass.getDeclaredConstructor().newInstance();
onlinePlayer = onlinePlayerClass.getDeclaredConstructor().newInstance((Integer)size, clientSocket);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("Unable to instantiate players");
}
localPlayer.isServer = localPlayerIsServer;
onlinePlayer.isServer = !localPlayerIsServer;
startGameWithInstancedPlayers(localPlayer, onlinePlayer);
} else { } else {
throw new RuntimeException("Unexpected Package received before game initialisation"); // TODO: received invalid package / package out of order
} }
}); });
// TODO: instantiate local player, set server / client roles
} }
/**
* finds the largest common version in two lists of version strings
* @return null if no common versions are found
*/
public String findMostRecentVersion(List<String> versions1, List<String> versions2) {
if (versions1 == null || versions2 == null) return null;
String largestCommonVersion = null;
for (String v1 : versions1) {
if (!checkVersionString(v1)) continue;
for (String v2 : versions2) {
if (!checkVersionString(v2)) continue;
// strings within the lists must be equal
// if no largest common version has been found or currently checked version is larger than
// previous largest common version, new largest version has been found
if (compareVersions(v1, v2) == 0 && (largestCommonVersion == null || compareVersions(v1, largestCommonVersion) >= 1)) {
largestCommonVersion = v1;
continue;
}
}
}
return largestCommonVersion;
}
/**
* compares two version strings
* @return
* 0 if versions are equal
* 1 if version1 is more recent than version2
* -1 otherwise
*/
public int compareVersions(String version1, String version2) {
if (!checkVersionString(version1) || !checkVersionString(version2)) {
throw new IllegalArgumentException("Version is not valid version string");
}
String[] version1Split = version1.split("\\.");
String[] version2Split = version2.split("\\.");
for (int i = 0; i < version1Split.length; i++) {
int v1 = Integer.parseInt(version1Split[i]);
int v2 = Integer.parseInt(version2Split[i]);
if (v1 == v2) continue;
if (v1 > v2) {
return 1;
} else {
return -1;
}
}
return 0;
}
/**
* checks if a provided string matches the format of a version number
*/
public boolean checkVersionString(String versionString) {
return versionString != null && versionString.matches("\\d+\\.\\d+\\.\\d+");
}
public void startLocalGame(Class<? extends LocalPlayer> localPlayerClass, Class<? extends AiPlayer> enemyClass, int size) { public void startLocalGame(Class<? extends LocalPlayer> localPlayerClass, Class<? extends AiPlayer> enemyClass, int size) {
LocalPlayer localPlayer; LocalPlayer localPlayer;
@ -163,20 +52,10 @@ public class GameController {
aiPlayer = enemyClass.getDeclaredConstructor().newInstance(); aiPlayer = enemyClass.getDeclaredConstructor().newInstance();
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
throw new RuntimeException("Unable to instantiate players"); return;
} }
localPlayer.setEnemy(aiPlayer);
localPlayer.createBoard(size); aiPlayer.setEnemy(localPlayer);
aiPlayer.createBoard(size);
startGameWithInstancedPlayers(localPlayer, aiPlayer);
}
private void startGameWithInstancedPlayers(LocalPlayer p1, Player p2) {
p1.setEnemy(p2);
p2.setEnemy(p1);
// TODO: frontend configuration
} }
} }

View File

@ -34,8 +34,4 @@ public class HitResponse {
public String toString() { public String toString() {
return this.getPoint().toString() + " " + this.type.ordinal(); return this.getPoint().toString() + " " + this.type.ordinal();
} }
public HitResponseType getType() {
return type;
}
} }

View File

@ -1,4 +1,7 @@
public class HumanPlayer extends LocalPlayer { public class HumanPlayer extends LocalPlayer {
public HumanPlayer(int size) {
super(size);
}
} }

View File

@ -1,11 +1,7 @@
import java.util.Random;
public class LocalPlayer extends Player { public class LocalPlayer extends Player {
public LocalPlayer(){ LocalPlayer(int size) {
super(); super(size);
Random random = new Random();
this.myCoin = random.nextBoolean();
} }
@Override @Override
@ -13,46 +9,14 @@ public class LocalPlayer extends Player {
HitResponse hitResponse = board.getHitResponsOnPoint(point); HitResponse hitResponse = board.getHitResponsOnPoint(point);
if (!(hitResponse == null)){ if (!(hitResponse == null)){
enemy.receiveHit(hitResponse); enemy.receiveHit(hitResponse);
} else { } else {
hitResponse = this.board.hit(point); enemy.receiveHit(this.board.hit(point));
enemy.receiveHit(hitResponse);
}
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
} }
} }
@Override @Override
public synchronized void receiveHit(HitResponse hitResponse) { public synchronized void receiveHit(HitResponse hitResponse) {
enemy.board.addHits(hitResponse); enemy.board.addHits(hitResponse);
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
}
}
@Override
public synchronized void receiveCoin(boolean coin) {
if (!this.haseReceivedCoin) {
boolean result = coin ^ this.myCoin; // XOR
this.myTurn = result == this.isServer;
this.haseReceivedCoin = true;
}
}
public void sendCoin() {
enemy.receiveCoin(this.myCoin);
}
@Override
public void shoot(Point point){
this.myTurn = false;
enemy.receiveShoot(point);
} }
} }

View File

@ -1,12 +1,9 @@
public abstract class OnlinePlayer extends Player implements AsyncSocketListener{ public abstract class OnlinePlayer extends Player implements AsyncSocketListener{
protected AsyncSocket socket; protected AsyncSocket socket;
protected int wantedBoardSize;
protected boolean hasReceivedCoinPackage;
public OnlinePlayer(int size, AsyncSocket socket) { public OnlinePlayer(int size, AsyncSocket socket) {
super(size);
this.socket = socket; this.socket = socket;
this.wantedBoardSize = size;
socket.setHandler(this); socket.setHandler(this);
//TODO Auto-generated constructor stub //TODO Auto-generated constructor stub
} }
@ -19,7 +16,4 @@ public abstract class OnlinePlayer extends Player implements AsyncSocketListener
@Override @Override
public abstract void receiveHit(HitResponse hitResponse); public abstract void receiveHit(HitResponse hitResponse);
@Override
public abstract void receiveCoin(boolean coin);
} }

View File

@ -11,34 +11,8 @@ public class OnlinePlayer_1_1_0 extends OnlinePlayer {
public void receive(String message) { public void receive(String message) {
SocketPackage p = new SocketPackage(message); SocketPackage p = new SocketPackage(message);
List<String> data = p.splitData(); // TODO: parse package
switch (p.getName()) { switch (p.getName()) {
case "IAM":
if (data.size() < 2) break;
if (this.board != null) break;
int semester = Integer.parseInt(data.get(0));
String username = p.getData().substring(data.get(0).length() + 1);
int usedBoardSize = Math.min(GameController.semesterToBoardSize(semester), this.wantedBoardSize);
this.setName(username);
this.createBoard(usedBoardSize);
this.enemy.createBoard(usedBoardSize);
break;
// TODO: IAMU
case "COIN":
if(!this.hasReceivedCoinPackage && (p.getData().equals("1") || p.getData().equals("0"))){
this.myCoin = p.getData().equals("1");
enemy.receiveCoin(this.myCoin);
this.hasReceivedCoinPackage = true;
}
break;
case "SHOOT": case "SHOOT":
if (Point.isValidSyntax(p.getData())){ if (Point.isValidSyntax(p.getData())){
Point point = new Point(p.getData()); Point point = new Point(p.getData());
@ -47,6 +21,7 @@ public class OnlinePlayer_1_1_0 extends OnlinePlayer {
break; break;
case "HIT": case "HIT":
List<String> data = p.splitData();
if (data.size()==2){ if (data.size()==2){
Point point = new Point(data.get(0)); Point point = new Point(data.get(0));
int typeIndex = Integer.parseInt(data.get(1)); int typeIndex = Integer.parseInt(data.get(1));
@ -75,12 +50,4 @@ public class OnlinePlayer_1_1_0 extends OnlinePlayer {
public synchronized void receiveHit(HitResponse hitResponse) { public synchronized void receiveHit(HitResponse hitResponse) {
super.socket.send(new SocketPackage("HIT", hitResponse.toString())); super.socket.send(new SocketPackage("HIT", hitResponse.toString()));
} }
@Override
public synchronized void receiveCoin(boolean coin) {
if (!this.haseReceivedCoin) {
super.socket.send(new SocketPackage("COIN", String.valueOf(coin ? 1 : 0)));
this.haseReceivedCoin = true;
}
}
} }

View File

@ -1,4 +1,3 @@
import java.util.Random;
public abstract class Player { public abstract class Player {
protected boolean myTurn; protected boolean myTurn;
@ -7,18 +6,8 @@ public abstract class Player {
protected Player enemy; protected Player enemy;
protected String name; protected String name;
protected Board board; protected Board board;
protected boolean myCoin;
protected boolean sendCoin; public Player(int size) {
protected boolean haseReceivedCoin;
public Player() {
this.haseReceivedCoin = false;
this.sendCoin = false;
}
public void createBoard(int size) {
this.board = new Board(size); this.board = new Board(size);
} }
@ -26,7 +15,9 @@ public abstract class Player {
public abstract void receiveHit(HitResponse hitResponse); public abstract void receiveHit(HitResponse hitResponse);
public abstract void shoot(Point point); public void click(Point point) {
}
public void beginTrun() { public void beginTrun() {
@ -35,14 +26,4 @@ public abstract class Player {
public void setEnemy(Player enemy) { public void setEnemy(Player enemy) {
this.enemy = enemy; this.enemy = enemy;
} }
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public abstract void receiveCoin(boolean coin);
} }

View File

@ -1,3 +1,7 @@
public class SpecificAiPlayerEasy extends AiPlayer{ public class SpecificAiPlayerEasy extends AiPlayer{
public SpecificAiPlayerEasy(int size) {
super(size);
}
} }

View File

@ -1,3 +1,7 @@
public class SpecificAiPlayerHard extends AiPlayer{ public class SpecificAiPlayerHard extends AiPlayer{
public SpecificAiPlayerHard(int size) {
super(size);
}
} }

View File

@ -5,6 +5,10 @@ public class SpecificAiPlayerMedium extends AiPlayer{
private List<Point> hitsQueue = new ArrayList<>(); private List<Point> hitsQueue = new ArrayList<>();
public SpecificAiPlayerMedium(int size) {
super(size);
}
@Override @Override
public void AiShoot() { public void AiShoot() {
Point nextShot = ComputeNextShot(); Point nextShot = ComputeNextShot();