縦型探索(8パズル)

/*********************************/
/* 縦型探索(8パズル)          */
/*           coded by Y.Suganuma */
/*********************************/
import java.io.*;
import java.util.*;

class Depth
{
	int dep;
	String prev;
	Depth (String str, int dep1)
	{
		prev = str;   // 前の状態
		dep  = dep1;   // 深さ
	}
}

class Pair
{
	String str;
	int dep;
	Pair (String str1, int dep1)
	{
		str = str1;   // 状態
		dep = dep1;   // 深さ
	}
}

class Search
{
	/********************************/
	/* コマの移動                   */
	/*      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 : 目標状態  */
	/*      max : 最大深さ   */
	/*************************/
	void depth(String start, String goal, int max)
	{
		int i1, n, node1 = 1, node2 = 0, dep = 1, ct = 1;
		char at[] = new char [10];
		boolean sw;
		String str = "", res[] = new String [4];
		Pair pair;
		Stack <Pair> s = new Stack <Pair> ();
		TreeMap<String, Depth> m = new TreeMap<String, Depth> ();

		m.put(start, new Depth("",dep));
		s.add(new Pair(start, dep));
		while (!s.isEmpty()) {
			pair = s.pop();
			str  = pair.str;
			dep  = pair.dep;
			node2++;
					// ゴール
			if (str.compareTo(goal) == 0) {
				ct = dep;
				break;
			}
					// ゴールでない
					// コマを移動し,同じ状態のものがなければキューに追加
			else {
				if (dep < max) {
					n = move(str, res);
					for (i1 = 0; i1 < n; i1++) {
						sw = true;
						if (m.containsKey(res[i1])) {
							if (dep+1 < m.ceilingEntry(res[i1]).getValue().dep)
								m.remove(res[i1]);
							else
								sw = false;
						}
						if (sw) {
							m.put(res[i1], new Depth(str,dep+1));
							s.add(new Pair(res[i1], dep+1));
							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.depth(start, goal, 6);

		System.out.printf("例2\n");
		start = "216408753";
		ss.depth(start, goal, 19);
	}
}