8 パズルの解法

/****************************/
/* 8 パズルの解法           */
/*      Coded by Y.Suganuma */
/****************************/
import java.io.*;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;

public class Test {
	public static void main (String[] args)
	{
		S_Eight win = new S_Eight("8 パズルの解法( Swing )");
	}
}

class S_Eight extends JFrame implements ItemListener {

	int MAX = 1000;   // 最大試行回数
	int g[][];   // 目標状態
	int kodomo[][][];   // [i][0][j] : 適用した規則番号
                        // [i][1][j] : 適用後の状態
	int n_o_pattern;   // 展開された状態の数
	int oya[];   // 親の状態番号
	int pattern[][][];   // 現在の状態
	int s_method = 1;   // 探索方法
                        //   =1 : 横型
                        //   =2 : 縦型
                        //   =3 : 深さ+目標状態と異なるコマの数
                        //   =4 : h(n) = p(n) + 3s(n)
                        //           p(n) : 目標状態からの距離
                        //           s(n) : =0 : 次の駒が正しい順序のとき(中心の駒を除く)
                        //                  =2 : 次の駒が誤った順序のとき(中心の駒を除く)
                        //                  =1 : 中心の駒
	int tenkai[];   // =0 : 未展開(葉)の状態
                    // =1 : 展開済みの状態
	double hukasa[][];   // [i][0] : 状態のの深さ
                         // [i][1] : 評価関数の値
	double max_depth = 10;   // 最大探索深さ

	JComboBox  choice;
	JTextField trial, depth;
	S_Eight dt = this;

	/******************/
	/* コンストラクタ */
	/******************/
	S_Eight(String name)
	{
						// JFrameクラスのコンストラクタ(Windowのタイトルを引き渡す)
		super(name);
						// Windowの大きさ
		setSize(300, 200);
						// レイアウトの変更
		Container cp = getContentPane();
		cp.setBackground(Color.white);
		JPanel jp = new JPanel();
		jp.setLayout(new GridLayout(4, 2, 5, 10));
		jp.setBackground(Color.white);
		cp.add(jp);
		Font f = new Font("TimesRoman", Font.BOLD, 20);
						// スクロールリスト & テキストフィールド
		JLabel fill1 = new JLabel("最大試行回数");
		fill1.setFont(f);
		jp.add(fill1);
		trial = new JTextField("1000", 10);
		trial.setBackground(Color.white);
		trial.setFont(f);
		jp.add(trial);

		JLabel fill2 = new JLabel("探索方法");
		fill2.setFont(f);
		jp.add(fill2);
		choice = new JComboBox ();
		choice.setBackground(Color.white);
		choice.setFont(f);
		choice.addItem("横型探索");
		choice.addItem("縦型探索");
		choice.addItem("評価関数1");
		choice.addItem("評価関数2");
		jp.add(choice);
		choice.addItemListener(this);

		JLabel fill3 = new JLabel("最大探索深さ");
		fill3.setFont(f);
		jp.add(fill3);
		depth = new JTextField("10", 10);
		depth.setBackground(Color.white);
		depth.setFont(f);
		jp.add(depth);
						// OK ボタンの設定
		JLabel fill4 = new JLabel(" スタート?");
		fill4.setFont(f);
		jp.add(fill4);
		JButton bt = new JButton("OK");
		bt.setFont(f);
		bt.addMouseListener(new ClickMouse());
		jp.add(bt);
					// ウィンドウを表示
		setVisible(true);
					// イベントアダプタ
		addWindowListener(new WinEnd());
	}

	/******************************/
	/* 上,左,下,右の余白の設定 */
	/******************************/
	public Insets getInsets()
	{
		return new Insets(50, 20, 20, 20);
	}

	/******************************/
	/* チョイスコントロールの処理 */
	/******************************/
	public void itemStateChanged(ItemEvent e)
	{
		if (e.getItemSelectable() == choice) {
			s_method = choice.getSelectedIndex() + 1;
		}
	}

	/********************************/
	/* OKボタンが押されたときの処理 */
	/********************************/
	class ClickMouse extends MouseAdapter
	{
		/************************************/
		/* マウスがクリックされたときの処理 */
		/************************************/
		public void mouseClicked(MouseEvent e)
		{
			int i1;
							// 領域の確保
			MAX       = Integer.parseInt(trial.getText());
			max_depth = Integer.parseInt(depth.getText());

			g         = new int [3][3];
			kodomo    = new int [MAX][2][4];
			oya       = new int [MAX];
			pattern   = new int [MAX][3][3];
			tenkai    = new int [MAX];
			hukasa    = new double [MAX][2];
							// 初期設定
			n_o_pattern  = 0;
			hukasa[0][0] = 0.0;
			tenkai[0]    = 0;
			oya[0]       = 0;
			for (i1 = 0; i1 < 4; i1++)
				kodomo[0][0][i1] = 0;
							// ゴールの設定
			g[0][0] = 1;
			g[0][1] = 2;
			g[0][2] = 3;
			g[1][0] = 8;
			g[1][1] = 0;
			g[1][2] = 4;
			g[2][0] = 7;
			g[2][1] = 6;
			g[2][2] = 5;
							// 初期状態の設定
			S_Initial initial = new S_Initial(dt);
		}
	}

	/************/
	/* 終了処理 */
	/************/
	class WinEnd extends WindowAdapter
	{
		public void windowClosing(WindowEvent e) {
			System.exit(0);
		}
	}
}

/****************************/
/* クラスS_Initialの定義    */
/* (初期状態の入力)       */
/****************************/
class S_Initial extends JFrame {

	int err = 0;   // エラーの有無
	private int n;   // 行・列の数
	private S_Eight dt;
	private S_Initial in = this;
	JTextField a[][];
	JLabel f[];
	Error_p ep;

	/*******************************************/
	/* コンストラクタ                          */
	/*      dt_i : S_Eightクラスのオブジェクト */
	/*******************************************/
	S_Initial(S_Eight dt_i)
	{
						// Frameクラスのコンストラクタの呼び出し
		super("初期状態");
						// レイアウトの変更
		n  = 3;
		dt = dt_i;
		a  = new JTextField [n][n];
		f  = new JLabel [n-1];
		Container cp = getContentPane();
		cp.setBackground(Color.white);
		cp.setLayout(null);
		JPanel jp = new JPanel();
		jp.setBackground(Color.white);
		cp.add(jp);
		jp.setLayout(new BorderLayout(5, 10));
		JPanel pn = new JPanel();
		pn.setBackground(Color.white);
		pn.setLayout(new GridLayout(n, n+1, 5, 10));
		jp.add(pn, BorderLayout.NORTH);
		Font fn = new Font("TimesRoman", Font.BOLD, 20);
						// テキストフィールドの設定
		int i1, i2;
		for (i1 = 0; i1 < n; i1++) {
			for (i2 = 0; i2 < n; i2++) {
				a[i1][i2] = new JTextField(2);
				a[i1][i2].setFont(fn);
				pn.add(a[i1][i2]);
			}
			if (i1 < n-1) {
				f[i1] = new JLabel();
				pn.add(f[i1]);
			}
		}
						// OK ボタンの設定
		JButton bt = new JButton("OK");
		bt.setFont(fn);
		bt.addMouseListener(new ClickMouse());
		pn.add(bt);
						// メッセージパネルの追加
		ep = new Error_p(this);
		ep.setBackground(Color.white);
		jp.add(ep, BorderLayout.CENTER);
						// Windowサイズを設定
		setSize(350, 250);
						// ウィンドウを表示
		setVisible(true);
		Insets in = getInsets();
		jp.setLocation(10, 10);
		jp.setSize(350-in.left-in.right-20, 250-in.top-in.bottom-20);
						// イベントアダプタ
		addWindowListener(new WinEnd());
	}

	/********************************/
	/* OKボタンが押されたときの処理 */
	/********************************/
	class ClickMouse extends MouseAdapter
	{
		/************************************/
		/* マウスがクリックされたときの処理 */
		/************************************/
		public void mouseClicked(MouseEvent e)
		{
			int i1, i2, i3, i4, k, k1;

			err = 0;
		/*
		          入力データの処理
		*/
			for (i1 = 0; i1 < n && err == 0; i1++) {
				for (i2 = 0; i2 < n && err == 0; i2++) {
					if ((a[i1][i2].getText()).length() <= 0)
						dt.pattern[0][i1][i2] = 0;
					else
						dt.pattern[0][i1][i2] = Integer.parseInt(a[i1][i2].getText());
					if (dt.pattern[0][i1][i2] < 0 || dt.pattern[0][i1][i2] > 8)
						err = 1;
					else {
						for (i3 = 0; i3 <= i1 && err == 0; i3++) {
							k1 = (i3 == i1) ? i2 : n;
							for (i4 = 0; i4 < k1 && err == 0; i4++) {
								if (dt.pattern[0][i1][i2] == dt.pattern[0][i3][i4])
									err = 1;
							}
						}
					}
				}
			}

			ep.repaint();
							// 解を見つける
			if (err == 0) {
				in.setVisible(false);
				Eight eight = new Eight(dt);
			}
		}
	}

	/************/
	/* 終了処理 */
	/************/
	class WinEnd extends WindowAdapter
	{
		public void windowClosing(WindowEvent e) {
			in.setVisible(false);
		}
	}
}

/**************************/
/* エラーメッセージの表示 */
/**************************/
class Error_p extends JPanel {
	S_Initial in;

	Error_p(S_Initial in1)
	{
		in = in1;
	}

	public void paintComponent (Graphics g)
	{
		super.paintComponent(g);   // 親クラスの描画(必ず必要)
						// フォントの設定
		Font f = new Font("TimesRoman", Font.BOLD, 20);
		g.setFont(f);
						// エラーメッセージの出力
		int x = 10;
		int y = 25;
		if (in.err == 0)
			g.drawString("             ", x, y);
		else {
			g.setColor(Color.red);
			g.drawString("*** Error ***", x, y);
			g.setColor(Color.black);
		}
	}
}

/************************/
/* クラスEightの定義    */
/* (問題を解く)       */
/************************/
class Eight extends JFrame {

	private S_Eight dt;
	private Eight et = this;
	private JTextArea text;

	/*******************************************/
	/* コンストラクタ                          */
	/*      dt_i : S_Eightクラスのオブジェクト */
	/*******************************************/
	Eight(S_Eight dt_i)
	{
						// JFrameクラスのコンストラクタの呼び出し
		super("8パズル");
						// テキストエリアの設定
		dt = dt_i;
		Container cp = getContentPane();
		cp.setBackground(Color.white);
		JPanel jp = new JPanel();
		cp.setLayout(null);
		jp.setBackground(Color.white);
		cp.add(jp);
		Font f = new Font("TimesRoman", Font.BOLD, 20);
		text = new JTextArea("", 15, 25);
		text.setFont(f);
		JScrollPane sp = new JScrollPane(text);
		jp.add(sp);
						// Windowサイズを設定
		setSize(470, 450);
						// ウィンドウを表示
		setVisible(true);
		Insets in = getInsets();
		jp.setLocation(10, 10);
		jp.setSize(470-in.left-in.right-20, 450-in.top-in.bottom-20);
						// イベントアダプタ
		addWindowListener(new WinEnd());
						// 実行
		solve();
	}

	/********************/
	/* 8-パズルを解く */
	/********************/
	public void solve()
	{
		int i1, i2, i3, pt = 0, rl = 0, sw = 0;
		int ptn[][] = new int [3][3];
		int ptn1[][] = new int [3][3];
		int rl1[] = new int [1];
		double pf, pf1;
	/*
	          問題解決
	*/
		while (sw == 0) {
						// 規則の探索
			pf = 99999.0;
			for (i1 = 0; i1 <= dt.n_o_pattern; i1++) {
				if (dt.tenkai[i1] == 0) {
					pf1 = fire(i1, rl1, ptn1);   // 適用規則と評価関数の計算
					if (pf1 > 10000.0)
						dt.tenkai[i1] = 1;
					else {
						if (pf1 < pf) {           // 最小評価関数規則の選択 */
							pf = pf1;                      // 評価関数値
							pt = i1;                       // 展開パターン
							rl = rl1[0];                   // 適用規則
							for (i2 = 0; i2 < 3; i2++) {   // 規則適用後のパターン
								for (i3 = 0; i3 < 3; i3++)
									ptn[i2][i3] = ptn1[i2][i3];
							}
						}
					}
				}
			}
						// 適用可能規則なし
			if (pf > 10000.0) {
				sw = 1;
				text.insert("解決できませんでした!\n", 0);
			}
						// 規則の適用
			else {

				dt.n_o_pattern += 1;
							// 制限回数超過
				if (dt.n_o_pattern >= dt.MAX) {
					sw = 1;
					text.insert("解決できませんでした!\n", 0);
				}
							// 制限回数以内
				else {

					dt.oya[dt.n_o_pattern]       = pt;
					dt.hukasa[dt.n_o_pattern][0] = dt.hukasa[pt][0] + 1.0;
					dt.hukasa[dt.n_o_pattern][1] = pf;
					dt.tenkai[dt.n_o_pattern]    = 0;

					for (i1 = 0; i1 < 4; i1++)
						dt.kodomo[dt.n_o_pattern][0][i1] = 0;

					for (i1 = 0; i1 < 3; i1++) {
						for (i2 = 0; i2 < 3; i2++)
							dt.pattern[dt.n_o_pattern][i1][i2] = ptn[i1][i2];
					}

					sw = 1;
					for (i1 = 0; i1 < 4 && sw > 0; i1++) {
						if (dt.kodomo[pt][0][i1] == 0) {
							sw                   = 0;
							dt.kodomo[pt][0][i1] = rl;
							dt.kodomo[pt][1][i1] = dt.n_o_pattern;
						}
					}
								// 目標達成のチェック
					sw = 1;
					for (i1 = 0; i1 < 3 && sw > 0; i1++) {
						for (i2 = 0; i2 < 3 && sw > 0; i2++) {
							if (ptn[i1][i2] != dt.g[i1][i2])
								sw = 0;
						}
					}
								// 目標達成
					if (sw > 0) {
						pt = dt.n_o_pattern;
						text.insert("成功!!\n", 0);
						while (pt > 0) {
							p_pattern(pt);
							pt = dt.oya[pt];
						}
						p_pattern(0);
					}
				}
			}
		}
	}

	/*****************************************/
	/* 適用可能な規則を選ぶ                  */
	/*      pt : パターン番号                */
	/*      rl : 適用規則番号                */
	/*      ptn[i][j] : 規則適用後のパターン */
	/*      return : 評価関数の値            */
	/* 有効な規則の集合                      */
	/*      13 : IF [0][0]=0 THEN RIGHT      */
	/*      14 : IF [0][0]=0 THEN DOWN       */
	/*      21 : IF [0][1]=0 THEN LEFT       */
	/*      23 : IF [0][1]=0 THEN RIGHT      */
	/*      24 : IF [0][1]=0 THEN DOWN       */
	/*      31 : IF [0][2]=0 THEN LEFT       */
	/*      34 : IF [0][2]=0 THEN DOWN       */
	/*      42 : IF [1][0]=0 THEN UP         */
	/*      43 : IF [1][0]=0 THEN RIGHT      */
	/*      44 : IF [1][0]=0 THEN DOWN       */
	/*      51 : IF [1][1]=0 THEN LEFT       */
	/*      52 : IF [1][1]=0 THEN UP         */
	/*      53 : IF [1][1]=0 THEN RIGHT      */
	/*      54 : IF [1][1]=0 THEN DOWN       */
	/*      61 : IF [1][2]=0 THEN LEFT       */
	/*      62 : IF [1][2]=0 THEN UP         */
	/*      64 : IF [1][2]=0 THEN DOWN       */
	/*      72 : IF [2][0]=0 THEN UP         */
	/*      73 : IF [2][0]=0 THEN RIGHT      */
	/*      81 : IF [2][1]=0 THEN LEFT       */
	/*      82 : IF [2][1]=0 THEN UP         */
	/*      83 : IF [2][1]=0 THEN RIGHT      */
	/*      91 : IF [2][2]=0 THEN LEFT       */
	/*      92 : IF [2][2]=0 THEN UP         */
	/*        最初の数字:空白の位置         */
	/*        次の数字  :空白を移動する方向 */
	/*****************************************/
	public double fire(int pt, int [] rl,int [][] ptn)
	{
		int i1, i2, i3, i4, k1, sw;
		int ptn1[][] = new int [3][3];
		double pf;
		double pf1[] = new double [1];

		pf = 99999.0;

		for (i1 = 1; i1 <= 9; i1++) {
			for (i2 = 1; i2 <= 4; i2++) {
				k1 = 10 * i1 + i2;
				sw = rule(pt, pf1, k1, ptn1);
				if (sw > 0) {
					if (pf1[0] < pf) {
						pf    = pf1[0];
						rl[0] = k1;
						for (i3 = 0; i3 < 3; i3++) {
							for (i4 = 0; i4 < 3; i4++)
								ptn[i3][i4] = ptn1[i3][i4];
						}
					}
				}
			}
		}

		return pf;
	}

	/**********************************************************/
	/* 規則が適用か否かを調べ、かつ、適用後の評価関数値を計算 */
	/*      pt : パターン番号                                 */
	/*      pf : 評価関数の値                                 */
	/*      rl : 適用規則番号                                 */
	/*      ptn[i][j] : 規則適用後のパターン                  */
	/*      return : =0 : 適用不可能                          */
	/*               =1 : 適用可能                            */
	/**********************************************************/
	public int rule(int pt, double [] pf, int rl, int [][] ptn)
	{
		int i1, i2, i3, k1, k2, k3, sw;
		double pi[] = new double [1];

		sw = 1;
	/*
	          既に適用した規則か否かのチェック
	*/
		for (i1 = 0; i1 < 4 && sw > 0; i1++) {
			if (rl == dt.kodomo[pt][0][i1])
				sw = 0;
		}
	/*
	          物理的適用可能性のチェック
	*/
		if (sw > 0) {
			k1 = rl / 10;
			k2 = rl % 10;
			sw = -1;
			for (i1 = 0; i1 < 3 && sw < 0; i1++) {
				for (i2 = 0; i2 < 3 && sw < 0; i2++) {
					if (dt.pattern[pt][i1][i2] == 0) {
						sw = 1;
						k3 = 3 * i1 + i2 + 1;
						if (k1 != k3)    // 位置が不適当
							sw = 0;
						else {           // 移動方向のチェック
							if (i1 == 0 && k2 == 2)
								sw = 0;
							if (i1 == 2 && k2 == 4)
								sw = 0;
							if (i2 == 0 && k2 == 1)
								sw = 0;
							if (i2 == 2 && k2 == 3)
								sw = 0;
						}
					}
				}
			}
	/*
	          規則の適用
	*/
			if (sw > 0) {
				apply(pt,rl,ptn);
	/*
	          既に展開したパターンに同じものがあるか否かのチェック
	*/
				for (i1 = 0; i1 <= dt.n_o_pattern && sw > 0; i1++) {
					sw = 0;
					for (i2 = 0; i2 < 3 && sw == 0; i2++) {
						for (i3 = 0; i3 < 3 && sw == 0; i3++) {
							if (ptn[i2][i3] != dt.pattern[i1][i2][i3])
								sw = 1;
						}
					}
					if (sw == 0 && dt.s_method == 2) {
						if (dt.hukasa[i1][0] > dt.hukasa[pt][0]+1.0)
							sw = 1;
					}
				}
	/*
	          評価関数の計算
	*/
				if (sw > 0) {
					sw    = cal_pf(pt, pi, ptn);
					pf[0] = pi[0];
				}
			}
		}

		return sw;
	}

	/*****************************************/
	/* 与えられた規則を適用する              */
	/*      pt : パターン番号                */
	/*      rl : 適用規則番号                */
	/*      ptn : 規則適用後のパターン       */
	/*****************************************/
	public void apply(int pt, int rl, int [][] ptn)
	{
		int i1, i2, j1, j2, k1 = 0, k2 = 0, l1, l2;
	/*
	          適用前のパターン
	*/
		for (i1 = 0; i1 < 3; i1++) {
			for (i2 = 0; i2 < 3; i2++)
				ptn[i1][i2] = dt.pattern[pt][i1][i2];
		}
	/*
	          規則適用後のパターン
	*/
		l1 = rl / 10;
		l2 = rl % 10;
						// 適用前の空白の位置
		j1 = (l1 - 1) / 3;
		j2 = (l1 - 1) % 3;
						// 適用後の空白の位置
		switch (l2) {
			case 1 :
				k1 = j1;
				k2 = j2 - 1;
				break;
			case 2 :
				k1 = j1 - 1;
				k2 = j2;
				break;
			case 3 :
				k1 = j1;
				k2 = j2 + 1;
				break;
			case 4 :
				k1 = j1 + 1;
				k2 = j2;
				break;
		}
	/*
	          適用後のパターン
	*/
		ptn[j1][j2] = ptn[k1][k2];
		ptn[k1][k2] = 0;
	}

	/**************************************************************/
	/* 評価関数の値を計算する                                     */
	/*      pt : パターン番号                                     */
	/*      pf : 評価関数の値                                     */
	/*      ptn[i][j] : 規則適用後のパターン(縦型、横型では未使用)*/
	/*      return : =0 : 適用不可能(縦型探索で深さ制限を越えた時 */
	/*               =1 : 適用可能(その他)                        */
	/**************************************************************/
	public int cal_pf(int pt, double [] pf,int [][] ptn)
	{
		int i1, i2, i3, i4, j1, j2, kyori, pos, seq, ssw, sw;

		sw = 1;

		switch (dt.s_method) {
	/*
	          横型探索
	*/
			case 1 :
				pf[0] = dt.hukasa[pt][0];
				break;
	/*
	          縦型探索
	*/
			case 2 :
				if (dt.hukasa[pt][0] < dt.max_depth)
					pf[0] = -dt.hukasa[pt][0];
				else
					sw = 0;
				break;
	/*
	          深さ+目標状態と異なる位置の数
	*/
			case 3 :
				pos = 0;
				for (i1 = 0; i1 < 3; i1++) {
					for (i2 = 0; i2 < 3; i2++) {
						if (ptn[i1][i2] != 0) {
							if (ptn[i1][i2] != dt.g[i1][i2])
								pos += 1;
						}
					}
				}
				pf[0] = dt.hukasa[pt][0] + (double)pos;
				break;
	/*
	          h(n) = p(n) + 3s(n)
	               p(n) : 目標状態からの距離
	               s(n) : =0 : 次の駒が正しい順序の時(中心の駒を除く)
	                      =2 : 次の駒が誤った順序の時(中心の駒を除く)
	                      =1 : 中心の駒
	*/
			case 4 :
				kyori = 0;
				for (i1 = 0; i1 < 3; i1++) {
					for (i2 = 0; i2 < 3; i2++) {
						if (ptn[i1][i2] != 0) {
								// 距離の計算
							ssw = 0;
							for (i3 = 0; i3 < 3 && ssw == 0; i3++) {
								for (i4 = 0; i4 < 3 && ssw == 0; i4++) {
									if (ptn[i1][i2] == dt.g[i3][i4]) {
										kyori += (Math.abs(i3-i1) + Math.abs(i4-i2));
										ssw    = 1;
									}
								}
							}
								// 次の駒の位置のチェック
							seq = 2;
							if (i1 == 1 && i2 == 1)   // 中心の駒
								seq = 1;
							else {    // 中心以外の駒
								if (i1 == 0) {
									if (i2 == 2) {
										j1 = 1;
										j2 = 2;
									}
									else {
										j1 = i1;
										j2 = i2 + 1;
									}
								}
								else {
									if (i1 == 1) {
										if (i2 == 0) {
											j1 = 0;
											j2 = 0;
										}
										else {
											j1 = 2;
											j2 = 2;
										}
									}
									else {
										if (i2 == 0) {
											j1 = 1;
											j2 = 0;
										}
										else {
											j1 = i1;
											j2 = i2 - 1;
										}
									}
								}
								if (ptn[i1][i2] == 8) {
									if (ptn[j1][j2] == 1)
										seq = 0;
								}
								else {
									if (ptn[j1][j2] == ptn[i1][i2]+1)
										seq = 0;
								}
							}

							kyori += (3 * seq);

						}
					}
				}

				pf[0] = dt.hukasa[pt][0] + (double)kyori;
				break;
	/*
	         その他
	*/
			default :
				pf[0] = dt.hukasa[pt][0];
				break;
		}

		return sw;
	}

	/****************************/
	/* 与えられたパターンの出力 */
	/*      pt : パターン番号   */
	/****************************/
	public void p_pattern(int pt)
	{
		int i1, i2;
		String str;

		for (i1 = 2; i1 >= 0; i1--) {
			str = "   ";
			for (i2 = 0; i2 < 3; i2++)
				str += Integer.toString(dt.pattern[pt][i1][i2]);
			str += "\n";
			text.insert(str, 0);
		}

		str  = "状態番号 ";
		str += Integer.toString(pt);
		str += "  深さ= ";
		str += Integer.toString((int)dt.hukasa[pt][0]);
		str += "  評価= ";
		str += Integer.toString((int)dt.hukasa[pt][1]);
		text.insert(str + "\n", 0);
	}

	/************/
	/* 終了処理 */
	/************/
	class WinEnd extends WindowAdapter
	{
		public void windowClosing(WindowEvent e) {
			et.setVisible(false);
		}
	}
}