FloA #19

Merged
lgc merged 3 commits from FloA into main 2024-12-20 15:59:51 +00:00
8 changed files with 279 additions and 49 deletions

View File

@ -1,9 +1,16 @@
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random; import java.util.Random;
public abstract class AiPlayer extends LocalPlayer {
public abstract class AiPlayer extends LocalPlayer implements Runnable {
List<Thread> shootThreads;
public AiPlayer() { public AiPlayer() {
this.setName("AI Player"); this.setName("AI Player");
this.shootThreads = new ArrayList<>();
} }
public Point RandomPoint() { public Point RandomPoint() {
Random random = new Random(); // Pseudo Random für zufallszahlen Random random = new Random(); // Pseudo Random für zufallszahlen
@ -12,7 +19,14 @@ public abstract class AiPlayer extends LocalPlayer {
return new Point(posx,posy); return new Point(posx,posy);
} }
public void AiSetShips() { @Override
public void createBoard(int size) {
super.createBoard(size);
this.aiSetShips();
this.ready();
}
public void aiSetShips() {
for(int i = 0; i < super.board.getShips().size(); i++) { // Interiert durch alle Shiffe for(int i = 0; i < super.board.getShips().size(); i++) { // Interiert durch alle Shiffe
//TODO: set horizontal //TODO: set horizontal
while(!super.board.getShips().get(i).setPosition(RandomPoint(), true, super.board.getShips(), super.board.getSize())) {} while(!super.board.getShips().get(i).setPosition(RandomPoint(), true, super.board.getShips(), super.board.getSize())) {}
@ -20,8 +34,63 @@ public abstract class AiPlayer extends LocalPlayer {
return; return;
} }
public void AiShoot() { public void aiShoot() {
super.board.hit(RandomPoint()); this.enemy.receiveShoot(RandomPoint());
return; return;
} }
@Override
public synchronized void receiveHit(HitResponse hitResponse) {
super.receiveHit(hitResponse);
if (this.myTurn) {
Thread t = new Thread(this);
t.start();
this.shootThreads.add(t);
}
}
@Override
public synchronized void receiveShoot(Point point) {
super.receiveShoot(point);
if (this.myTurn) {
Thread t = new Thread(this);
t.start();
this.shootThreads.add(t);
}
}
@Override
public void beginTurn() {
Thread t = new Thread(this);
t.start();
this.shootThreads.add(t);
}
public void run() {
Iterator<Thread> i = this.shootThreads.iterator();
while(i.hasNext()) {
Thread thread = i.next();
if (!thread.isAlive()) {
try {
thread.join();
i.remove();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.aiShoot();
}
} }

View File

@ -160,12 +160,16 @@ public class GameController {
throw new RuntimeException("Unable to instantiate players"); throw new RuntimeException("Unable to instantiate players");
} }
localPlayer.createBoard(size); localPlayer.isServer = true;
aiPlayer.createBoard(size); aiPlayer.isServer = false;
localPlayer.setEnemy(aiPlayer); localPlayer.setEnemy(aiPlayer);
aiPlayer.setEnemy(localPlayer); aiPlayer.setEnemy(localPlayer);
localPlayer.createBoard(size);
aiPlayer.createBoard(size);
localPlayer.setName(localPlayerName); localPlayer.setName(localPlayerName);
startGameWithInstancedPlayers(localPlayer, aiPlayer, size); startGameWithInstancedPlayers(localPlayer, aiPlayer, size);

View File

@ -119,6 +119,9 @@ public class MainFrame extends JFrame {
} }
public void refreshGameBoard() { public void refreshGameBoard() {
if(this.gameBoard == null) {
return;
}
this.gameBoard.refresh(); this.gameBoard.refresh();
} }
} }

View File

@ -6,6 +6,7 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator;
import java.util.Map; import java.util.Map;
public class SoundHandler { public class SoundHandler {
@ -35,12 +36,14 @@ public class SoundHandler {
thread.start(); thread.start();
runningThreads.add(thread); runningThreads.add(thread);
} }
for (Thread oldThread : runningThreads) { Iterator<Thread> i = runningThreads.iterator();
while (i.hasNext()) {
Thread oldThread = i.next();
if (!oldThread.isAlive()) { if (!oldThread.isAlive()) {
try { try {
oldThread.join(); oldThread.join();
runningThreads.remove(oldThread); i.remove();
System.out.println("cleared thread"); System.out.println("cleared thread");
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); e.printStackTrace();

View File

@ -1,3 +1,9 @@
public class SpecificAiPlayerEasy extends AiPlayer{ public class SpecificAiPlayerEasy extends AiPlayer{
public SpecificAiPlayerEasy() {
super();
this.setName("AI Player Easy");
}
} }

View File

@ -1,3 +1,125 @@
import java.util.ArrayList;
import java.util.Random;
public class SpecificAiPlayerHard extends AiPlayer{ public class SpecificAiPlayerHard extends AiPlayer{
private int gridSize;
private boolean[][] shotsFired;
private final ArrayList<Point> hitQueue;
private final Random random;
private int nextChessRow;
private int nextChessCol;
public SpecificAiPlayerHard() {
super();
this.setName("AI Player Hard");
/*this.gridSize = super.board.getSize();
this.shotsFired = new boolean[gridSize][gridSize];*/
this.gridSize = 0;
this.hitQueue = new ArrayList<>();
this.random = new Random();
this.nextChessRow = 0;
this.nextChessCol = 0;
}
// Checks if a position has already been shot at
public boolean alreadyShot(Point p) {
return shotsFired[p.getX()][p.getY()];
}
// Generates the next move for the AI
public Point getNextMove() {
if(gridSize == 0) {
this.gridSize = super.board.getSize();
this.shotsFired = new boolean[gridSize][gridSize];
}
// If there are hits to process, prioritize those
while (!hitQueue.isEmpty()) {
Point target = hitQueue.remove(0);
if (!alreadyShot(target)) {
return target;
}
}
// Otherwise, use chess pattern targeting
int row = nextChessRow;
int col = nextChessCol;
while (alreadyShot(new Point(row, col))) {
advanceChessPattern();
row = nextChessRow;
col = nextChessCol;
}
shotsFired[row][col] = true;
advanceChessPattern();
return new Point(row, col);
}
@Override
public synchronized void receiveHit(HitResponse hitResponse) {
super.receiveHit(hitResponse);
// If it's a hit or sunk, add adjacent cells to the hitsQueue
if (hitResponse.getHitResponse() == HitResponseType.HIT) {
addAdjacentPoints(hitResponse.getPoint());
}
}
private void addAdjacentPoints(Point point) {
int x = point.getX();
int y = point.getY();
// Possible adjacent positions (up, down, left, right)
Point[] adjacentPoints = {
new Point(x, y - 1),
new Point(x, y + 1),
new Point(x - 1, y),
new Point(x + 1, y)
};
for (Point p : adjacentPoints) {
if (isValidPoint(p) && !alreadyShot(p) && !hitQueue.contains(p)) {
hitQueue.add(p);
}
}
}
private boolean isValidPoint(Point point) {
return point.getX() >= 0 && point.getX() < gridSize &&
point.getY() >= 0 && point.getY() < gridSize;
}
@Override
public void aiShoot() {
this.enemy.receiveShoot(getNextMove());
}
// Advances the chess pattern to the next cell
private void advanceChessPattern() {
nextChessCol += 2;
if (nextChessCol >= gridSize) {
nextChessRow += 1;
nextChessCol = (nextChessRow % 2 == 0) ? 0 : 1; // Alternate starting points for chess pattern
}
if (nextChessRow >= gridSize) {
nextChessRow = 0;
nextChessCol = 0; // Reset if pattern wraps around
}
}
// Adds adjacent cells to the hit queue
/* public void processHit(int row, int col) {
if (row > 0 && !alreadyShot(row - 1, col)) {
hitQueue.add(new int[]{row - 1, col});
}
if (row < gridSize - 1 && !alreadyShot(row + 1, col)) {
hitQueue.add(new int[]{row + 1, col});
}
if (col > 0 && !alreadyShot(row, col - 1)) {
hitQueue.add(new int[]{row, col - 1});
}
if (col < gridSize - 1 && !alreadyShot(row, col + 1)) {
hitQueue.add(new int[]{row, col + 1});
}
}*/
} }

View File

@ -6,19 +6,23 @@ public class SpecificAiPlayerMedium extends AiPlayer{
private List<Point> hitsQueue = new ArrayList<>(); private List<Point> hitsQueue = new ArrayList<>();
public SpecificAiPlayerMedium() { public SpecificAiPlayerMedium() {
super();
this.setName("AI Player Medium"); this.setName("AI Player Medium");
} }
@Override @Override
public void AiShoot() { public void aiShoot() {
Point nextShot = ComputeNextShot(); Point nextShot = ComputeNextShot();
// Shoot at the enemy and receive the hit response // Shoot at the enemy and receive the hit response
enemy.receiveShoot(nextShot); enemy.receiveShoot(nextShot);
}
HitResponse hitResponse = enemy.board.getHitResponseOnPoint(nextShot); @Override
public synchronized void receiveHit(HitResponse hitResponse) {
super.receiveHit(hitResponse);
// If it's a hit or sunk, add adjacent cells to the hitsQueue // If it's a hit or sunk, add adjacent cells to the hitsQueue
if (hitResponse.getHitResponse() == HitResponseType.HIT) { if (hitResponse.getHitResponse() == HitResponseType.HIT) {
addAdjacentPoints(nextShot); addAdjacentPoints(hitResponse.getPoint());
} }
} }
@ -61,8 +65,9 @@ public class SpecificAiPlayerMedium extends AiPlayer{
} }
private boolean alreadyShot(Point p) { private boolean alreadyShot(Point p) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'alreadyShot'"); return this.enemy.board.getHitResponseOnPoint(p) != null;
} }
private boolean isValidPoint(Point point) { private boolean isValidPoint(Point point) {

View File

@ -1,6 +1,7 @@
import javax.swing.*; import javax.swing.*;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.util.HashMap;
/** /**
* Das startLocalGame Panel dient dem Erstellen eines lokalen Spiels. * Das startLocalGame Panel dient dem Erstellen eines lokalen Spiels.
@ -203,42 +204,59 @@ public class startLocalGame extends JPanel {
// Um zum startLocalGameLoadingScreen zu wechseln und Daten an Backend weiterzureichen. // Um zum startLocalGameLoadingScreen zu wechseln und Daten an Backend weiterzureichen.
startButton.addActionListener(new ActionListener() { startButton.addActionListener(new ActionListener() {
@SuppressWarnings("unchecked")
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
HashMap<ImageIcon, Class<? extends LocalPlayer>> playerClassMap = new HashMap<>();
playerClassMap.put(humanPlayerIcon, HumanPlayer.class);
playerClassMap.put(aiPlayerEasyIcon, SpecificAiPlayerEasy.class);
playerClassMap.put(aiPlayerNormalIcon, SpecificAiPlayerMedium.class);
playerClassMap.put(aiPlayerHardIcon, SpecificAiPlayerHard.class);
frame.showPanelSLGLS("startLocalGameLoadingScreen", semesterCounter); //TODO frame.showPanelSLGLS("startLocalGameLoadingScreen", semesterCounter); //TODO
if (leftPlayerIcon.getIcon() == humanPlayerIcon) {// TODO Wird name wirklich weitergegeben?
if (rightPlayerIcon.getIcon() == aiPlayerEasyIcon) { Class<? extends LocalPlayer> leftPlayerClass = playerClassMap.get(leftPlayerIcon.getIcon());
GameController.startLocalGame(HumanPlayer.class, leftPlayerNickname, SpecificAiPlayerEasy.class, GameController.semesterToBoardSize(semesterCounter)); Class<? extends AiPlayer> rightPlayerClass = (Class<? extends AiPlayer>) playerClassMap.get(rightPlayerIcon.getIcon());
} else if (rightPlayerIcon.getIcon() == aiPlayerNormalIcon) { GameController.startLocalGame(
GameController.startLocalGame(HumanPlayer.class, leftPlayerNickname, SpecificAiPlayerMedium.class, GameController.semesterToBoardSize(semesterCounter)); leftPlayerClass, leftPlayerNickname,
} else if (rightPlayerIcon.getIcon() == aiPlayerHardIcon) { rightPlayerClass,
GameController.startLocalGame(HumanPlayer.class, leftPlayerNickname, SpecificAiPlayerHard.class, GameController.semesterToBoardSize(semesterCounter)); GameController.semesterToBoardSize(semesterCounter)
} );
} else if (leftPlayerIcon.getIcon() == aiPlayerEasyIcon) {
if (rightPlayerIcon.getIcon() == aiPlayerEasyIcon) { // if (leftPlayerIcon.getIcon() == humanPlayerIcon) {// TODO Wird name wirklich weitergegeben?
GameController.startLocalGame(HumanPlayer.class, leftPlayerNickname, SpecificAiPlayerEasy.class, GameController.semesterToBoardSize(semesterCounter)); // if (rightPlayerIcon.getIcon() == aiPlayerEasyIcon) {
} else if (rightPlayerIcon.getIcon() == aiPlayerNormalIcon) { // GameController.startLocalGame(HumanPlayer.class, leftPlayerNickname, SpecificAiPlayerEasy.class, GameController.semesterToBoardSize(semesterCounter));
GameController.startLocalGame(HumanPlayer.class, leftPlayerNickname, SpecificAiPlayerMedium.class, GameController.semesterToBoardSize(semesterCounter)); // } else if (rightPlayerIcon.getIcon() == aiPlayerNormalIcon) {
} else if (rightPlayerIcon.getIcon() == aiPlayerHardIcon) { // GameController.startLocalGame(HumanPlayer.class, leftPlayerNickname, SpecificAiPlayerMedium.class, GameController.semesterToBoardSize(semesterCounter));
GameController.startLocalGame(HumanPlayer.class, leftPlayerNickname, SpecificAiPlayerHard.class, GameController.semesterToBoardSize(semesterCounter)); // } else if (rightPlayerIcon.getIcon() == aiPlayerHardIcon) {
} // GameController.startLocalGame(HumanPlayer.class, leftPlayerNickname, SpecificAiPlayerHard.class, GameController.semesterToBoardSize(semesterCounter));
} else if (rightPlayerIcon.getIcon() == aiPlayerNormalIcon) { // }
if (rightPlayerIcon.getIcon() == aiPlayerEasyIcon) { // } else if (leftPlayerIcon.getIcon() == aiPlayerEasyIcon) {
GameController.startLocalGame(HumanPlayer.class, leftPlayerNickname, SpecificAiPlayerEasy.class, GameController.semesterToBoardSize(semesterCounter)); // if (rightPlayerIcon.getIcon() == aiPlayerEasyIcon) {
} else if (rightPlayerIcon.getIcon() == aiPlayerNormalIcon) { // GameController.startLocalGame(SpecificAiPlayerEasy.class, leftPlayerNickname, SpecificAiPlayerEasy.class, GameController.semesterToBoardSize(semesterCounter));
GameController.startLocalGame(HumanPlayer.class, leftPlayerNickname, SpecificAiPlayerMedium.class, GameController.semesterToBoardSize(semesterCounter)); // } else if (rightPlayerIcon.getIcon() == aiPlayerNormalIcon) {
} else if (rightPlayerIcon.getIcon() == aiPlayerHardIcon) { // GameController.startLocalGame(SpecificAiPlayerEasy.class, leftPlayerNickname, SpecificAiPlayerMedium.class, GameController.semesterToBoardSize(semesterCounter));
GameController.startLocalGame(HumanPlayer.class, leftPlayerNickname, SpecificAiPlayerHard.class, GameController.semesterToBoardSize(semesterCounter)); // } else if (rightPlayerIcon.getIcon() == aiPlayerHardIcon) {
} // GameController.startLocalGame(SpecificAiPlayerEasy.class, leftPlayerNickname, SpecificAiPlayerHard.class, GameController.semesterToBoardSize(semesterCounter));
} else if (rightPlayerIcon.getIcon() == aiPlayerHardIcon) { // }
if (rightPlayerIcon.getIcon() == aiPlayerEasyIcon) { // } else if (rightPlayerIcon.getIcon() == aiPlayerNormalIcon) {
GameController.startLocalGame(HumanPlayer.class, leftPlayerNickname, SpecificAiPlayerEasy.class, GameController.semesterToBoardSize(semesterCounter)); // if (rightPlayerIcon.getIcon() == aiPlayerEasyIcon) {
} else if (rightPlayerIcon.getIcon() == aiPlayerNormalIcon) { // GameController.startLocalGame(SpecificAiPlayerMedium.class, leftPlayerNickname, SpecificAiPlayerEasy.class, GameController.semesterToBoardSize(semesterCounter));
GameController.startLocalGame(HumanPlayer.class, leftPlayerNickname, SpecificAiPlayerMedium.class, GameController.semesterToBoardSize(semesterCounter)); // } else if (rightPlayerIcon.getIcon() == aiPlayerNormalIcon) {
} else if (rightPlayerIcon.getIcon() == aiPlayerHardIcon) { // GameController.startLocalGame(SpecificAiPlayerMedium.class, leftPlayerNickname, SpecificAiPlayerMedium.class, GameController.semesterToBoardSize(semesterCounter));
GameController.startLocalGame(HumanPlayer.class, leftPlayerNickname, SpecificAiPlayerHard.class, GameController.semesterToBoardSize(semesterCounter)); // } else if (rightPlayerIcon.getIcon() == aiPlayerHardIcon) {
} // GameController.startLocalGame(SpecificAiPlayerMedium.class, leftPlayerNickname, SpecificAiPlayerHard.class, GameController.semesterToBoardSize(semesterCounter));
} // }
// } else if (rightPlayerIcon.getIcon() == aiPlayerHardIcon) {
// if (rightPlayerIcon.getIcon() == aiPlayerEasyIcon) {
// GameController.startLocalGame(SpecificAiPlayerHard.class, leftPlayerNickname, SpecificAiPlayerEasy.class, GameController.semesterToBoardSize(semesterCounter));
// } else if (rightPlayerIcon.getIcon() == aiPlayerNormalIcon) {
// GameController.startLocalGame(SpecificAiPlayerHard.class, leftPlayerNickname, SpecificAiPlayerMedium.class, GameController.semesterToBoardSize(semesterCounter));
// } else if (rightPlayerIcon.getIcon() == aiPlayerHardIcon) {
// GameController.startLocalGame(SpecificAiPlayerHard.class, leftPlayerNickname, SpecificAiPlayerHard.class, GameController.semesterToBoardSize(semesterCounter));
// }
// }
} }
}); });