mirror of
https://github.com/2OOP/pism.git
synced 2026-02-04 10:54:51 +00:00
Moved the Move record into it's own file, seperated from Game
This commit is contained in:
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
3
game/src/main/java/org/toop/game/records/Move.java
Normal file
3
game/src/main/java/org/toop/game/records/Move.java
Normal file
@@ -0,0 +1,3 @@
|
||||
package org.toop.game.records;
|
||||
|
||||
public record Move(int position, char value) {}
|
||||
@@ -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;
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -6,6 +6,7 @@ import java.util.Set;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.toop.game.Game;
|
||||
import org.toop.game.records.Move;
|
||||
|
||||
class TicTacToeAITest {
|
||||
private TicTacToe game;
|
||||
@@ -22,12 +23,12 @@ class TicTacToeAITest {
|
||||
// X X -
|
||||
// O O -
|
||||
// - - -
|
||||
game.play(new Game.Move(0, 'X'));
|
||||
game.play(new Game.Move(3, 'O'));
|
||||
game.play(new Game.Move(1, 'X'));
|
||||
game.play(new Game.Move(4, 'O'));
|
||||
game.play(new Move(0, 'X'));
|
||||
game.play(new Move(3, 'O'));
|
||||
game.play(new Move(1, 'X'));
|
||||
game.play(new Move(4, 'O'));
|
||||
|
||||
final Game.Move move = ai.findBestMove(game, 1);
|
||||
final Move move = ai.findBestMove(game, 1);
|
||||
|
||||
assertNotNull(move);
|
||||
assertEquals('X', move.value());
|
||||
@@ -39,11 +40,11 @@ class TicTacToeAITest {
|
||||
// - - -
|
||||
// O - -
|
||||
// X X -
|
||||
game.play(new Game.Move(6, 'X'));
|
||||
game.play(new Game.Move(3, 'O'));
|
||||
game.play(new Game.Move(7, 'X'));
|
||||
game.play(new Move(6, 'X'));
|
||||
game.play(new Move(3, 'O'));
|
||||
game.play(new Move(7, 'X'));
|
||||
|
||||
final Game.Move move = ai.findBestMove(game, 1);
|
||||
final Move move = ai.findBestMove(game, 1);
|
||||
|
||||
assertNotNull(move);
|
||||
assertEquals('O', move.value());
|
||||
@@ -52,7 +53,7 @@ class TicTacToeAITest {
|
||||
|
||||
@Test
|
||||
void testBestMove_preferCornerOnEmpty() {
|
||||
final Game.Move move = ai.findBestMove(game, 0);
|
||||
final Move move = ai.findBestMove(game, 0);
|
||||
|
||||
assertNotNull(move);
|
||||
assertEquals('X', move.value());
|
||||
@@ -64,15 +65,15 @@ class TicTacToeAITest {
|
||||
// O X -
|
||||
// - O X
|
||||
// X O X
|
||||
game.play(new Game.Move(1, 'X'));
|
||||
game.play(new Game.Move(0, 'O'));
|
||||
game.play(new Game.Move(5, 'X'));
|
||||
game.play(new Game.Move(4, 'O'));
|
||||
game.play(new Game.Move(6, 'X'));
|
||||
game.play(new Game.Move(7, 'O'));
|
||||
game.play(new Game.Move(8, 'X'));
|
||||
game.play(new Move(1, 'X'));
|
||||
game.play(new Move(0, 'O'));
|
||||
game.play(new Move(5, 'X'));
|
||||
game.play(new Move(4, 'O'));
|
||||
game.play(new Move(6, 'X'));
|
||||
game.play(new Move(7, 'O'));
|
||||
game.play(new Move(8, 'X'));
|
||||
|
||||
final Game.Move move = ai.findBestMove(game, game.getLegalMoves().length);
|
||||
final Move move = ai.findBestMove(game, game.getLegalMoves().length);
|
||||
|
||||
assertNotNull(move);
|
||||
assertEquals('O', move.value());
|
||||
|
||||
Reference in New Issue
Block a user