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

Mine Sweepr Like

特に変わったところはないです。

左クリック→オープン
右クリック→フラグ
Get Adobe Flash player
by chimad 21 Aug 2014
/**
 * Copyright chimad ( http://wonderfl.net/user/chimad )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/tQ9Y
 */

package {
    import flash.display.Sprite;
    
    public class Main extends Sprite {
        public function Main() {
            addChild(new StartScene());
        }
    }
}

import com.bit101.components.PushButton;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.DisplayObjectContainer;
import flash.display.GradientType;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.text.TextField;
import flash.text.TextFormat;
import org.libspark.betweenas3.BetweenAS3;

class Board {
    public var width:int;
    
    public var height:int;
    
    public var numMines:int;
    
    private var tiles:Vector.<Vector.<int>>;
    
    private var revealed:Vector.<Vector.<int>>;
    
    private var flags:Vector.<Vector.<int>>;
    
    public var inited:Boolean;
    
    public function getFlag(x:int, y:int):int {
        if (x < 0 || x >= width || y < 0 || y >= height) {
            return -1;
        }
        return flags[y][x];
    }
    
    public function setFlag(x:int, y:int):void {
        if (x < 0 || x >= width || y < 0 || y >= height) {
            return;
        }
        if (flags[y][x] >= 2)
            flags[y][x] = 0;
        else
            flags[y][x] = flags[y][x] + 1;
    }
    
    public function getTile(x:int, y:int):int {
        if (x < 0 || x >= width || y < 0 || y >= height) {
            return -1;
        }
        return tiles[y][x];
    }
    
    public function isMine(x:int, y:int):Boolean {
        if (x < 0 || x >= width || y < 0 || y >= height) {
            return false;
        }
        return tiles[y][x] == 9;
    }
    
    public function isRevealed(x:int, y:int):Boolean {
        if (x < 0 || x >= width || y < 0 || y >= height) {
            return false;
        }
        return revealed[y][x] == 1;
    }
    
    // シードフィル法を使って指定したマスとその周辺のマスをまとめて開く
    public function reveal(x:int, y:int, isRecursiveCall:Boolean = false):void {
        if (x < 0 || x >= width || y < 0 || y >= height) {
            return;
        }
        
        if (isMine(x, y) && isRecursiveCall) { 
            return;
        }
        
        // すでに開かれていたら関数を終了
        if (isRevealed(x, y))
            return;
        
        revealed[y][x] = 1;
        flags[y][x] = 0;
        
        // 再帰呼び出しであり、タイルが数字タイルだったら終了
        if (isRecursiveCall && tiles[y][x] != 0)
            return;
        
        // 上下左右のタイルを再帰的に開く
        reveal(x, y - 1, true);
        reveal(x + 1, y, true);
        reveal(x, y + 1, true);
        reveal(x - 1, y, true);
        
        // タイルが何もなしのタイルだったらナナメ方向のタイルも開く
        if (tiles[y][x] == 0) {
            reveal(x - 1, y - 1, true);
            reveal(x + 1, y - 1, true);
            reveal(x + 1, y + 1, true);
            reveal(x - 1, y + 1, true);
        }
    }
    
    public function revealAll(exceptMines:Boolean = false):void {
        for (var y:int = 0; y < height; y++) {
            for (var x:int = 0; x < width; x++) {
                if (exceptMines && isMine(x, y))
                    continue;
                revealed[y][x] = 1;
            }
        }
    }
    
    public function isComplete():Boolean {
        var count:int = 0;
        for (var y:int = 0; y < height; y++) {
            for (var x:int = 0; x < width; x++) {
                count += revealed[y][x];
            }
        }
        return (count + numMines >= width * height);
    }
    
    public function Board(width:int, height:int, numberOfMines:int) {
        this.width = width;
        this.height = height;
        this.numMines = numberOfMines;
        
        this.tiles = new Vector.<Vector.<int>>(height);
        this.revealed = new Vector.<Vector.<int>>(height);
        this.flags = new Vector.<Vector.<int>>(height);
        for (var y:int = 0; y < height; y++) {
            tiles[y] = new Vector.<int>(width);
            revealed[y] = new Vector.<int>(width);
            flags[y] = new Vector.<int>(width);
        }
    }
    
    public function init(startX:int, startY:int):void {
        var randMax:int = width * height;
        var r:int, x:int, y:int;
        
        // 爆弾を設置する
        for (var i:int = 0; i < numMines; i++) {
            do {
                r = Math.random() * randMax;
                x = r % width;
                y = r / width;
            } while (tiles[y][x] != 0 || (Math.abs(x - startX) < 2 && Math.abs(y - startY) < 2));
            tiles[y][x] = 9;
        }
        
        // 爆弾の周囲のマスに数字をセットする
        for (y = 0; y < height; y++) {
            for (x = 0; x < width; x++) {
                if (isMine(x, y))
                    continue;
                
                var count:int = 0;
                count += (isMine(x - 1, y - 1)) ? 1 : 0;
                count += (isMine(x    , y - 1)) ? 1 : 0;
                count += (isMine(x + 1, y - 1)) ? 1 : 0;
                count += (isMine(x - 1, y    )) ? 1 : 0;
                count += (isMine(x + 1, y    )) ? 1 : 0;
                count += (isMine(x - 1, y + 1)) ? 1 : 0;
                count += (isMine(x    , y + 1)) ? 1 : 0;
                count += (isMine(x + 1, y + 1)) ? 1 : 0;
                tiles[y][x] = count;
            }
        }
        
        inited = true;
    }
}

class Scene extends Sprite {
    public function Scene() {
        addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
    }
    
    protected function onAddedToStage(e:Event):void {
        removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
        BetweenAS3.tween(this, { alpha:1 }, { alpha:0 }, 1).play();
    }
    
    public function goTo(scene:Scene, removePreviousScenes:Boolean = true):void {
        if (this.parent == null)
            return;
        
        var parent:DisplayObjectContainer = this.parent;
        if (removePreviousScenes) {
            parent.removeChildren();
        }
        parent.addChild(scene);
    }
}

class BoardScene extends Scene {
    private var board:Board;
    
    private var background:BitmapData;
    
    private var surface:BitmapData;
    
    private var flagLayer:Sprite;
    
    private var cursorA:Shape;
    
    private var container:Sprite;
    
    public function BoardScene(board:Board) {
        super();
        this.board = board;
    }
    
    private function onGiveupClick(e:Event):void {
        goTo(new StartScene());
    }
    
    override protected function onAddedToStage(e:Event):void {
        init();
        super.onAddedToStage(e);
    }
    
    private function init():void {
        graphics.beginFill(0x0);
        graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
        graphics.endFill();
        
        var width:int = board.width * Tiles.size;
        var height:int = board.height * Tiles.size;
        
        background = new BitmapData(width, height, false);
        surface = new BitmapData(width, height, true, 0x0);

        // drawBackground(); // 初めてクリックした時に行う
        drawSurface();
        initCursor();
        flagLayer = new Sprite();

        container = new Sprite();
        container.addChild(new Bitmap(background));
        container.addChild(new Bitmap(surface));
        container.addChild(flagLayer);
        container.addChild(cursorA);
        addChild(container);
        
        container.x = (stage.stageWidth - container.width) / 2;
        container.y = (stage.stageHeight - container.height) / 2;
        
        container.addEventListener(MouseEvent.CLICK, onClick);
        container.addEventListener(MouseEvent.RIGHT_CLICK, onRightClick);
        container.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);

        var giveupButton:PushButton = new PushButton(this, 0, 0, "Give Up", onGiveupClick);
        giveupButton.x = (stage.stageWidth - giveupButton.width) / 2;
        giveupButton.y = stage.stageHeight - giveupButton.height;
    }
    
    private function drawBackground():void {
        for (var y:int = 0; y < board.height; y++) {
            for (var x:int = 0; x < board.width; x++) {
                var tile:int = board.getTile(x, y);
                var image:BitmapData = Tiles.getTile(tile);
                background.copyPixels(image, image.rect, new Point(x * Tiles.size, y * Tiles.size));
            }
        }
    }
    
    private function drawSurface():void {
        for (var y:int = 0; y < board.height; y++) {
            for (var x:int = 0; x < board.width; x++) {
                surface.copyPixels(Tiles.surface, Tiles.surface.rect, new Point(x * Tiles.size, y * Tiles.size));
            }
        }
    }
    
    private function initCursor():void {
        cursorA = new Shape();
        cursorA.graphics.beginFill(0xFFFFFF, 0.4);
        cursorA.graphics.drawRect(0, 0, Tiles.size, Tiles.size);
        cursorA.graphics.endFill();
    }
    
    private function update():void {
        var size:int = Tiles.size;
        
        flagLayer.graphics.clear();
        for (var y:int = 0; y < board.height; y++) {
            for (var x:int = 0; x < board.width; x++) {
                // draw surface
                if (board.isRevealed(x, y)) {
                    surface.fillRect(new Rectangle(x * size, y * size, size, size), 0x0);
                }
                
                // draw flags
                if (board.getFlag(x, y) == 1) {
                    flagLayer.graphics.beginBitmapFill(Tiles.flag);
                    flagLayer.graphics.drawRect(x * size, y * size, size, size);
                    flagLayer.graphics.endFill();
                } else if (board.getFlag(x, y) == 2) {
                    flagLayer.graphics.beginBitmapFill(Tiles.question);
                    flagLayer.graphics.drawRect(x * size, y * size, size, size);
                    flagLayer.graphics.endFill();
                }
            }
        }
    }
    
    private function onClick(e:MouseEvent):void {
        var x:int = e.localX / Tiles.size;
        var y:int = e.localY / Tiles.size;
        
        // 最初のマスが爆弾になるのを避けるため、ここでボードの初期化を行う
        if (!board.inited) {
            board.init(x, y);
            drawBackground();
        }
        
        if (!board.isRevealed(x, y) && board.getFlag(x, y) == 0) {
            board.reveal(x, y);
            
            if (board.isMine(x, y)) {
                board.revealAll();
                goTo(new GameOverScene(), false);
            } else if (board.isComplete()) {
                board.revealAll(true);
                goTo(new GameClearScene(), false);
            }
            
            update();
        }
    }
    
    private function onRightClick(e:MouseEvent):void {
        var x:int = e.localX / Tiles.size;
        var y:int = e.localY / Tiles.size;
        
        if (!board.isRevealed(x, y)) {
            board.setFlag(x, y);
            update();
        }
    }
    
    private function onMouseMove(e:MouseEvent):void {
        if (e.localX >= container.width || e.localY >= container.height)
            return;
        
        var x:int = e.localX / Tiles.size;
        var y:int = e.localY / Tiles.size;
        
        if (board.isRevealed(x, y)) {
            cursorA.visible = false;
        } else {
            cursorA.visible = true;
            cursorA.x = x * Tiles.size;
            cursorA.y = y * Tiles.size;
        }
    }
}

class StartScene extends Scene { 
    public function StartScene() {
        super();
    }
    
    private function init():void {
        // background
        graphics.beginFill(0x0, 1);
        graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
        graphics.endFill();
        
        // title
        var title:TextField = new TextField();
        title.defaultTextFormat = new TextFormat("_typeWriter", 24, 0xFFFFFF, true);
        title.text = "M Sweeper";
        title.autoSize = "left";
        title.selectable = false;
        title.x = (stage.stageWidth - title.width) / 2;
        title.y = (stage.stageHeight - title.height) / 2;
        addChild(title);
        
        // buttons
        var x:Number = (stage.stageWidth - 100) / 2;
        var y:Number = title.y + 60;
        var button1:PushButton = new PushButton(this, x, y, "EASY", onButtonClick);
        var button2:PushButton = new PushButton(this, x, y + 30, "NORMAL", onButtonClick);
        var button3:PushButton = new PushButton(this, x, y + 60, "HARD", onButtonClick);
    }
    
    override protected function onAddedToStage(e:Event):void {
        init();
        super.onAddedToStage(e);
    }
    
    private function onButtonClick(e:Event):void {
        var target:PushButton = e.target as PushButton;
        switch (target.label) {
            case "EASY":
                goTo(new BoardScene(new Board(9, 9, 10)));
                break;
            case "NORMAL":
                goTo(new BoardScene(new Board(16, 16, 40)));
                break;
            case "HARD":
                goTo(new BoardScene(new Board(22, 22, 99)));
                break;
        }
    }
}

class GameOverScene extends Scene {
    public function GameOverScene() {
        super();
        addEventListener(MouseEvent.CLICK, onClick);
    }
    
    override protected function onAddedToStage(e:Event):void {
        // background
        graphics.beginFill(0xFF0000, 0.6);
        graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
        graphics.endFill();
        
        // text
        var tf:TextField = new TextField();
        tf.defaultTextFormat = new TextFormat("_typeWriter", 36, 0xFFFFFF, true);
        tf.autoSize = "left";
        tf.text = "Game Over";
        tf.selectable = false;
        tf.x = (stage.stageWidth - tf.width) / 2;
        tf.y = (stage.stageHeight - tf.height) / 2;
        addChild(tf);
        
        super.onAddedToStage(e);
    }

    private function onClick(e:MouseEvent):void {
        goTo(new StartScene());
    }
}

class GameClearScene extends Scene { 
    public function GameClearScene() {
        super();
        addEventListener(MouseEvent.CLICK, onClick);
    }
    
    override protected function onAddedToStage(e:Event):void {
        // background
        graphics.beginFill(0x0000FF, 0.6);
        graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
        graphics.endFill();
        
        // text
        var tf:TextField = new TextField();
        tf.defaultTextFormat = new TextFormat("_typeWriter", 36, 0xFFFFFF, true);
        tf.autoSize = "left";
        tf.text = "Game Clear!";
        tf.selectable = false;
        tf.x = (stage.stageWidth - tf.width) / 2;
        tf.y = (stage.stageHeight - tf.height) / 2;
        addChild(tf);
        
        super.onAddedToStage(e);
    }

    private function onClick(e:MouseEvent):void {
        goTo(new StartScene());
    }
}

class Tiles {
    private static var initted:Boolean = Tiles._init();
    
    public static var size:int = 16;
    
    public static var tiles:Array;
    
    public static var surface:BitmapData;
    
    public static var flag:BitmapData;
    
    public static var question:BitmapData;
    
    public static function getTile(id:int):BitmapData {
        if (id < 0 || id >= tiles.length)
            return null;
        return tiles[id];
    }
    
    private static function _init():Boolean {
        var base:Shape = new Shape();
        
        base.graphics.beginFill(0xA9A9A9); // dark gray
        base.graphics.drawRect(0, 0, size, size);
        base.graphics.beginFill(0xC0C0C0); // silver
        base.graphics.drawRect(1, 1, size - 1, size - 1);
        base.graphics.endFill();
        
        var textColors:Array = [
            0,
            0x1E90FF, // 1
            0x008000, // 2
            0x8B0000, // 3
            0x000080, // 4
            0x800000, // 5
            0xDAA520, // 6
            0xFF0000, // 7
            0x800080, // 8
            0xFF0000, // Mine
            0xFF0000, // Flag
            0x00FFFF];  // ?
        
        var textField:TextField = new TextField();
        textField.defaultTextFormat = new TextFormat("_typeWriter", 12, 0x0, true);
        textField.autoSize = "left";
        var textMatrix:Matrix = new Matrix();
        tiles = [];
        for (var i:int = 0; i < 12; i++) {
            tiles[i] = new BitmapData(size, size, true, 0x0);
            
            // 背景を塗る
            if (i < 10) {
                tiles[i].draw(base);
            }
            
            // 1~8の番号を振る
            if (1 <= i && i <= 8) {
                textField.text = i.toString();
            } else if (i == 9) {
                textField.text = "*";
            } else if (i == 10) {
                textField.text = "!";
            } else if (i == 11) {
                textField.text = "?";
            }
            textField.textColor = textColors[i];
            textMatrix.tx = (size - textField.width) / 2;
            textMatrix.ty = (size - textField.height) / 2;
            tiles[i].draw(textField, textMatrix);
        }
        
        flag = tiles[10];
        question = tiles[11];
        
        createSurface();
        
        return true;
    }
    
    private static function createSurface():void {
        surface = new BitmapData(size, size);
        
        var matrix:Matrix = new Matrix();
        matrix.createGradientBox(size - 2, size - 2, 45);
        var tile:Shape = new Shape();
        tile.graphics.beginFill(0xCCCCCC);
        tile.graphics.drawRect(0, 0, size - 1, size - 1);
        tile.graphics.beginFill(0x444444);
        tile.graphics.drawRect(1, 1, size - 1, size - 1);
        tile.graphics.beginGradientFill(GradientType.LINEAR, [0xAAAAAA, 0x888888], [1.0, 1.0], [0, 255], matrix);
        tile.graphics.drawRect(1, 1, size - 2, size - 2);
        tile.graphics.endFill();
        
        surface.draw(tile);
    }
}