changed algo. added build

This commit is contained in:
rattatwinko
2025-06-04 20:33:34 +02:00
parent 431a229157
commit 776c63f185
3 changed files with 650 additions and 24 deletions

View File

@@ -466,31 +466,50 @@ public class HamiltonianSnakeAI extends JPanel implements ActionListener {
scoreLabel.setText("Score: " + score);
}
}
private Point findDirectPathToFood(Point head, List<Point> possibleMoves) {
// Find moves that directly reduce distance to food
Point bestMove = null;
int minDistance = Integer.MAX_VALUE;
for (Point move : possibleMoves) {
int dist = estimateDistance(move, food);
if (dist < minDistance && !willCollideImmediately(move)) {
minDistance = dist;
bestMove = move;
}
}
return bestMove;
}
private Point getNextMove(Point head) {
List<Point> possibleMoves = getSafeMoves(head);
if (possibleMoves.isEmpty()) {
return head; // No safe moves available (will trigger game over)
return head; // No safe moves available
}
// 1. First priority: Don't die next turn
// 1. If food is very close and safe, go for it immediately
if (estimateDistance(head, food) <= 3) {
Point foodMove = findDirectPathToFood(head, possibleMoves);
if (foodMove != null) {
return foodMove;
}
}
// 2. Filter out immediately deadly moves
possibleMoves = filterImmediatelyDeadlyMoves(possibleMoves);
if (possibleMoves.isEmpty()) return head;
// 2. Second priority: Don't create future traps
possibleMoves = filterFutureTraps(possibleMoves, 3); // Look 3 moves ahead
if (possibleMoves.isEmpty()) return head;
// 3. If food is reachable and safe, go for it
// 3. If food is reachable via safe path, prioritize it
Point foodPathMove = findSafePathToFood(head, possibleMoves);
if (foodPathMove != null) {
if (foodPathMove != null && !willCreateTrap(foodPathMove)) {
return foodPathMove;
}
// 4. Follow Hamiltonian cycle with safety checks
return followSuperSafeHamiltonianCycle(head, possibleMoves);
}
private List<Point> filterImmediatelyDeadlyMoves(List<Point> moves) {
List<Point> safeMoves = new ArrayList<>();
for (Point move : moves) {
@@ -593,29 +612,35 @@ public class HamiltonianSnakeAI extends JPanel implements ActionListener {
return bestMove;
}
private boolean willCreateTrap(Point move) {
// Simulate the move
List<Point> simulatedBody = new ArrayList<>(snake.getBody());
simulatedBody.add(0, move);
simulatedBody.remove(simulatedBody.size() - 1);
// Check if this would leave enough space
int reachable = countReachableCells(move, new HashSet<>(simulatedBody));
return reachable < snake.getLength() * 0.5; // Adjust threshold as needed
}
private Point followSuperSafeHamiltonianCycle(Point head, List<Point> possibleMoves) {
int currentIndex = hamiltonianPath[head.y][head.x];
int nextIndex = (currentIndex + 1) % (gridSize * gridSize);
// Find the safest move along the cycle
Point bestMove = null;
int bestSafetyScore = -1;
for (Point move : possibleMoves) {
// Sort moves by how much they progress along the cycle
possibleMoves.sort(Comparator.comparingInt(move -> {
int moveIndex = hamiltonianPath[move.y][move.x];
int cycleProgress = (moveIndex - currentIndex + gridSize * gridSize) % (gridSize * gridSize);
return (moveIndex - currentIndex + gridSize * gridSize) % (gridSize * gridSize);
}));
// Calculate safety score (higher is better)
int safetyScore = (gridSize * gridSize - cycleProgress) + countSafeExits(move, new HashSet<>(snake.getBody()));
if (safetyScore > bestSafetyScore ||
(safetyScore == bestSafetyScore && cycleProgress < (gridSize * gridSize) / 2)) {
bestSafetyScore = safetyScore;
bestMove = move;
// Return the move that makes most progress while being safe
for (Point move : possibleMoves) {
if (!willCreateTrap(move)) {
return move;
}
}
return bestMove != null ? bestMove : possibleMoves.get(0);
// Fallback to first possible move if all would create traps
return possibleMoves.get(0);
}
private Point findOptimalPathToFood(Point head, List<Point> possibleMoves) {
@@ -982,4 +1007,12 @@ class Snake {
public boolean contains(Point point) {
return body.contains(point);
}
public int getGridSize() {
return gridSize;
}
public void setGridSize(int gridSize) {
this.gridSize = gridSize;
}
}