001 /* 002 * Created on Feb 15, 2005 003 * 004 */ 005 package aima.games; 006 007 import java.util.ArrayList; 008 009 import aima.basic.XYLocation; 010 011 /** 012 * @author Ravi Mohan 013 * 014 */ 015 public class TicTacToe extends Game { 016 public TicTacToe() { 017 ArrayList<XYLocation> moves = new ArrayList<XYLocation>(); 018 for (int i = 0; i < 3; i++) { 019 for (int j = 0; j < 3; j++) { 020 XYLocation loc = new XYLocation(i, j); 021 moves.add(loc); 022 } 023 } 024 initialState.put("moves", moves); 025 initialState.put("player", "X"); 026 initialState.put("utility", new Integer(0)); 027 initialState.put("board", new TicTacToeBoard()); 028 initialState.put("level", new Integer(0)); 029 presentState = initialState; 030 } 031 032 public TicTacToeBoard getBoard(GameState state) { 033 034 return (TicTacToeBoard) state.get("board"); 035 } 036 037 @Override 038 public ArrayList getSuccessorStates(GameState state) { 039 GameState temp = presentState; 040 ArrayList<Object> retVal = new ArrayList<Object>(); 041 int parentLevel = getLevel(state); 042 for (int i = 0; i < getMoves(state).size(); i++) { 043 XYLocation loc = (XYLocation) getMoves(state).get(i); 044 045 GameState aState = makeMove(state, loc); 046 aState.put("moveMade", loc); 047 aState.put("level", new Integer(parentLevel + 1)); 048 retVal.add(aState); 049 050 } 051 presentState = temp; 052 return retVal; 053 } 054 055 @Override 056 public GameState makeMove(GameState state, Object o) { 057 XYLocation loc = (XYLocation) o; 058 return makeMove(state, loc.getXCoOrdinate(), loc.getYCoOrdinate()); 059 } 060 061 public GameState makeMove(GameState state, int x, int y) { 062 GameState temp = getMove(state, x, y); 063 if (temp != null) { 064 presentState = temp; 065 } 066 return presentState; 067 } 068 069 public GameState makeMove(int x, int y) { 070 GameState state = presentState; 071 GameState temp = getMove(state, x, y); 072 if (temp != null) { 073 presentState = temp; 074 } 075 return presentState; 076 } 077 078 public GameState getMove(GameState state, int x, int y) { 079 GameState retVal = null; 080 XYLocation loc = new XYLocation(x, y); 081 ArrayList moves = getMoves(state); 082 ArrayList newMoves = (ArrayList) moves.clone(); 083 if (moves.contains(loc)) { 084 int index = newMoves.indexOf(loc); 085 newMoves.remove(index); 086 087 retVal = new GameState(); 088 089 retVal.put("moves", newMoves); 090 TicTacToeBoard newBoard = getBoard(state).cloneBoard(); 091 if (getPlayerToMove(state) == "X") { 092 newBoard.markX(x, y); 093 retVal.put("player", "O"); 094 095 } else { 096 newBoard.markO(x, y); 097 retVal.put("player", "X"); 098 099 } 100 retVal.put("board", newBoard); 101 retVal.put("utility", new Integer(computeUtility(newBoard, 102 getPlayerToMove(getState())))); 103 retVal.put("level", new Integer(getLevel(state) + 1)); 104 // presentState = retVal; 105 } 106 return retVal; 107 } 108 109 @Override 110 public int computeUtility(GameState state) { 111 int utility = computeUtility((TicTacToeBoard) state.get("board"), 112 (getPlayerToMove(state))); 113 return utility; 114 } 115 116 private int computeUtility(TicTacToeBoard aBoard, String playerToMove) { 117 int retVal = 0; 118 if (aBoard.lineThroughBoard()) { 119 if (playerToMove.equals("X")) { 120 retVal = -1; 121 } else { 122 retVal = 1; 123 } 124 125 } 126 return retVal; 127 } 128 129 @Override 130 public boolean terminalTest(GameState state) { 131 TicTacToeBoard board = (TicTacToeBoard) state.get("board"); 132 boolean line = board.lineThroughBoard(); 133 boolean filled = board.getNumberOfMarkedPositions() == 9; 134 return (line || filled); 135 } 136 137 public void printPossibleMoves() { 138 System.out.println("Possible moves"); 139 140 ArrayList moves = getMoves(presentState); 141 for (int i = 0; i < moves.size(); i++) { 142 XYLocation moveLoc = (XYLocation) moves.get(i); 143 GameState newState = getMove(presentState, 144 moveLoc.getXCoOrdinate(), moveLoc.getYCoOrdinate()); 145 TicTacToeBoard board = (TicTacToeBoard) newState.get("board"); 146 System.out.println("utility = " + computeUtility(newState)); 147 System.out.println(""); 148 } 149 150 } 151 152 @Override 153 public int getMiniMaxValue(GameState state) { 154 // statesSeen = new ArrayList(); 155 // System.out.println("In get Minimax Value"); 156 // System.out.println("Received state "); 157 // ((TicTacToeBoard)state.get("board")).print(); 158 if (getPlayerToMove(state).equalsIgnoreCase("X")) { 159 return maxValue(state); 160 161 } else { 162 return minValue(state); 163 } 164 } 165 166 @Override 167 public int getAlphaBetaValue(GameState state) { 168 169 if (getPlayerToMove(state).equalsIgnoreCase("X")) { 170 AlphaBeta initial = new AlphaBeta(Integer.MIN_VALUE, 171 Integer.MAX_VALUE); 172 int max = maxValue(state, initial); 173 return max; 174 175 } else { 176 // invert? 177 AlphaBeta initial = new AlphaBeta(Integer.MIN_VALUE, 178 Integer.MAX_VALUE); 179 return minValue(state, initial); 180 } 181 } 182 }