
//***********************************************//
//*                                             *//
//*迷路アルゴリズム DEVELOPMENT DATE: 2005/ 4/ 4*//
//*                                             *//
//***********************************************//

//**************************************//
//*このプログラムで使うパッケージの宣言*//
//**************************************//
import java.applet.Applet;//アプレットを使うためのパッケージ
import java.awt.*;        //グラフィックスとイメージのペイント用のパッケージ
import java.util.*;       //便利な機能を使うためのパッケージ


public class meiro_1 extends Applet implements Runnable{
	//********************************************//
	//           *迷路エリア変数の宣言*           //
	//********************************************//
		final int hyozi[][] = {						//最短経路を表示するための配列
						  	  {4,0,4,12},				// "|"
						  	  {0,4,12,4},				// "―"
						  	  {0,4,8,4,4,0,4,8},		// "」"
						  	  {4,4,8,4,4,0,4,8},		// "Ｌ"
						  	  {4,4,8,4,4,4,4,8},		// "「"
						  	  {0,4,8,4,4,4,4,8},		// "¬"
						  	  };
		final int tn = 31;             //迷路の縦の長さ
		final int yn = 31;             //迷路の横の長さ
		final int areaSize = 12;       //1マスの縦横の大きさ
		int M [][] = new int[tn][yn];  //迷路全体を表す配列の宣言
		int m_k[][] = new int[1000][2];//迷路の経路を表す配列の宣言
		boolean meiro_draw = false;    //迷路を描画するかどうかのboolean変数
		boolean anim_flag;	   //描画をアニメーションさせるかどうかのboolean変数
	//********************************************//
	//*このプログラムで使うインスタンス変数の宣言*//
	//********************************************//
		ControlPanel cp;               //ControlPanelのメソッドを使うためのインスタンス変数の宣言
		MeiroMake    mm;               //MeiroMakeのメソッドを使うためのインスタンス変数の宣言
		MeiroSearch  ms;               //MeiroSearchのメソッドを使うためのインスタンス変数の宣言
		MeiroDrawCheck md;
		Thread thread = null;
	//******************************************//
	//*   このプログラムで使う画面変数の宣言   *//
	//******************************************//
		Color bgcolor;                 //背景色の宣言
		Color KaBecolor;               //壁の色の宣言
		Color Keirocolor;
		Dimension d;                   //画面を設定するためのインスタンス変数
		Image offs;                    //オフスクリーンを作成するためのImage変数
		Graphics grf;                  //オフスクリーン
	public void init(){                           //初期化メソッド
		//****************************************//
		//*            画面情報の取得            *//
		//****************************************//
			d = getSize();                        //HTMLのコードから画面情報を取得
			offs = createImage(d.width,d.height); //それを元にImageを作成
			grf = offs.getGraphics();             //オフスクリーン用のグラフィックスコンテキストを作成
		//****************************************//
		//*              配列の初期化            *//
		//****************************************//
			Initialize();                         //配列の状態を全て0(道)の状態にする。
		//****************************************//
		//*          インスタンスの生成          *//
		//****************************************//
			cp = new ControlPanel(this,"迷路操作");//迷路操作画面を生成し、画面のタイトルを"迷路操作"に設定する。
		//****************************************//
		//*              色の設定                *//
		//****************************************//
			bgcolor = Color.white;                //背景色を白に設定する。
			KaBecolor = Color.black;              //壁の色を黒に設定する。
			Keirocolor = Color.green;
			anim_flag = false;
	}
	public void paint(Graphics g){                //描画メソッド
		update(g);                                //updateメソッドに処理を依頼
	}
	public void update(Graphics g){               							//実際に描画するメソッド
		//****************************************//
		//*              背景の描画              *//
		//****************************************//
			grf.setColor(bgcolor);                								//色を背景色（白）に設定する。
			grf.fillRect(0,0,d.width,d.height);   								//先ほど設定した色で、アプレット画面を塗りつぶす。
		//****************************************//
		//*           迷路エリアの描画           *//
		//****************************************//
			if(meiro_draw){													  //迷路を描画しなければならない時
			//****************************************//
			//*             各マスの描画             *//
			//****************************************//                       
				for(int i = 0;i < tn;i++){										//縦のマスの数だけくりかえす。
					int ii = i * areaSize;										  //各マスの左上のy座標を求める。
					for(int j = 0;j < yn;j++){									  //横のマスの数だけくりかえす。
						int jj = j * areaSize;									    //各マスの左上のx座標を求める
						if(M[i][j] == 1){										    //そのマスが壁だった時
							grf.setColor(KaBecolor);							      //色を壁の色に設定する。
							grf.fillRect(jj,ii,areaSize,areaSize);				      //1マスの縦横の大きさ分だけ塗りつぶす。
						}else{
							if(M[i][j] >= 2){																			//
								grf.setColor(Keirocolor);																//
								int ind = M[i][j] - 2;																	//
								grf.fillRect(jj + hyozi[ind][0],ii+hyozi[ind][1],hyozi[ind][2],hyozi[ind][3]);			//
								if(M[i][j] >= 4){																		//
									grf.fillRect(jj + hyozi[ind][4],ii+hyozi[ind][5],hyozi[ind][6],hyozi[ind][7]);		//
								}
							}
						}														  //
					}															//
			//****************************************//
			//*        スタート・ゴールの描画        *//
			//****************************************//
						grf.setColor(Color.black);								//色を黒に設定する。
						grf.drawString("Ｓ",12,23);								//スタート位置を描画する。
						grf.drawString("Ｇ",(tn - 2) * 12,(yn - 1) * 12 - 1);   //ゴール位置を描画する。
				}
			}
																			  //
			g.drawImage(offs,0,0,this);											//オフスクリーンをGraphicsに移動して描画する。
	}
																			//
	//****************************************//
	//*               迷路の取得             *//
	//****************************************//
	public void getMap(){													//迷路データを取得するメソッド
		meiro_draw = true;														//meiro_drawをtrueにし、迷路を描画させる。
		if(anim_flag){												  //アニメーションさせるという設定のときは
			start();//start()メソッドを呼び出す
		}else{																	  //
			mm = new MeiroMake(tn,yn);												//MeiroMakeのインスタンスを作成する。
			M = mm.MeiroMake_method(new int[tn][yn]);								//MeiroMake内のMeiroMake_method(int[][])を実行し、実行結果をMに返す。
		}																		  //
		repaint();																//paintメソッドを呼び出す。
	}																		//
	//****************************************//
	//*               迷路の探索             *//
	//****************************************//																		
	public void searchMap(){												//迷路データの最短経路を取得するメソッド
		ms = new MeiroSearch(tn,yn);											//MeiroSearchのインスタンスを作成する。
		m_k = ms.Search(M);														//MeiroSearch内のSearch(int[][])を実行し、実行結果をm_kに返す。
		md = new MeiroDrawCheck(tn,yn);
		md.DrawCheck(M,m_k);
		repaint();																//paintメソッドを呼び出す。
	}																		//
	//****************************************//
	//*               迷路の消去             *//
	//****************************************//
	public void clearMap(){													//描画されている迷路データを消去するメソッド
		Initialize();															//配列の状態を全て0(道)の状態にする。
		meiro_draw = false;														//迷路を描画しない設定に戻す。
		stop();
		repaint();																//paintメソッドを呼び出す
	}																		//
	//****************************************//
	//*              配列の初期化            *//
	//****************************************//
	public void Initialize(){												//配列の状態を初期化するメソッド
		for(int i = 0;i < tn;i++){												//縦のマスの数だけくりかえす。
			for(int j = 0;j < yn;j++){											  //横のマスの数だけくりかえす。
				M[i][j] = 0;                                                        //M[][]を0クリアする。
			}																	  //
		}																		//
	}
	public void start(){													//スレッドを起動させるためのメソッド
	  if(anim_flag){
	  	if(thread == null){													  //スレッドが停止状態であれば
			thread = new Thread(this);											//Threadクラスのインスタンスを生成する。
			thread.start();														//スレッドを起動させる（runメソッドに処理が移る)
		}																	  //
	  }
	}																		//
	public void stop(){														//スレッドを停止させるためのメソッド（非推奨API)
		if(thread != null){													  //スレッドが起動状態であれば
			thread.stop();														//スレッドを停止させる。
			thread = null;														//threadの値をnullにする。(これによりrunメソッドを停止させる)
		}																	  //
	}																		//
	public void run(){														//スレッドが行う実際の処理を行うメソッド
		mm = new MeiroMake(tn,yn);											  //MeiroMakeのインスタンスを生成する。
		for(int i = 0;i < tn;i++){											  //縦のマスの数だけくりかえす。
			for(int j = 0;j < yn;j++){										    //横のマスの数だけくりかえす。
				try{
					Thread.sleep(3);												//2ミリ秒スレッドに休憩を与える。
				}catch(InterruptedException e){										//例外が発生したときは何もしない。
				}																	//
				M[i][j] = mm.MeiroInit_method(i,j);								    //MeiroMakeのMeiroInit_methodを実行する。
				repaint();															//paintメソッドを呼び出す。
			}																	//
		}																	  //
	    for(int i = 2;i < (tn - 2);i = i + 2){								  //(偶数,偶数)（端のマスを除く)のマスを繰り返す
			for(int j = 2;j < (yn - 2);j = j + 2){							    //
				try{
					Thread.sleep(10);												//10ミリ秒スレッドに休憩を与える。
				}catch(InterruptedException e){										//例外が発生したときは何もしない。
				}																	//
				int z = mm.MeiroNobasi_method(i,j,M);
				M[i + mm.h[0][z]][j + mm.h[1][z]] = 1;
				repaint();
			}																	//
		}
	}																		//
}


		
