In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

幅優先探索(BFS)

迷路生成(穴掘り法)
http://wonderfl.net/code/c753aea9f78f70c78522bda1546912b15568436d
深さ優先探索(DFS)
http://wonderfl.net/code/2fe2b7feed97268aa569ab138932603ec82d047d
Get Adobe Flash player
by matsu4512 10 Jan 2010
/**
 * Copyright matsu4512 ( http://wonderfl.net/user/matsu4512 )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/6PCb
 */

 /*
 迷路生成(穴掘り法)
 http://wonderfl.net/code/c753aea9f78f70c78522bda1546912b15568436d
 深さ優先探索(DFS)
 http://wonderfl.net/code/2fe2b7feed97268aa569ab138932603ec82d047d
 */

package {
	import caurina.transitions.Tweener;
	
	import flash.display.Shape;
	import flash.display.Sprite;
	
	/*
		幅優先探索によって迷路のスタートからゴールまでの最短経路を求める。
	*/
	[SWF(width=500, height=500, backgroundColor=0x000000)]
	
	public class BFS extends Sprite
	{
		//フィールドの情報を格納する配列。1は道、0は壁。
		private var field:Array;
		//フィールドのサイズ
		private var fsize:int = 31;
		//マスの数
		private var size:int = fsize*fsize;
		//道を伸ばす方向, 東西南北の順
		private var dir_ary:Array = [-fsize, 1, fsize, -1];
		//辿った道を記録しておく配列
		private var trace_ary:Array = [];
		//一マスのサイズ
		private var mass_size:Number;
		//可視化のために通った道を全て記録しておく配列
		private var route_records:Array = [];
		private var ball:Sprite = new Sprite();
		
		//隣接行列
		private var ad_mat:Array = [];
		//一度訪れた場所を記録しておく配列
		private var visited:Array = [];
		//探索に必要なQueue
		private var queue:Array = [];
		
		private var startNode:int, endNode:int;
		
		public function BFS()
		{
			mass_size = 500 / fsize;
			create_maze();
			for(var i:int = 0; i < size; i++){
				if(field[i]) draw(i);
			}
			
			startBfs();
			
			ball.graphics.beginFill(0x0000ff);
			ball.graphics.drawRect(0, 0, mass_size, mass_size);
			ball.graphics.endFill();
			ball.x = 0;
			ball.y = 0;
			
			addChild(ball);
			
			draw(startNode, 0xfff000);
			draw(endNode, 0x00ff00);
			
			//可視化の開始
			visualize(0);
		}
		
		//隣接行列の生成
		private function create_ad_mat():void{
			var len:int = field.length;
			while(len--) ad_mat[len] = [];
			for(var i:int = 0; i < fsize; i++){
				for(var j:int = 0; j < fsize; j++){
					var p:int = i*fsize+j;
					ad_mat[p][p] = 0;
					if(i == 0 || j == 0 || i == fsize-1 || j == fsize-1) continue;
					if(field[p]){
						if(field[p+1]) ad_mat[p][p+1] = ad_mat[p+1][p] = 1;
						else ad_mat[p][p+1] = ad_mat[p+1][p] = 0;
						if(field[p-1]) ad_mat[p][p-1] = ad_mat[p-1][p] = 1;
						else ad_mat[p][p-1] = ad_mat[p-1][p] = 0;
						if(field[p+fsize]) ad_mat[p][p+fsize] = ad_mat[p+fsize][p] = 1;
						else ad_mat[p][p+fsize] = ad_mat[p+fsize][p] = 0;
						if(field[p-fsize]) ad_mat[p][p-fsize] = ad_mat[p-fsize][p] = 1;
						else ad_mat[p][p-fsize] = ad_mat[p-fsize][p] = 0;
					}
				}
			}
		}
		
		private function startBfs():void{
			create_ad_mat();
			for(var i:int = 0; i < size; i++)
				if(field[i]) startNode = i;
			for(i = size-1; i > 0; i--)
				if(field[i]) endNode = i;
			
			for (i = 0; i < size; i++ ) visited[ i ] = false;
			
			queue.push(new Node(startNode, null));
			visited[startNode] = true;
     		bfs();
		}
		
		//幅優先探索でゴール地点を探索
		private function bfs():void{
			var cur_node:Node;
			while(1){
				cur_node = queue.pop() as Node;
				for(var i:int = 0; i < size; i++){
					if(ad_mat[cur_node.pos][i] && !visited[i]){
						visited[i] = true;
						route_records.push(i);
						queue.unshift(new Node(i, cur_node));
						if(i == endNode) return;
					}
				}
			}
		}
		
		private function create_maze():void{
			//迷路のフィールドのサイズを20*20で確保 & 初期化
			//まずは外枠以外全て壁にする。
			field = [];
			for(var i:int = 0; i < fsize; i++){
				for(var j:int = 0; j < fsize; j++){
					if(i == 0 || i == fsize-1 || j%fsize == 0 || (j+1)%fsize == 0){
						field[i*fsize+j] = 1;
					}
					else field[i*fsize+j] = 0;
				}
			}
			
			//1~(fsize-2)の間の奇数な乱数を生成。
			var odd_x:int = Math.random() * int((fsize-2)/2+1) * 2 + 1;
			var odd_y:int = Math.random() * int((fsize-2)/2+1) * 2 + 1;
			
			//fieldに対応した値に直して渡す。
			create_path(odd_y*fsize + odd_x);
			
			//外枠を壁にする
			for(i = 0; i < fsize; i++){
				for(j = 0; j < fsize; j++){
					if(i == 0 || i == fsize-1 || j%fsize == 0 || (j+1)%fsize == 0) field[i*fsize+j] = 0;
				}
			}
		}
		
		//指定された地点から道を作る関数
		private function create_path(pos:int):void{	
			var dir_ary2:Array = dir_ary.slice(0, 4);
			for(var i:int = 4; i > 0; i--){
				//道を伸ばす方向をランダムに決める
				var dir:int = int(Math.random()*i);

				//指定した方向の2マス先まで調べる
				for(var j:int = 0; j < 2; j++){
					if(field[pos + dir_ary2[dir]*(j+1)]) break;
				}
				if(j == 2) break;
				dir_ary2.splice(dir, 1);
			}
			//どちらも壁ならば、その2マスを道にする。
			if(j == 2){
				field[pos + dir_ary2[dir]] = field[pos + dir_ary2[dir]*2] = 1;
				
				pos += dir_ary2[dir];
				//移動する
				pos += dir_ary2[dir];
				
				//通った道の記録
				trace_ary.push(pos);
				
				//新たに道を作る
				create_path(pos);
			}
			//道が作れなかったら、一つ前に戻る。
			else{
				//初期位置に戻ってきたら終了
				if(trace_ary.length == 1) return;
				create_path(trace_ary.pop());
			}
		}
		
		private function draw(pos:int, c:uint=0xffffff):void{
			var rect:Shape = new Shape();
			rect.graphics.beginFill(c);
			rect.graphics.drawRect(0, 0, mass_size, mass_size);
			rect.graphics.endFill();
			rect.x = pos%fsize*mass_size;
			rect.y = int(pos/fsize)*mass_size;
			addChild(rect);
		}
		
		//route_recordsに記録されている道順にオブジェクトを移動させる
		private function visualize(i:int):void{
			Tweener.addTween(ball, {x:route_records[i]%fsize*mass_size, y:int(route_records[i]/fsize)*mass_size, time:0.01,
				onComplete:function():void{
					draw(route_records[i], 0xff0000);
					if(i == route_records.length-2){
						var node:Node = queue.shift().pre_node;
						while(node.pre_node != null){
							draw(node.pos, 0x000fff);
							node = node.pre_node;
						}
						return;
					}
					visualize(i+1);
				}
			});
		}
	}
}

class Node{
	public var pos:int;
	public var pre_node:Node;
	public function Node(pos:int, pre_node:Node){
		this.pos = pos;
		this.pre_node = pre_node;
	}
}