Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions Strategy/BasicMoveStrategy.java
Original file line number Diff line number Diff line change
@@ -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;
}

}
13 changes: 13 additions & 0 deletions Strategy/MoveStrategy.java
Original file line number Diff line number Diff line change
@@ -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 );

}
36 changes: 36 additions & 0 deletions Strategy/MoveStrategyFactory.java
Original file line number Diff line number Diff line change
@@ -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;
}

}
32 changes: 32 additions & 0 deletions Strategy/OptimalMoveStrategy.java
Original file line number Diff line number Diff line change
@@ -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<Cell> 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;
}
}
63 changes: 63 additions & 0 deletions Strategy/SmartMoveStrategy.java
Original file line number Diff line number Diff line change
@@ -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;
}
}
95 changes: 4 additions & 91 deletions api/AIEngine.java
Original file line number Diff line number Diff line change
@@ -1,108 +1,21 @@
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<Cell> 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{
throw new IllegalArgumentException();
}
}

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;
}
}