/*********************************/ /* 知識を用いた探索(8パズル) */ /* coded by Y.Suganuma */ /*********************************/ import java.io.*; import java.util.*; class Depth { int dep, est; String prev; Depth (String str, int dep1, int est1) { prev = str; // 前の状態 dep = dep1; // 深さ est = est1; // 評価値 } } class Node { int dep, est; String str; Node (String str1, int dep1, int est1) { str = str1; // 状態 dep = dep1; // 深さ est = est1; // 評価値 } } class Comp implements Comparator <Node> { public int compare (Node n1, Node n2) { int sw = 0; if (n1.est == n2.est) { if (n1.dep == n2.dep) sw = n1.str.compareTo(n2.str); else sw = n1.dep - n2.dep; } else sw = n1.est - n2.est; return sw; } } class Search { /************************/ /* ノードの評価 */ /* dep : 深さ */ /* str : 状態 */ /* goal : 目標状態 */ /* return : 評価値 */ /************************/ int estimation(int dep, String str, String goal) { int i1, i2, i3, i4, k1, k2, pi = dep, sw; char at[], cg[][] = new char [3][3], cn[][] = new char [3][3]; at = goal.toCharArray(); for (i1 = 0; i1 < 9; i1++) { k1 = i1 / 3; k2 = i1 - 3 * k1; cg[k1][k2] = (char)(at[i1] - '0'); } at = str.toCharArray(); for (i1 = 0; i1 < 9; i1++) { k1 = i1 / 3; k2 = i1 - 3 * k1; cn[k1][k2] = (char)(at[i1] - '0'); } for (i1 = 0; i1 < 3; i1++) { for (i2 = 0; i2 < 3; i2++) { sw = 1; for (i3 = 0; i3 < 3 && sw > 0; i3++) { for (i4 = 0; i4 < 3 && sw > 0; i4++) { if (cg[i3][i4] == cn[i1][i2]) { sw = 0; pi += (Math.abs(i3-i1) + Math.abs(i4-i2)); } } } } } if (cn[1][1] != '0') pi++; if (cn[0][1] != (cn[0][0]+1)%9) pi += 2; if (cn[0][2] != (cn[0][1]+1)%9) pi += 2; if (cn[1][2] != (cn[0][2]+1)%9) pi += 2; if (cn[2][2] != (cn[1][2]+1)%9) pi += 2; if (cn[2][1] != (cn[2][2]+1)%9) pi += 2; if (cn[2][0] != (cn[2][1]+1)%9) pi += 2; if (cn[1][0] != (cn[2][0]+1)%9) pi += 2; if (cn[0][0] != (cn[1][0]+1)%9) pi += 2; return pi; } /********************************/ /* コマの移動 */ /* str : 現在の状態 */ /* res : 移動後の状態 */ /* return : 移動後の状態数 */ /********************************/ int move(String str, String res[]) { int k, n = 0; String str1; char c[] = new char [2]; k = str.indexOf('0'); switch(k) { case 0: c = str.substring(k+3,k+4).toCharArray(); str1 = str.replace('0', '9'); str1 = str1.replace(c[0],'0'); str1 = str1.replace('9', c[0]); res[n] = str1; n++; c = str.substring(k+1,k+2).toCharArray(); str1 = str.replace('0', '9'); str1 = str1.replace(c[0],'0'); str1 = str1.replace('9', c[0]); res[n] = str1; n++; break; case 1: c = str.substring(k+3,k+4).toCharArray(); str1 = str.replace('0', '9'); str1 = str1.replace(c[0],'0'); str1 = str1.replace('9', c[0]); res[n] = str1; n++; c = str.substring(k-1,k).toCharArray(); str1 = str.replace('0', '9'); str1 = str1.replace(c[0],'0'); str1 = str1.replace('9', c[0]); res[n] = str1; n++; c = str.substring(k+1,k+2).toCharArray(); str1 = str.replace('0', '9'); str1 = str1.replace(c[0],'0'); str1 = str1.replace('9', c[0]); res[n] = str1; n++; break; case 2: c = str.substring(k+3,k+4).toCharArray(); str1 = str.replace('0', '9'); str1 = str1.replace(c[0],'0'); str1 = str1.replace('9', c[0]); res[n] = str1; n++; c = str.substring(k-1,k).toCharArray(); str1 = str.replace('0', '9'); str1 = str1.replace(c[0],'0'); str1 = str1.replace('9', c[0]); res[n] = str1; n++; break; case 3: c = str.substring(k-3,k-2).toCharArray(); str1 = str.replace('0', '9'); str1 = str1.replace(c[0],'0'); str1 = str1.replace('9', c[0]); res[n] = str1; n++; c = str.substring(k+3,k+4).toCharArray(); str1 = str.replace('0', '9'); str1 = str1.replace(c[0],'0'); str1 = str1.replace('9', c[0]); res[n] = str1; n++; c = str.substring(k+1,k+2).toCharArray(); str1 = str.replace('0', '9'); str1 = str1.replace(c[0],'0'); str1 = str1.replace('9', c[0]); res[n] = str1; n++; break; case 4: c = str.substring(k-3,k-2).toCharArray(); str1 = str.replace('0', '9'); str1 = str1.replace(c[0],'0'); str1 = str1.replace('9', c[0]); res[n] = str1; n++; c = str.substring(k+3,k+4).toCharArray(); str1 = str.replace('0', '9'); str1 = str1.replace(c[0],'0'); str1 = str1.replace('9', c[0]); res[n] = str1; n++; c = str.substring(k-1,k).toCharArray(); str1 = str.replace('0', '9'); str1 = str1.replace(c[0],'0'); str1 = str1.replace('9', c[0]); res[n] = str1; n++; c = str.substring(k+1,k+2).toCharArray(); str1 = str.replace('0', '9'); str1 = str1.replace(c[0],'0'); str1 = str1.replace('9', c[0]); res[n] = str1; n++; break; case 5: c = str.substring(k-3,k-2).toCharArray(); str1 = str.replace('0', '9'); str1 = str1.replace(c[0],'0'); str1 = str1.replace('9', c[0]); res[n] = str1; n++; c = str.substring(k+3,k+4).toCharArray(); str1 = str.replace('0', '9'); str1 = str1.replace(c[0],'0'); str1 = str1.replace('9', c[0]); res[n] = str1; n++; c = str.substring(k-1,k).toCharArray(); str1 = str.replace('0', '9'); str1 = str1.replace(c[0],'0'); str1 = str1.replace('9', c[0]); res[n] = str1; n++; break; case 6: c = str.substring(k-3,k-2).toCharArray(); str1 = str.replace('0', '9'); str1 = str1.replace(c[0],'0'); str1 = str1.replace('9', c[0]); res[n] = str1; n++; c = str.substring(k+1,k+2).toCharArray(); str1 = str.replace('0', '9'); str1 = str1.replace(c[0],'0'); str1 = str1.replace('9', c[0]); res[n] = str1; n++; break; case 7: c = str.substring(k-3,k-2).toCharArray(); str1 = str.replace('0', '9'); str1 = str1.replace(c[0],'0'); str1 = str1.replace('9', c[0]); res[n] = str1; n++; c = str.substring(k-1,k).toCharArray(); str1 = str.replace('0', '9'); str1 = str1.replace(c[0],'0'); str1 = str1.replace('9', c[0]); res[n] = str1; n++; c = str.substring(k+1,k+2).toCharArray(); str1 = str.replace('0', '9'); str1 = str1.replace(c[0],'0'); str1 = str1.replace('9', c[0]); res[n] = str1; n++; break; case 8: c = str.substring(k-3,k-2).toCharArray(); str1 = str.replace('0', '9'); str1 = str1.replace(c[0],'0'); str1 = str1.replace('9', c[0]); res[n] = str1; n++; c = str.substring(k-1,k).toCharArray(); str1 = str.replace('0', '9'); str1 = str1.replace(c[0],'0'); str1 = str1.replace('9', c[0]); res[n] = str1; n++; break; } return n; } /********************************/ /* 知識を用いた探索(8パズル) */ /* start : 初期状態 */ /* goal : 目標状態 */ /********************************/ void intel(String start, String goal) { int i1, n, node1 = 1, node2 = 0, dep = 1, ct = 1, est; char at[] = new char [10]; boolean sw; String str = "", res[] = new String [4]; Node nd; Comparator<Node> cp = new Comp(); PriorityQueue <Node> p = new PriorityQueue <Node> (1, cp); TreeMap<String, Depth> m = new TreeMap<String, Depth> (); est = estimation(dep, start, goal); m.put(start, new Depth("",dep,est)); p.add(new Node(start, dep, est)); while (!p.isEmpty()) { nd = p.poll(); str = nd.str; dep = nd.dep; node2++; // ゴール if (str.compareTo(goal) == 0) { ct = dep; break; } // ゴールでない // コマを移動し,同じ状態のものがなければキューに追加 else { n = move(str, res); for (i1 = 0; i1 < n; i1++) { sw = true; est = estimation(dep+1, res[i1], goal); if (m.containsKey(res[i1])) { if (est < m.ceilingEntry(res[i1]).getValue().est) m.remove(res[i1]); else sw = false; } if (sw) { m.put(res[i1], new Depth(str,dep+1,est)); p.add(new Node(res[i1], dep+1, est)); node1++; } } } } // 結果の出力 System.out.printf(" 展開とチェック: %d %d, 最短距離: %d\n", node1, node2, ct); while (str.length() > 0) { at = str.toCharArray(); System.out.printf("\n %c %c %c\n", at[0], at[1], at[2]); System.out.printf(" %c %c %c\n", at[3], at[4], at[5]); System.out.printf(" %c %c %c\n", at[6], at[7], at[8]); str = m.ceilingEntry(str).getValue().prev; } } } public class Test { public static void main (String[] args) { String goal = "123804765"; Search ss = new Search(); System.out.printf("例1\n"); String start = "283164705"; ss.intel(start, goal); System.out.printf("例2\n"); start = "216408753"; ss.intel(start, goal); } }