001 package aima.search.eightpuzzle; 002 003 import java.util.ArrayList; 004 import java.util.List; 005 006 import aima.basic.XYLocation; 007 008 /** 009 * @author Ravi Mohan 010 * 011 */ 012 013 public class EightPuzzleBoard { 014 015 public static String LEFT = "Left"; 016 017 public static String RIGHT = "Right"; 018 019 public static String UP = "Up"; 020 021 public static String DOWN = "Down"; 022 023 public int[] getBoard() { 024 return board; 025 } 026 027 int[] board; 028 029 public EightPuzzleBoard() { 030 board = new int[] { 5, 4, 0, 6, 1, 8, 7, 3, 2 }; 031 032 } 033 034 public EightPuzzleBoard(int[] aBoard) { 035 board = aBoard; 036 } 037 038 private int[] xycoordinatesFromAbsoluteCoordinate(int x) { 039 int[] retVal = null; 040 switch (x) { 041 case 0: 042 retVal = new int[] { 0, 0 }; 043 break; 044 case 1: 045 retVal = new int[] { 0, 1 }; 046 break; 047 case 2: 048 retVal = new int[] { 0, 2 }; 049 break; 050 case 3: 051 retVal = new int[] { 1, 0 }; 052 break; 053 case 4: 054 retVal = new int[] { 1, 1 }; 055 break; 056 case 5: 057 retVal = new int[] { 1, 2 }; 058 break; 059 case 6: 060 retVal = new int[] { 2, 0 }; 061 break; 062 case 7: 063 retVal = new int[] { 2, 1 }; 064 break; 065 case 8: 066 retVal = new int[] { 2, 2 }; 067 break; 068 069 } 070 return retVal; 071 } 072 073 private int absoluteCoordinatesFromXYCoordinates(int x, int y) { 074 return x * 3 + y; 075 } 076 077 private int getValueAt(int x, int y) { 078 // refactor this use either case or a div/mod soln 079 return board[absoluteCoordinatesFromXYCoordinates(x, y)]; 080 } 081 082 private int getGapPosition() { 083 084 return getPositionOf(0); 085 } 086 087 private int getPositionOf(int val) { 088 int retVal = -1; 089 for (int i = 0; i < 9; i++) { 090 if (board[i] == val) { 091 retVal = i; 092 } 093 } 094 return retVal; 095 } 096 097 public XYLocation getLocationOf(int val) { 098 int abspos = getPositionOf(val); 099 int xpos = xycoordinatesFromAbsoluteCoordinate(abspos)[0]; 100 int ypos = xycoordinatesFromAbsoluteCoordinate(abspos)[1]; 101 return new XYLocation(xpos, ypos); 102 } 103 104 private void setValue(int xPos, int yPos, int val) { 105 int abscoord = absoluteCoordinatesFromXYCoordinates(xPos, yPos); 106 board[abscoord] = val; 107 108 } 109 110 public int getValueAt(XYLocation loc) { 111 return getValueAt(loc.getXCoOrdinate(), loc.getYCoOrdinate()); 112 } 113 114 public void moveGapRight() { 115 int gapPosition = getGapPosition(); 116 int xpos = xycoordinatesFromAbsoluteCoordinate(gapPosition)[0]; 117 int ypos = xycoordinatesFromAbsoluteCoordinate(gapPosition)[1]; 118 if (!(ypos == 2)) { 119 int valueOnRight = getValueAt(xpos, ypos + 1); 120 setValue(xpos, ypos, valueOnRight); 121 setValue(xpos, ypos + 1, 0); 122 } 123 124 } 125 126 public void moveGapLeft() { 127 int gapPosition = getGapPosition(); 128 int xpos = xycoordinatesFromAbsoluteCoordinate(gapPosition)[0]; 129 int ypos = xycoordinatesFromAbsoluteCoordinate(getGapPosition())[1]; 130 if (!(ypos == 0)) { 131 int valueOnLeft = getValueAt(xpos, ypos - 1); 132 setValue(xpos, ypos, valueOnLeft); 133 setValue(xpos, ypos - 1, 0); 134 } 135 136 } 137 138 public void moveGapDown() { 139 int gapPosition = getGapPosition(); 140 int xpos = xycoordinatesFromAbsoluteCoordinate(gapPosition)[0]; 141 int ypos = xycoordinatesFromAbsoluteCoordinate(gapPosition)[1]; 142 if (!(xpos == 2)) { 143 int valueOnBottom = getValueAt(xpos + 1, ypos); 144 setValue(xpos, ypos, valueOnBottom); 145 setValue(xpos + 1, ypos, 0); 146 } 147 148 } 149 150 public void moveGapUp() { 151 int gapPosition = getGapPosition(); 152 int xpos = xycoordinatesFromAbsoluteCoordinate(gapPosition)[0]; 153 int ypos = xycoordinatesFromAbsoluteCoordinate(gapPosition)[1]; 154 if (!(xpos == 0)) { 155 int valueOnTop = getValueAt(xpos - 1, ypos); 156 setValue(xpos, ypos, valueOnTop); 157 setValue(xpos - 1, ypos, 0); 158 } 159 160 } 161 162 @Override 163 public boolean equals(Object o) { 164 165 if (this == o) { 166 return true; 167 } 168 if ((o == null) || (this.getClass() != o.getClass())) { 169 return false; 170 } 171 EightPuzzleBoard aBoard = (EightPuzzleBoard) o; 172 173 for (int i = 0; i < 8; i++) { 174 if (this.getPositionOf(i) != aBoard.getPositionOf(i)) { 175 return false; 176 } 177 } 178 return true; 179 } 180 181 @Override 182 public int hashCode() { 183 int result = 17; 184 for (int i = 0; i < 8; i++) { 185 int position = this.getPositionOf(i); 186 result = 37 * result + position; 187 } 188 return result; 189 } 190 191 public List<XYLocation> getPositions() { 192 ArrayList<XYLocation> retVal = new ArrayList<XYLocation>(); 193 for (int i = 0; i < 9; i++) { 194 int[] res = xycoordinatesFromAbsoluteCoordinate(getPositionOf(i)); 195 XYLocation loc = new XYLocation(res[0], res[1]); 196 retVal.add(loc); 197 198 } 199 return retVal; 200 } 201 202 public void setBoard(List<XYLocation> locs) { 203 204 int count = 0; 205 206 for (int i = 0; i < locs.size(); i++) { 207 XYLocation loc = locs.get(i); 208 this.setValue(loc.getXCoOrdinate(), loc.getYCoOrdinate(), count); 209 count = count + 1; 210 } 211 } 212 213 public boolean canMoveGap(String where) { 214 boolean retVal = true; 215 int absPos = getPositionOf(0); 216 if (where.equals(LEFT)) { 217 if ((absPos == 0) || (absPos == 3) || (absPos == 6)) { 218 retVal = false; 219 } 220 } 221 if (where.equals(RIGHT)) { 222 if ((absPos == 2) || (absPos == 5) || (absPos == 8)) { 223 retVal = false; 224 } 225 } 226 if (where.equals(UP)) { 227 if ((absPos == 0) || (absPos == 1) || (absPos == 2)) { 228 retVal = false; 229 } 230 } 231 if (where.equals(DOWN)) { 232 if ((absPos == 6) || (absPos == 7) || (absPos == 8)) { 233 retVal = false; 234 } 235 } 236 237 return retVal; 238 } 239 240 @Override 241 public String toString() { 242 String retVal = board[0] + " " + board[1] + " " + board[2] + "\n" 243 + board[3] + " " + board[4] + " " + board[5] + " " + "\n" 244 + board[6] + " " + board[7] + " " + board[8]; 245 return retVal; 246 } 247 248 }