125 lines
3.8 KiB
Java
125 lines
3.8 KiB
Java
import java.util.ArrayList;
|
|
import java.util.Random;
|
|
|
|
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});
|
|
}
|
|
}*/
|
|
} |