迷路の解き方

by inu
迷路はどこかの1つのマスを、いわゆるバケツツールで塗りつぶせば
ゴールまでのルートが浮き出る。というやつ。
クリックで迷路を作ったり、左上のマスを塗りつぶしたりします。
塗りつぶしたあと赤と黒の間を通ればゴールにたどり着きます。
大きさを変えてみたりして遊んでください。
♥0 | Line 90 | Modified 2012-01-16 01:58:04 | MIT License
play

ActionScript3 source code

/**
 * Copyright inu ( http://wonderfl.net/user/inu )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/itY1
 */

package 
{
    import flash.display.*;
    import flash.events.*;
    import flash.geom.*;
    
    /**
     * @author inu
     */
    
    /**
     * 迷路はどこかの1つのマスを、いわゆるバケツツールで塗りつぶせば
     * ゴールまでのルートが浮き出る。というやつ。
     * クリックで迷路を作ったり、左上のマスを塗りつぶしたりします。
     * 
     * 塗りつぶしたあと赤と黒の間を通ればゴールにたどり着きます。
     * 大きさを変えてみたりして遊んでください。
     */ 
    
    public class Main extends Sprite 
    {
        /**
         *  WIDTH HEIGHT の条件
         *  ・奇数
         *  ・5 以上 465 以下
         **/
        private const WIDTH:int = 101;
        private const HEIGHT:int = 101;
        
        private var bmp:Bitmap;
        private var bmd:BitmapData;
        
        private const WHITE:uint = 0xffffffff;
        private const BLACK:uint = 0xff000000;
        private const RED:uint = 0xffff0000;
        
        public function Main():void 
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        
        private function init(e:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            // entry point
            if (WIDTH % 2 == 0 || HEIGHT % 2 == 0 || WIDTH < 5 || HEIGHT < 5 || WIDTH > 465 || HEIGHT > 465) return;
            
            var sp:Sprite = new Sprite();
            sp.addChild(bmp = new Bitmap(bmd = new BitmapData(WIDTH, HEIGHT)));
            sp.scaleX = 465 / WIDTH;
            sp.scaleY = 465 / HEIGHT;
            addChild(sp);
            
            createMaze();
            
            sp.addEventListener(MouseEvent.CLICK, clickEvent);
        }
        
        private function clickEvent(e:MouseEvent):void {
            if (bmd.getPixel32(0, 0) == BLACK) bmd.floodFill(0, 0, RED);
            else createMaze();
        }
        
        //壁のばし法で迷路を作る。
        private function createMaze():void {
            
            var i:int, j:int;
            
            var pointsDefault:Vector.<Point> = Vector.<Point>([new Point(0, -1), new Point(1, 0), new Point(0, 1), new Point( -1, 0)]);
            var pastWalls:Vector.<Point> = new Vector.<Point>();
            
            var index:int = 0;
            var next:int = 0;
            var cnt:int = 0;
            
            bmd.fillRect(new Rectangle(0, 0, WIDTH, HEIGHT), BLACK);
            bmd.fillRect(new Rectangle(1, 1, WIDTH - 2, HEIGHT - 2), WHITE);
            
            for (i = 2; i < HEIGHT - 1; i += 2 ) for (j = 0 ; j < WIDTH; j += WIDTH - 1 ) {
                pastWalls.push(new Point(j, i));
            }
        
            for (i = 0 ; i < HEIGHT; i += HEIGHT - 1  )for (j = 2; j < WIDTH - 1; j += 2 ) {
                pastWalls.push(new Point(j, i));
            }
            
            bmd.setPixel32(1, 0, WHITE);//start
            bmd.setPixel32(WIDTH - 2, HEIGHT - 1, WHITE);//goal
            
            while (cnt != int((WIDTH-2)/2)*int((HEIGHT-2)/2)) {
                index = Math.random() * pastWalls.length;
                
                var rx:int = pastWalls[index].x;
                var ry:int = pastWalls[index].y;
                
                next = 0;
                next += (ry - 2 >= 0 && bmd.getPixel32(rx + 0, ry - 2) != BLACK )?1:0;
                next += (rx + 2 <= WIDTH - 1 && bmd.getPixel32(rx + 2, ry + 0) != BLACK)?1:0;
                next += (ry + 2 <= HEIGHT - 1 && bmd.getPixel32(rx + 0, ry + 2) != BLACK)?1:0;
                next += (rx - 2 >= 0 && bmd.getPixel32(rx - 2, ry + 0) != BLACK)?1:0;
                
                if (next == 0) {
                    pastWalls.splice(index, 1);
                    continue;
                }
                
                while (next) {
                    
                    var points:Vector.<Point> = pointsDefault.slice(0);
                    
                    for (i = 0; i < 4; i++ ) {
                        
                        index = Math.random() * points.length;
                        
                        if ((bmd.getPixel32(rx + points[index].x * 2, ry + points[index].y * 2) == BLACK)
                        || (rx + points[index].x < 0 || ry + points[index].y < 0 || rx + points[index].x > WIDTH - 1 || ry + points[index].y > HEIGHT - 1)){
                            points.splice(index, 1);
                            continue;
                        }
                        
                        bmd.setPixel32(rx += points[index].x, ry += points[index].y, BLACK);
                        bmd.setPixel32(rx += points[index].x, ry += points[index].y, BLACK);
                        cnt++;
                        break;
                        
                    }
                    
                    next = 0;
                    next += (ry - 2 >= 0 && bmd.getPixel32(rx + 0, ry - 2) != BLACK )?1:0;
                    next += (rx + 2 <= WIDTH - 1 && bmd.getPixel32(rx + 2, ry + 0) != BLACK)?1:0;
                    next += (ry + 2 <= HEIGHT - 1 && bmd.getPixel32(rx + 0, ry + 2) != BLACK)?1:0;
                    next += (rx - 2 >= 0 && bmd.getPixel32(rx - 2, ry + 0) != BLACK)?1:0;
                    
                    if (next > 1) pastWalls.push(new Point(rx, ry));
                    
                }
            }
        }
    }
}