import java.util.*; class Node { int[] state = new int[9]; int cost; Node parent = null; Vector<Node> successors = new Vector<Node>(); Node(int s[], Node parent) { this.parent = parent; for (int i = 0; i < 9; i++) state[i] = s[i]; } public String toString() { String s = ""; for (int i = 0; i < 9; i++) { s = s + state[i] + " "; } return s; }
public boolean equals(Node n) { boolean result = true; for (int i = 0; i < 9; i++) { if (n.state[i] != state[i]) result = false; } return result; } Vector<Node> getPath(Vector<Node> v) { v.insertElementAt(this, 0); if (parent != null) v = parent.getPath(v); return v; } Vector<Node> getPath() { return getPath(new Vector<Node>()); } }
class EightPuzzleSpace { Node getRoot() { int ex[] = {3, 1, 2, 4, 7, 5, 6, 8, 0}; int rn[] = {7, 2, 4, 5, 0, 6, 8, 3, 1}; // the Russell and Norvig eg return new Node(ex, null); } Node getGoal() { int state[] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; return new Node(state, null); } Node transformState(int r0, int c0, int r1, int c1, Node parent) { int[] s = parent.state; int[] newState = {s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[8]}; newState[(r1 * 3) + c1] = s[(r0 * 3) + c0]; newState[(r0 * 3) + c0] = 0; return new Node(newState, parent); }
Vector<Node> getSuccessors(Node parent) { Vector<Node> successors = new Vector<Node>(); for (int r = 0; r < 3; r++) { for (int c = 0; c < 3; c++) { if (parent.state[(r * 3) + c] == 0) { /* hole here */ if (r > 0) { /* move tile from left */ successors.add(transformState(r-1, c, r, c, parent)); } if (r < 2) { /* move tile from right */ successors.add(transformState(r+1, c, r, c, parent)); } if (c > 0) { /* move tile from below */ successors.add(transformState(r, c-1, r, c, parent)); } if (c < 2) { /* move tile from above */ successors.add(transformState(r, c+1, r, c, parent)); } } } } parent.successors = successors; /* used in getTree */ return successors; } }
public class EightPuzzleSearch { EightPuzzleSpace space = new EightPuzzleSpace(); Vector<Node> open = new Vector<Node>(); Vector<Node> closed = new Vector<Node>(); int h1Cost(Node node) { int cost = 0; for (int i = 0; i < node.state.length; i++) { if (node.state[i] != i) cost++; } return cost; }
int h2Cost(Node node) { int cost = 0; int state[] = node.state; for (int i = 0; i < state.length; i++) { int v0 = i, v1 = state[i]; if (v1 == 0) continue; /* don't count the hole */ int row0 = v0 / 3, col0 = v0 % 3, row1 = v1 / 3, col1 = v1 % 3; int c = (Math.abs(row0 - row1) + Math.abs(col0 - col1)); cost += c; } return cost; } int hCost(Node node) { /* set to call either h1 or h2 */ return h2Cost(node); }
Node getBestNode(Vector nodes) { int index = 0, minCost = Integer.MAX_VALUE; for (int i = 0; i < nodes.size(); i++) { Node node = (Node)nodes.elementAt(i); if (node.cost < minCost) { minCost = node.cost; index = i; } } Node bestNode = (Node)nodes.remove(index); return(bestNode); }
Node getUniqueNode(Node node) { int i = open.indexOf(node); if (i != -1) { node = open.get(i); } else if ((i = closed.indexOf(node)) != -1) { node = closed.get(i); } return(node); }
void printPath(Vector path) { for (int i = 0; i < path.size(); i++) { System.out.print(" " + path.elementAt(i) + "\n"); } }
void run() { Node root = space.getRoot(); Node goal = space.getGoal(); Node solution = null; open.add(root); System.out.print("\nRoot: " + root + "\n\n");
while (open.size() > 0) { Node node = getBestNode(open); int pathLength = node.getPath().size(); closed.add(node); if (node.equals(goal)) { solution = node; break; } Vector<Node> successors = space.getSuccessors(node); for (int i = 0; i < successors.size(); i++) { Node successor = getUniqueNode(successors.get(i)); int cost = hCost(successor) + pathLength + 1; int previousCost = successor.cost; boolean inClosed = closed.contains(successor); boolean inOpen = open.contains(successor); if (!(inClosed || inOpen) || cost < previousCost) { if (inClosed) closed.remove(successor); if (!inOpen) open.add(successor); successor.cost = cost; successor.parent = node; } } }
// new TreePrint(getTree(root)); if (solution != null) { Vector path = solution.getPath(); System.out.print("\nSolution found\n"); printPath(path); } } public static void main(String args[]) { // do the search new EightPuzzleSearch().run(); } }
Root: 3 1 2 4 7 5 6 8 0 3 1 2 4 7 5 6 8 0 |-- 3 1 2 4 7 0 6 8 5 |-- 3 1 2 4 7 5 6 0 8 |-- 3 1 2 4 0 5 6 7 8 | |-- 3 0 2 4 1 5 6 7 8 | |-- 3 1 2 4 7 5 6 0 8 | |-- 3 1 2 0 4 5 6 7 8 | | |-- 0 1 2 3 4 5 6 7 8 | | |-- 3 1 2 6 4 5 0 7 8 | | |-- 3 1 2 4 0 5 6 7 8 | |-- 3 1 2 4 5 0 6 7 8 |-- 3 1 2 4 7 5 0 6 8 |-- 3 1 2 4 7 5 6 8 0
3 1 2 4 7 5 6 8 0 3 1 2 4 7 5 6 0 8 3 1 2 4 0 5 6 7 8 3 1 2 0 4 5 6 7 8 0 1 2 3 4 5 6 7 8.