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    }