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
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,8 @@ While doing Step 6, I learned these things:
3. Smartly think of handling concurrent request without causing deadlock (Ex here is if we wanted to undo the suggested move , then high possibility is that parallel request can create deadlocks)


Step 7: Making tests extensible, we now don't rely on AiEngine to suggest move, as our main focus is to test the moves and rules.
Step 7: Making tests extensible, we now don't rely on AiEngine to suggest move, as our main focus is to test the moves and rules.

Step 8: Using Prototype Design Pattern: It is used when we wanted to deep or shallow clone the object. It is beneficial when new Object creation is expensive

Step 9: We used Lambda functions to adhere to the DRY principle.
104 changes: 46 additions & 58 deletions api/RuleEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,70 +4,29 @@
import game.Board;
import game.GameState;

import java.util.function.BiFunction;
import java.util.function.Function;

public class RuleEngine {
public GameState getState(Board board){
if(board instanceof TicTacToeBoard board1) {
boolean rowComplete = true;
for (int i = 0; i < 3; i++) {
String firstCharacter = board1.getSymbol(i,0);
rowComplete = firstCharacter!=null;
if(firstCharacter!=null){
for (int j = 1; j < 3; j++) {
if (!firstCharacter.equals(board1.getSymbol(i,j))) {
rowComplete = false;
break;
}
}
}
if (rowComplete) {
return new GameState(true, firstCharacter);
}
}
boolean colComplete = true;
for (int i = 0; i < 3; i++) {
String firstCharacter = board1.getSymbol(0,i);
colComplete = firstCharacter!=null;
if(firstCharacter!=null){
for (int j = 1; j < 3; j++) {
if (!firstCharacter.equals(board1.getSymbol(j,i))) {
colComplete = false;
break;
}
}
}
if (colComplete) {
return new GameState(true, firstCharacter);
}
}

String firstCharacter = board1.getSymbol(0,0);
boolean diagonalComplete = firstCharacter!=null;
if(firstCharacter!=null){
for (int i = 1; i < 3; i++) {
if (!firstCharacter.equals(board1.getSymbol(i,i))) {
diagonalComplete = false;
break;
}
}
}
BiFunction<Integer,Integer,String> getRow = board1::getSymbol;
BiFunction<Integer,Integer,String> getCol = (i,j)->board1.getSymbol(j,i);
Function<Integer,String> getDiagonal = (i)->board1.getSymbol(i,i);
Function<Integer,String> getRevDiagonal = (i)->board1.getSymbol(i,3-i-1);

if (diagonalComplete) {
return new GameState(true, firstCharacter);
}
firstCharacter = board1.getSymbol(0,2);
boolean reverseDiagonalComplete = firstCharacter!=null;
if(firstCharacter!=null){
for (int i = 1; i < 3; i++) {
if (!firstCharacter.equals(board1.getSymbol(i ,3 - i - 1))) {
reverseDiagonalComplete = false;
break;
}
}
}
GameState rowWin = outerTraversal(getRow);
if(rowWin.isOver()) return rowWin;

if (reverseDiagonalComplete) {
return new GameState(true, firstCharacter);
}
GameState colWin = outerTraversal(getCol);
if(colWin.isOver()) return colWin;

GameState diagonalWin = traverse(getDiagonal);
if(diagonalWin.isOver()) return diagonalWin;

GameState reverseDiagonalWin = traverse(getRevDiagonal);
if(reverseDiagonalWin.isOver()) return reverseDiagonalWin;

int count=0;
for (int i = 0; i < 3; i++) {
Expand All @@ -87,4 +46,33 @@ public GameState getState(Board board){
return new GameState(true, "-");
}
}

public GameState outerTraversal(BiFunction<Integer, Integer,String> next){
GameState result = new GameState(false, "-");
for (int i = 0; i < 3; i++) {
int finalI = i;
Function<Integer,String> nextValue = (j) -> next.apply(finalI,j);
GameState traversal = traverse(nextValue);
if(traversal.isOver()) {
result = traversal;
break;
}
}
return result;
}

public GameState traverse(Function<Integer,String> next){
GameState result = new GameState(false, "-");
boolean possibleStreak = true;
for (int i = 0; i < 3; i++) {
if (next.apply(i)== null || !next.apply(0).equals(next.apply(i))) {
possibleStreak = false;
break;
}
}
if (possibleStreak) {
result = new GameState(true, next.apply(0));
}
return result;
}
}