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
35 changes: 11 additions & 24 deletions api/AIEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

import boards.TicTacToeBoard;
import game.*;
import stateManager.DefensivePlacement;
import stateManager.Placement;

import java.util.Optional;

public class AIEngine {
private RuleEngine ruleEngine;
Expand Down Expand Up @@ -62,32 +66,15 @@ public Cell getSmartMove(Player player, TicTacToeBoard board){
}

public Cell getOptimalMove(Player player, TicTacToeBoard board){

// 1. Victorious Move = We found a winning move.
Cell best = defense(player,board);
if(best!=null) return best;
// 2. Defensive Move = We found a move where Player wins and we block the move.
best = offense(player,board);
if(best!=null) return best;
// 3. Fork Move = If I have a fork, then play it.
// 4. AntiFork Move = If opponent have a fork, then block it.

GameInfo gameInfo = ruleEngine.getInfo(board);
if(gameInfo.hasAFork()){
best = gameInfo.getForkCell();
return best;
}
// 5. If the center is available, play it.
if(board.getSymbol(1,1)==null) return new Cell(1,1);
// 6. If the corner is available, play it.
int corners[][] = new int[][]{{0,0},{0,2},{2,0},{2,2}};
for(int i=0;i<4;i++){
if(board.getSymbol(corners[i][0],corners[i][1])==null) return new Cell(corners[i][0],corners[i][1]);
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);

//return new Cell(0,0);
}

public Move suggestMove(Player player, Board board){
Expand Down
36 changes: 36 additions & 0 deletions stateManager/CenterPlacement.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package stateManager;

import boards.TicTacToeBoard;
import game.Board;
import game.Cell;
import game.Move;
import game.Player;

import java.util.Optional;

public class CenterPlacement implements Placement{

private static CenterPlacement centerPlacement;

public synchronized static Placement get(){
if(centerPlacement!= null) return centerPlacement;
return new CenterPlacement();
}

@Override
public Optional<Cell> place(TicTacToeBoard board, Player player){
Cell center = null;
if (board.getSymbol(1, 1) == null) {
center= new Cell (1,1);
}
return Optional.ofNullable(center);

}

@Override
public Placement next(){
return CornerPlacement.get();
}


}
36 changes: 36 additions & 0 deletions stateManager/CornerPlacement.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package stateManager;

import boards.TicTacToeBoard;
import game.Board;
import game.Cell;
import game.Move;
import game.Player;

import java.util.Optional;

public class CornerPlacement implements Placement{

private static CornerPlacement cornerPlacement;

public synchronized static Placement get(){
if(cornerPlacement!= null) return cornerPlacement;
return new CornerPlacement();
}

@Override
public Optional<Cell> place(TicTacToeBoard board, Player player){
int corners[][] = new int[][]{{0,0},{0,2},{2,0},{2,2}};
Cell cell = null;
for(int i=0;i<4;i++){
if(board.getSymbol(corners[i][0],corners[i][1])==null) cell= new Cell(corners[i][0],corners[i][1]);
}
return Optional.ofNullable(cell);
}

@Override
public Placement next(){
return null;
}


}
47 changes: 47 additions & 0 deletions stateManager/DefensivePlacement.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package stateManager;

import boards.TicTacToeBoard;
import game.Board;
import game.Cell;
import game.Move;
import game.Player;

import java.util.Optional;

public class DefensivePlacement implements Placement{

private static DefensivePlacement defensivePlacement;

public synchronized static Placement get(){
if(defensivePlacement!= null) return defensivePlacement;
return new DefensivePlacement();
}

@Override
public Optional<Cell> place(TicTacToeBoard board, Player player){

return Optional.ofNullable(defense(player,board));
}

@Override
public Placement next(){
return OffensivePlacement.get();
}

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.clone();
boardCopy.move(move);
if (ruleEngine.getState(boardCopy).isOver()) {
return new Cell(i,j);
}
}
}
}
return null;
}

}
38 changes: 38 additions & 0 deletions stateManager/ForkPlacement.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package stateManager;

import boards.TicTacToeBoard;
import game.*;

import java.util.Optional;

public class ForkPlacement implements Placement{

private static ForkPlacement forkPlacement;

public synchronized static Placement get(){
if(forkPlacement!= null) return forkPlacement;
return new ForkPlacement();
}

@Override
public Optional<Cell> place(TicTacToeBoard board, Player player){

return Optional.ofNullable(fork(player,board));
}

@Override
public Placement next(){
return CenterPlacement.get();
}

private Cell fork(Player player, TicTacToeBoard board) {
GameInfo gameInfo = ruleEngine.getInfo(board);
Cell forkCell = null;
if(gameInfo.hasAFork()){
forkCell = gameInfo.getForkCell();
return forkCell;
}
return forkCell;
}

}
45 changes: 45 additions & 0 deletions stateManager/OffensivePlacement.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package stateManager;

import boards.TicTacToeBoard;
import game.Board;
import game.Cell;
import game.Move;
import game.Player;

import java.util.Optional;

public class OffensivePlacement implements Placement{
private static OffensivePlacement offensivePlacement;

public synchronized static Placement get(){
if(offensivePlacement!= null) return offensivePlacement;
return new OffensivePlacement();
}
@Override
public Optional<Cell> place(TicTacToeBoard board, Player player){
return Optional.ofNullable(offense(player,board));
}

@Override
public Placement next(){
return ForkPlacement.get() ;
}

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.clone();
boardCopy.move(move);
if(ruleEngine.getState(boardCopy).isOver()){
return new Cell(i,j);
}
}
}
}
return null;
}

}
14 changes: 14 additions & 0 deletions stateManager/Placement.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package stateManager;

import api.RuleEngine;
import boards.TicTacToeBoard;
import game.Cell;
import game.Player;

import java.util.Optional;

public interface Placement {
RuleEngine ruleEngine = new RuleEngine();
Optional<Cell> place(TicTacToeBoard board, Player player);
Placement next ();
}