aima.core.environment.eightpuzzle.EightPuzzleBoard Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aima-core Show documentation
Show all versions of aima-core Show documentation
AIMA-Java Core Algorithms from the book Artificial Intelligence a Modern Approach 3rd Ed.
package aima.core.environment.eightpuzzle;
import java.util.ArrayList;
import java.util.List;
import aima.core.agent.Action;
import aima.core.agent.impl.DynamicAction;
import aima.core.util.datastructure.XYLocation;
/**
* @author Ravi Mohan
* @author R. Lunde
*/
public class EightPuzzleBoard {
public static Action LEFT = new DynamicAction("Left");
public static Action RIGHT = new DynamicAction("Right");
public static Action UP = new DynamicAction("Up");
public static Action DOWN = new DynamicAction("Down");
private int[] state;
//
// PUBLIC METHODS
//
public EightPuzzleBoard() {
state = new int[] { 5, 4, 0, 6, 1, 8, 7, 3, 2 };
}
public EightPuzzleBoard(int[] state) {
this.state = new int[state.length];
System.arraycopy(state, 0, this.state, 0, state.length);
}
public EightPuzzleBoard(EightPuzzleBoard copyBoard) {
this(copyBoard.getState());
}
public int[] getState() {
return state;
}
public int getValueAt(XYLocation loc) {
return getValueAt(loc.getXCoOrdinate(), loc.getYCoOrdinate());
}
public XYLocation getLocationOf(int val) {
int absPos = getPositionOf(val);
return new XYLocation(getXCoord(absPos), getYCoord(absPos));
}
public void moveGapRight() {
int gapPos = getGapPosition();
int x = getXCoord(gapPos);
int ypos = getYCoord(gapPos);
if (!(ypos == 2)) {
int valueOnRight = getValueAt(x, ypos + 1);
setValue(x, ypos, valueOnRight);
setValue(x, ypos + 1, 0);
}
}
public void moveGapLeft() {
int gapPos = getGapPosition();
int x = getXCoord(gapPos);
int ypos = getYCoord(gapPos);
if (!(ypos == 0)) {
int valueOnLeft = getValueAt(x, ypos - 1);
setValue(x, ypos, valueOnLeft);
setValue(x, ypos - 1, 0);
}
}
public void moveGapDown() {
int gapPos = getGapPosition();
int x = getXCoord(gapPos);
int y = getYCoord(gapPos);
if (!(x == 2)) {
int valueOnBottom = getValueAt(x + 1, y);
setValue(x, y, valueOnBottom);
setValue(x + 1, y, 0);
}
}
public void moveGapUp() {
int gapPos = getGapPosition();
int x = getXCoord(gapPos);
int y = getYCoord(gapPos);
if (!(x == 0)) {
int valueOnTop = getValueAt(x - 1, y);
setValue(x, y, valueOnTop);
setValue(x - 1, y, 0);
}
}
public List getPositions() {
ArrayList retVal = new ArrayList();
for (int i = 0; i < 9; i++) {
int absPos = getPositionOf(i);
XYLocation loc = new XYLocation(getXCoord(absPos),
getYCoord(absPos));
retVal.add(loc);
}
return retVal;
}
public void setBoard(List locs) {
int count = 0;
for (int i = 0; i < locs.size(); i++) {
XYLocation loc = locs.get(i);
this.setValue(loc.getXCoOrdinate(), loc.getYCoOrdinate(), count);
count = count + 1;
}
}
public boolean canMoveGap(Action where) {
boolean retVal = true;
int absPos = getPositionOf(0);
if (where.equals(LEFT))
retVal = (getYCoord(absPos) != 0);
else if (where.equals(RIGHT))
retVal = (getYCoord(absPos) != 2);
else if (where.equals(UP))
retVal = (getXCoord(absPos) != 0);
else if (where.equals(DOWN))
retVal = (getXCoord(absPos) != 2);
return retVal;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if ((o == null) || (this.getClass() != o.getClass())) {
return false;
}
EightPuzzleBoard aBoard = (EightPuzzleBoard) o;
for (int i = 0; i < 8; i++) {
if (this.getPositionOf(i) != aBoard.getPositionOf(i)) {
return false;
}
}
return true;
}
@Override
public int hashCode() {
int result = 17;
for (int i = 0; i < 8; i++) {
int position = this.getPositionOf(i);
result = 37 * result + position;
}
return result;
}
@Override
public String toString() {
String retVal = state[0] + " " + state[1] + " " + state[2] + "\n"
+ state[3] + " " + state[4] + " " + state[5] + " " + "\n"
+ state[6] + " " + state[7] + " " + state[8];
return retVal;
}
//
// PRIVATE METHODS
//
/**
* Note: The graphic representation maps x values on row numbers (x-axis in
* vertical direction).
*/
private int getXCoord(int absPos) {
return absPos / 3;
}
/**
* Note: The graphic representation maps y values on column numbers (y-axis
* in horizontal direction).
*/
private int getYCoord(int absPos) {
return absPos % 3;
}
private int getAbsPosition(int x, int y) {
return x * 3 + y;
}
private int getValueAt(int x, int y) {
// refactor this use either case or a div/mod soln
return state[getAbsPosition(x, y)];
}
private int getGapPosition() {
return getPositionOf(0);
}
private int getPositionOf(int val) {
int retVal = -1;
for (int i = 0; i < 9; i++) {
if (state[i] == val) {
retVal = i;
}
}
return retVal;
}
private void setValue(int x, int y, int val) {
int absPos = getAbsPosition(x, y);
state[absPos] = val;
}
}