diff --git a/Strategy/BasicMoveStrategy.java b/Strategy/BasicMoveStrategy.java new file mode 100644 index 0000000..101b1d1 --- /dev/null +++ b/Strategy/BasicMoveStrategy.java @@ -0,0 +1,22 @@ +package Strategy; + +import boards.TicTacToeBoard; +import game.Cell; +import game.CellBoard; +import game.Player; + +public class BasicMoveStrategy extends MoveStrategy{ + + @Override + public Cell move(Player player, TicTacToeBoard board) { + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + if (board.getSymbol(i,j)==null){ + return new Cell(i,j); + } + } + } + return null; + } + +} \ No newline at end of file diff --git a/Strategy/MoveStrategy.java b/Strategy/MoveStrategy.java new file mode 100644 index 0000000..4bbf32d --- /dev/null +++ b/Strategy/MoveStrategy.java @@ -0,0 +1,13 @@ +package Strategy; + +import boards.TicTacToeBoard; +import game.Board; +import game.Cell; +import game.CellBoard; +import game.Player; + +public abstract class MoveStrategy { + + public abstract Cell move(Player player, TicTacToeBoard board ); + +} \ No newline at end of file diff --git a/Strategy/MoveStrategyFactory.java b/Strategy/MoveStrategyFactory.java new file mode 100644 index 0000000..42b76fc --- /dev/null +++ b/Strategy/MoveStrategyFactory.java @@ -0,0 +1,36 @@ +package Strategy; + +import boards.TicTacToeBoard; +import game.Board; + +public class MoveStrategyFactory { + + + public static MoveStrategy createStrategy(Board board){ + if(board instanceof TicTacToeBoard board1){ + int threshold = 2; + if(countMoves(board1) < threshold){ + return new BasicMoveStrategy(); + } else if(countMoves(board1)< threshold + 1) { + return new SmartMoveStrategy(); + } else{ + return new OptimalMoveStrategy(); + } + } else{ + throw new IllegalArgumentException(); + } + } + + public static int countMoves(TicTacToeBoard board) { + int count = 0; + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + if (board.getSymbol(i, j) != null) { + count++; + } + } + } + return count; + } + +} diff --git a/Strategy/OptimalMoveStrategy.java b/Strategy/OptimalMoveStrategy.java new file mode 100644 index 0000000..97a458d --- /dev/null +++ b/Strategy/OptimalMoveStrategy.java @@ -0,0 +1,32 @@ +package Strategy; + +import boards.TicTacToeBoard; +import game.Cell; +import game.CellBoard; +import game.Player; +import stateManager.DefensivePlacement; +import stateManager.Placement; + +import java.util.Optional; + +public class OptimalMoveStrategy extends MoveStrategy { + @Override + public Cell move(Player player, TicTacToeBoard board) { + Placement placement = DefensivePlacement.get(); + while (placement.next()!=null){ + Optional place = placement.place(board,player); + if(place.isPresent()){ + return place.get(); + } + placement = placement.next(); + } + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + if (board.getSymbol(i,j)==null){ + return new Cell(i,j); + } + } + } + return null; + } +} \ No newline at end of file diff --git a/Strategy/SmartMoveStrategy.java b/Strategy/SmartMoveStrategy.java new file mode 100644 index 0000000..975d1bf --- /dev/null +++ b/Strategy/SmartMoveStrategy.java @@ -0,0 +1,63 @@ +package Strategy; + +import api.RuleEngine; +import boards.TicTacToeBoard; +import game.*; + + +public class SmartMoveStrategy extends MoveStrategy{ + private final RuleEngine ruleEngine; + + public SmartMoveStrategy() { + this.ruleEngine = new RuleEngine(); + } + + @Override + public Cell move(Player player, TicTacToeBoard board) { + Cell defense = defense(player,board); + if(defense!=null) return defense; + + Cell offense = offense(player,board); + if(offense!=null) return offense; + + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + if (board.getSymbol(i,j)==null){ + return new Cell(i,j); + } + } + } + return null; + } + + private Cell offense(Player player, TicTacToeBoard board) { + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + if (board.getSymbol(i,j)==null){ + Move move = new Move(player.flip(), new Cell(i,j)); + + Board boardCopy = board.dummyMove(move); + if(ruleEngine.getState(boardCopy).isOver()){ + return new Cell(i,j); + } + } + } + } + return null; + } + + private Cell defense(Player player, TicTacToeBoard board) { + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + if (board.getSymbol(i, j) == null) { + Move move = new Move(player.flip(), new Cell(i,j)); + Board boardCopy = board.dummyMove(move); + if (ruleEngine.getState(boardCopy).isOver()) { + return new Cell(i,j); + } + } + } + } + return null; + } +} \ No newline at end of file diff --git a/api/AIEngine.java b/api/AIEngine.java index 24407be..c73f572 100644 --- a/api/AIEngine.java +++ b/api/AIEngine.java @@ -1,92 +1,16 @@ package api; +import Strategy.MoveStrategy; +import Strategy.MoveStrategyFactory; import boards.TicTacToeBoard; import game.*; -import stateManager.DefensivePlacement; -import stateManager.OffensivePlacement; -import stateManager.Placement; - -import java.util.Optional; public class AIEngine { - private RuleEngine ruleEngine; - - public Cell getBasicMove(Player player, TicTacToeBoard board){ - for (int i = 0; i < 3; i++) { - for (int j = 0; j < 3; j++) { - if (board.getSymbol(i,j)==null){ - return new Cell(i,j); - } - } - } - return null; - } - - private Cell offense(Player player, TicTacToeBoard board) { - for (int i = 0; i < 3; i++) { - for (int j = 0; j < 3; j++) { - if (board.getSymbol(i,j)==null){ - Move move = new Move(player.flip(), new Cell(i,j)); - - Board boardCopy = board.dummyMove(move); - if(ruleEngine.getState(boardCopy).isOver()){ - return new Cell(i,j); - } - } - } - } - return null; - } - - private Cell defense(Player player, TicTacToeBoard board) { - for (int i = 0; i < 3; i++) { - for (int j = 0; j < 3; j++) { - if (board.getSymbol(i, j) == null) { - Move move = new Move(player.flip(), new Cell(i,j)); - Board boardCopy = board.dummyMove(move); - if (ruleEngine.getState(boardCopy).isOver()) { - return new Cell(i,j); - } - } - } - } - return null; - } - - public Cell getSmartMove(Player player, TicTacToeBoard board){ - // Victorious Move = We found a move where Computer Wins - Cell defense = defense(player,board); - if(defense!=null) return defense; - - Cell offense = offense(player,board); - if(offense!=null) return offense; - - return getBasicMove(player, board); - } - - public Cell getOptimalMove(Player player, TicTacToeBoard board){ - Placement placement = DefensivePlacement.get(); - while (placement.next()!=null){ - Optional place = placement.place(board,player); - if(place.isPresent()){ - return place.get(); - } - placement = placement.next(); - } - return getBasicMove(player, board); - } public Move suggestMove(Player player, Board board){ if(board instanceof TicTacToeBoard board1){ - Cell suggestedMove = null; - int threshold = 2; - if(countMoves(board1) < threshold){ - suggestedMove = getBasicMove(player,board1); - } else if(countMoves(board1)< threshold + 1) { - suggestedMove = getSmartMove(player,board1); - } else{ - suggestedMove = getOptimalMove(player, board1); - } + MoveStrategy moveStrategy = MoveStrategyFactory.createStrategy(board1); + Cell suggestedMove = moveStrategy.move(player,board1); if(suggestedMove != null) return new Move(player,suggestedMove); throw new IllegalStateException(); } else{ @@ -94,15 +18,4 @@ public Move suggestMove(Player player, Board board){ } } - public int countMoves(TicTacToeBoard board) { - int count = 0; - for (int i = 0; i < 3; i++) { - for (int j = 0; j < 3; j++) { - if (board.getSymbol(i, j) != null) { - count++; - } - } - } - return count; - } }