Moved the Move record into it's own file, seperated from Game

This commit is contained in:
2025-10-29 14:49:43 +01:00
parent 13bac113b7
commit 925c848fda
15 changed files with 99 additions and 87 deletions

View File

@@ -1,5 +1,7 @@
package org.toop.game;
import org.toop.game.records.Move;
public abstract class AI<T extends Game> {
public abstract Game.Move findBestMove(T game, int depth);
public abstract Move findBestMove(T game, int depth);
}

View File

@@ -2,6 +2,7 @@ package org.toop.game.Connect4;
import org.toop.game.TurnBasedGame;
import org.toop.game.enumerators.GameState;
import org.toop.game.records.Move;
import java.util.ArrayList;

View File

@@ -1,26 +1,26 @@
package org.toop.game.Connect4;
import org.toop.game.AI;
import org.toop.game.Game;
import org.toop.game.enumerators.GameState;
import org.toop.game.records.Move;
public class Connect4AI extends AI<Connect4> {
public Game.Move findBestMove(Connect4 game, int depth) {
public Move findBestMove(Connect4 game, int depth) {
assert game != null;
assert depth >= 0;
final Game.Move[] legalMoves = game.getLegalMoves();
final Move[] legalMoves = game.getLegalMoves();
if (legalMoves.length <= 0) {
return null;
}
int bestScore = -depth;
Game.Move bestMove = null;
Move bestMove = null;
for (final Game.Move move : legalMoves) {
for (final Move move : legalMoves) {
final int score = getMoveScore(game, depth, move, true);
if (score > bestScore) {
@@ -32,7 +32,7 @@ public class Connect4AI extends AI<Connect4> {
return bestMove != null? bestMove : legalMoves[(int)(Math.random() * legalMoves.length)];
}
private int getMoveScore(Connect4 game, int depth, Game.Move move, boolean maximizing) {
private int getMoveScore(Connect4 game, int depth, Move move, boolean maximizing) {
final Connect4 copy = new Connect4(game);
final GameState state = copy.play(move);
@@ -45,10 +45,10 @@ public class Connect4AI extends AI<Connect4> {
return 0;
}
final Game.Move[] legalMoves = copy.getLegalMoves();
final Move[] legalMoves = copy.getLegalMoves();
int score = maximizing? depth + 1 : -depth - 1;
for (final Game.Move next : legalMoves) {
for (final Move next : legalMoves) {
if (maximizing) {
score = Math.min(score, getMoveScore(copy, depth - 1, next, false));
} else {

View File

@@ -5,7 +5,6 @@ import org.toop.game.interfaces.Playable;
import java.util.Arrays;
public abstract class Game implements Playable {
public record Move(int position, char value) {}
public static final char EMPTY = (char)0;

View File

@@ -1,9 +1,9 @@
package org.toop.game.interfaces;
import org.toop.game.Game;
import org.toop.game.enumerators.GameState;
import org.toop.game.records.Move;
public interface Playable {
Game.Move[] getLegalMoves();
GameState play(Game.Move move);
Move[] getLegalMoves();
GameState play(Move move);
}

View File

@@ -0,0 +1,3 @@
package org.toop.game.records;
public record Move(int position, char value) {}

View File

@@ -3,6 +3,7 @@ package org.toop.game.reversi;
import org.toop.game.Game;
import org.toop.game.TurnBasedGame;
import org.toop.game.enumerators.GameState;
import org.toop.game.records.Move;
import java.awt.*;
import java.util.ArrayList;

View File

@@ -1,12 +1,12 @@
package org.toop.game.reversi;
import org.toop.game.AI;
import org.toop.game.Game;
import org.toop.game.records.Move;
public final class ReversiAI extends AI<Reversi> {
@Override
public Game.Move findBestMove(Reversi game, int depth) {
Game.Move[] moves = game.getLegalMoves();
public Move findBestMove(Reversi game, int depth) {
Move[] moves = game.getLegalMoves();
int inty = (int)(Math.random() * moves.length-.5f);
return moves[inty];
}

View File

@@ -3,6 +3,7 @@ package org.toop.game.tictactoe;
import java.util.ArrayList;
import org.toop.game.TurnBasedGame;
import org.toop.game.enumerators.GameState;
import org.toop.game.records.Move;
public final class TicTacToe extends TurnBasedGame {
private int movesLeft;

View File

@@ -1,16 +1,16 @@
package org.toop.game.tictactoe;
import org.toop.game.AI;
import org.toop.game.Game;
import org.toop.game.enumerators.GameState;
import org.toop.game.records.Move;
public final class TicTacToeAI extends AI<TicTacToe> {
@Override
public Game.Move findBestMove(TicTacToe game, int depth) {
public Move findBestMove(TicTacToe game, int depth) {
assert game != null;
assert depth >= 0;
final Game.Move[] legalMoves = game.getLegalMoves();
final Move[] legalMoves = game.getLegalMoves();
if (legalMoves.length == 0) {
return null;
@@ -26,9 +26,9 @@ public final class TicTacToeAI extends AI<TicTacToe> {
}
int bestScore = -depth;
Game.Move bestMove = null;
Move bestMove = null;
for (final Game.Move move : legalMoves) {
for (final Move move : legalMoves) {
final int score = getMoveScore(game, depth, move, true);
if (score > bestScore) {
@@ -39,15 +39,15 @@ public final class TicTacToeAI extends AI<TicTacToe> {
return bestMove != null? bestMove : legalMoves[(int)(Math.random() * legalMoves.length)];
}
public Game.Move findWorstMove(TicTacToe game, int depth){
public Move findWorstMove(TicTacToe game, int depth){
Game.Move[] legalMoves = game.getLegalMoves();
Move[] legalMoves = game.getLegalMoves();
int bestScore = -depth;
Game.Move bestMove = null;
Move bestMove = null;
for (final Game.Move move : legalMoves) {
for (final Move move : legalMoves) {
final int score = getMoveScore(game, depth, move, false);
if (score > bestScore) {
@@ -58,7 +58,7 @@ public final class TicTacToeAI extends AI<TicTacToe> {
return bestMove;
}
private int getMoveScore(TicTacToe game, int depth, Game.Move move, boolean maximizing) {
private int getMoveScore(TicTacToe game, int depth, Move move, boolean maximizing) {
final TicTacToe copy = new TicTacToe(game);
final GameState state = copy.play(move);
@@ -71,10 +71,10 @@ public final class TicTacToeAI extends AI<TicTacToe> {
return 0;
}
final Game.Move[] legalMoves = copy.getLegalMoves();
final Move[] legalMoves = copy.getLegalMoves();
int score = maximizing? depth + 1 : -depth - 1;
for (final Game.Move next : legalMoves) {
for (final Move next : legalMoves) {
if (maximizing) {
score = Math.min(score, getMoveScore(copy, depth - 1, next, false));
} else {