From 448e7fd1453be55ff462eb50c5fff407c7a5d16a Mon Sep 17 00:00:00 2001 From: Sufyan Date: Tue, 25 Feb 2025 01:10:45 +0530 Subject: [PATCH] SUF-11 Good Engineer1: Adding the Rules inside the ruleset : Making rules extensible for different boards --- api/Rule.java | 13 ++++++++ api/RuleEngine.java | 67 +++----------------------------------- api/RuleSet.java | 24 ++++++++++++++ boards/TicTacToeBoard.java | 61 ++++++++++++++++++++++++++++++++++ 4 files changed, 102 insertions(+), 63 deletions(-) create mode 100644 api/Rule.java create mode 100644 api/RuleSet.java diff --git a/api/Rule.java b/api/Rule.java new file mode 100644 index 0000000..eb320e2 --- /dev/null +++ b/api/Rule.java @@ -0,0 +1,13 @@ +package api; + +import game.Board; +import game.GameState; + +import java.util.function.Function; + +public class Rule { + Function condition; + public Rule(Function condition){ + this.condition = condition; + } +} diff --git a/api/RuleEngine.java b/api/RuleEngine.java index 2f2113f..1e8797d 100644 --- a/api/RuleEngine.java +++ b/api/RuleEngine.java @@ -12,24 +12,16 @@ import java.util.function.Function; public class RuleEngine { - Map>> ruleMap = new HashMap<>(); + Map> ruleMap = new HashMap<>(); public RuleEngine(){ - String name = TicTacToeBoard.class.getName(); - ruleMap.put(name,new ArrayList<>()); - // Rules - ruleMap.get(name).add(new Rule<> ((board)->outerTraversal(board::getSymbol))); - ruleMap.get(name).add(new Rule<> ((board)->outerTraversal((i,j)-> board.getSymbol(j,i)))); - ruleMap.get(name).add(new Rule<> ((board)->traverse((i)-> board.getSymbol(i,i)))); - ruleMap.get(name).add(new Rule<> ((board)->traverse((i)-> board.getSymbol(i,2-i)))); - ruleMap.get(name).add(new Rule<> (this::countMoves)); - + ruleMap.put(TicTacToeBoard.class.getName(),TicTacToeBoard.getRules()); } public GameState getState(Board board){ if(board instanceof TicTacToeBoard board1) { - List>rules = ruleMap.get(TicTacToeBoard.class.getName()); - for(Rule rule:rules){ + RuleSet rules = (RuleSet) ruleMap.get(TicTacToeBoard.class.getName()); + for(Rule rule: rules){ GameState gameState = rule.condition.apply(board1); if(gameState.isOver()){ return gameState; @@ -40,57 +32,6 @@ public GameState getState(Board board){ return new GameState(true, "-"); } } - - public GameState countMoves (TicTacToeBoard board1){ - int count=0; - GameState gameState = new GameState(false, "-"); - for (int i = 0; i < 3; i++) { - for (int j = 0; j < 3; j++) { - if (board1.getSymbol(i,j)!=null){ - count ++; - } - } - } - if(count == 9){ - gameState = new GameState(true,"-"); - } - return gameState; - } - - public GameState outerTraversal(BiFunction next){ - GameState result = new GameState(false, "-"); - for (int i = 0; i < 3; i++) { - int finalI = i; - Function nextValue = (j) -> next.apply(finalI,j); - GameState traversal = traverse(nextValue); - if(traversal.isOver()) { - result = traversal; - break; - } - } - return result; - } - - public GameState traverse(Function 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; - } } -class Rule { - Function condition; - Rule(Function condition){ - this.condition = condition; - } -} diff --git a/api/RuleSet.java b/api/RuleSet.java new file mode 100644 index 0000000..4ae7b8e --- /dev/null +++ b/api/RuleSet.java @@ -0,0 +1,24 @@ +package api; + +import game.Board; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class RuleSet implements Iterable>{ + List> rules = new ArrayList<>(); + /** + * Returns an iterator over elements of type {@code T}. + * + * @return an Iterator. + */ + @Override + public Iterator> iterator() { + return rules.iterator(); + } + + public void add (Rule rule){ + rules.add(rule); + } +} diff --git a/boards/TicTacToeBoard.java b/boards/TicTacToeBoard.java index 35c2855..5805bb8 100644 --- a/boards/TicTacToeBoard.java +++ b/boards/TicTacToeBoard.java @@ -1,10 +1,15 @@ package boards; +import api.Rule; +import api.RuleSet; import game.Board; import game.Cell; +import game.GameState; import game.Move; import java.util.Arrays; +import java.util.function.BiFunction; +import java.util.function.Function; public class TicTacToeBoard implements Board, Cloneable { String[][] cells = new String[3][3]; @@ -29,6 +34,15 @@ public void setCell(Cell cell, String symbol) { } } + public static RuleSet getRules(){ + RuleSet rules = new RuleSet<>(); + rules.add(new Rule<>((board)->outerTraversal(board::getSymbol))); + rules.add(new Rule<> ((board)->outerTraversal((i,j)-> board.getSymbol(j,i)))); + rules.add(new Rule<> ((board)->traverse((i)-> board.getSymbol(i,i)))); + rules.add(new Rule<> ((board)->traverse((i)-> board.getSymbol(i,2-i)))); + rules.add(new Rule<> (TicTacToeBoard::countMoves)); + return rules; + } @Override public void move(Move move){ setCell(move.getCell(),move.getPlayer().symbol()); @@ -51,4 +65,51 @@ public String toString(){ public TicTacToeBoard clone() { return new TicTacToeBoard(this); } + + + public static GameState countMoves(TicTacToeBoard board1){ + int count=0; + GameState gameState = new GameState(false, "-"); + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + if (board1.getSymbol(i,j)!=null){ + count ++; + } + } + } + if(count == 9){ + gameState = new GameState(true,"-"); + } + return gameState; + } + + public static GameState outerTraversal(BiFunction next){ + GameState result = new GameState(false, "-"); + for (int i = 0; i < 3; i++) { + int finalI = i; + Function nextValue = (j) -> next.apply(finalI,j); + GameState traversal = traverse(nextValue); + if(traversal.isOver()) { + result = traversal; + break; + } + } + return result; + } + + public static GameState traverse(Function 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; + } + }