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

男女男男女男女

男女男男女男女
*
*    - ルール
*      - 異性が向かい合うように座らせてください
*      - 左から詰めて座ります
*      - 同じグループを重複して使えます
*      - 男女の人数が一致したらパーティ開始 (クリア) です
*
*    - 操作方法など
*      - 下 3 つのグループボタンをクリックすると座ります
*      - "1" "2" "3" や "z" "x" "c" キーでもいいです
*      - undo は "u" か BS
*      - 全 5 面です (ちゃんと解けます)
Get Adobe Flash player
by wondermame 24 Jul 2010
/**
 * Copyright wondermame ( http://wonderfl.net/user/wondermame )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/wcnb
 */

/*
 *  男女男男女男女
 *
 *    - ルール
 *      - 異性が向かい合うように座らせてください
 *      - 左から詰めて座ります
 *      - 同じグループを重複して使えます
 *      - 男女の人数が一致したらパーティ開始 (クリア) です
 *
 *    - 操作方法など
 *      - 下 3 つのグループボタンをクリックすると座ります
 *      - "1" "2" "3" や "z" "x" "c" キーでもいいです
 *      - undo は "u" か BS
 *      - 全 5 面です (ちゃんと解けます)
 */

package {
    import flash.display.Sprite;
    import flash.events.KeyboardEvent;
    import net.wonderfl.score.basic.BasicScoreForm;
    import net.wonderfl.score.basic.BasicScoreRecordViewer;

    public class main extends Sprite {
        public function main() {
            stage.align = "TL";
            stage.scaleMode = "noScale";
            var game:Game = new Game(stage.stageWidth / 10, stage.stageHeight / 10, view, submit);
            addChild(game);
            stage.addEventListener(KeyboardEvent.KEY_DOWN, game.keydown);
        }

        private function view():void {
            var x: int = (stage.stageWidth  - BasicScoreRecordViewer.WIDTH ) / 2;
            var y: int = (stage.stageHeight - BasicScoreRecordViewer.HEIGHT) / 2;
            new BasicScoreRecordViewer(this, x, y, "RANKING", 50);
        }

        private function submit(party:int):void {
            var x: int = (stage.stageWidth  - BasicScoreForm.WIDTH ) / 2;
            var y: int = (stage.stageHeight - BasicScoreForm.HEIGHT) / 2;
            new BasicScoreForm(this, x, y, party, "YOUR SCORE");
        }
    }
}

import flash.geom.Matrix;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.text.TextFormatAlign;
import flash.text.TextFieldAutoSize;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.display.Graphics;
import flash.display.SimpleButton;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.KeyboardEvent;

class Game extends Sprite {
    /* 問題データ */
    private var parties:Array = [
        [ ["a","aa"], ["aaa","a"], ["aa","bb"] ],
        [ ["a","baaa"], ["a","ab"], ["aba","a"] ],
        [ ["abb","a"], ["b","abb"], ["a","bb"] ],
        [ ["abb","a"], ["b","abb"], ["a","b"] ],
        [ ["baab","b"], ["a","aab"], ["ab","a"] ],
    ];
    private var party:int = 0;                // 現在の問題の番号
    private var pairs:Array;                  // 現在の問題
    private var upper:String, lower:String;   // 上下の列の状態
    private var moves:Array;                  // 今までの手順

    private var clear:Boolean;                // クリア状態のフラグ
    private var depth:int;                    // 画面からはみ出ている数
    private var screen:Sprite;                // 上下の列を持つダミースプライト
    private var groups:Array;                 // 表示されている Group 群
    private var uppers:Array, lowers:Array;   // 上下の列に表示されている Person 群
    private var unmatched_marks:Array;        // ×マークの UnmatchedMark 群
    private var heart_marks:Array;            // ハートマーク
    private var buttons:Array;                // ボタン 4 つ
    private var upper_vgroups:Array;          // 上側のプレビュー Group 3 つ
    private var lower_vgroups:Array;          // 下側のプレビュー Group 3 つ
    private var unmatched:Array;              // プレビュー Group で×マークが出る位置
    private var count:int;                    // マークアニメーション用カウンタ
    private var screen_scale:Number;          // 論理上の screen 縮尺
    private var screen_x:Number;              // 論理上の screen 位置
    private var screen_count:int;             // screen アニメーション用カウンタ
    private var party_name:TextField;         // 問題番号表示
    private var clear_msg:TextField;          // クリアメッセージ表示
    private var traceField:TextField;

    private var view:Function, submit:Function;  // スコア

    public function Game(_scaleX:Number, _scaleY:Number, _view:Function, _submit:Function) {
        // 画面の基本的な初期化
        scaleX = _scaleX;
        scaleY = _scaleY;
        view = _view;
        submit = _submit;
        var g:Graphics = this.graphics;
        g.beginFill(0x333333);
        g.drawRect(0, 0, 10, 10);
        g.endFill();
        traceField = create_text("", 20, 10, 1);
        this.addChild(traceField);

        // イベントハンドラ設定
        count = screen_count = 0;
        addEventListener(Event.ENTER_FRAME, animate);

        // ステージ番号
        party_name = create_text("", 20, 10, 1);
        party_name.y = 1;
        addChild(party_name);

        // クリアメッセージ表示
        clear_msg = create_text("", 30, 10, 1);
        clear_msg.y = 4.5;
        addChild(clear_msg);

        // ゲームスタート
        party = 0;
        setup();
    }

    // 各問題の初期化
    private function setup():void {
        clear = false;
        depth = 0;
        pairs = parties[party];
        upper = "";
        lower = "";
        moves = [];

        screen = new Sprite();
        addChild(screen);
        groups = [];
        uppers = [];
        lowers = [];
        unmatched_marks = [];
        heart_marks = [];
        upper_vgroups = [];
        lower_vgroups = [];
        buttons = [];
        unmatched = [];

        make_buttons();
        make_groups();
        make_unmatched();
        screen.y = 2;
        update();
        party_name.text = "Party " + (party + 1) + " / " + parties.length;
        clear_msg.text = "";
    }

    // 各問題の廃棄
    private function dispose():void {
        var i:int;
        for (i = 0; i < buttons.length; i++) {
            removeChild(buttons[i]);
        }
        removeChild(screen);
        Person.clear();
    }

    // 問題クリア
    private function next_party():void {
        dispose();
        if (++party == parties.length) {
            submit(party);
            party = 0;
        }
        setup();
    }

    // 画面構成補助: TextField 作成
    private function create_text(msg:String, weight:int, width:Number, height:Number):TextField {
        var text:TextField = new TextField();
        text.width  = width * scaleX;
        text.height = height * scaleY;
        var format:TextFormat = new TextFormat();
        format.align = TextFormatAlign.CENTER;
        format.size = weight;
        format.color = 0xffffff;
        text.defaultTextFormat = format;
        text.selectable = false;
        text.scaleX = 1 / scaleX;
        text.scaleY = 1 / scaleY;
        text.text = msg;
        return text;
    }

    // 画面構成補助: SimpleButton 作成
    private function create_button(x:Number, y:Number, make_state:Function, click:Function):SimpleButton {
        var button:SimpleButton = new SimpleButton();
        button.x = x;
        button.y = y;
        var state:Sprite = make_state();
        state.alpha = 0.5;
        button.upState = state;
        state = make_state();
        button.overState = button.downState = button.hitTestState = state;
        buttons.push(button);
        addChild(button);
        button.addEventListener(MouseEvent.CLICK, click);
        return button;
    }

    // 画面構成: ボタン
    private function make_buttons():void {
        var idx:int, margin:Number, x:Number;
        var button:SimpleButton;

        // マージンの計算
        for (idx = 0, margin = 10; idx < 3; idx++) {
            margin -= Math.max(pairs[idx][0].length, pairs[idx][1].length);
        }
        margin /= 4;

        // 問題の配置
        x = margin;
        for (idx = 0; idx < 3; idx++) {
            button = create_button(x, 6, function():Sprite {
                return new Button(idx, pairs[idx]);
            }, create_callback(move, idx));
            button.addEventListener(MouseEvent.MOUSE_OUT , create_callback(preview, -1));
            button.addEventListener(MouseEvent.MOUSE_OVER, create_callback(preview, idx));
            x += Math.max(pairs[idx][0].length, pairs[idx][1].length) + margin;
        }
        function create_callback(func:Function, arg:int):Function {
            return function():void { func(arg); };
        }

        // Undo ボタンの配置
        button = create_button(1, 8.25, make_button_shape("undo", 8, 0.5), function():void { undo(); });
        button = create_button(1, 9, make_button_shape("view ranking", 3.75, 0.5), function():void { view(); });
        button = create_button(5.25, 9, make_button_shape("submit your score", 3.75, 0.5), function():void { submit(party); });

        function make_button_shape(msg: String, width:Number, height:Number):Function {
            return function():Sprite { 
                var sprite:Sprite = new Sprite();
                var g:Graphics = sprite.graphics;
                g.beginFill(0x999999);
                g.drawRoundRect(0, 0, width, height, 0.5);
                g.endFill();
                var text:TextField = create_text(msg, 20, width, height);
                sprite.addChild(text);
                return sprite;
            };
        }
    }

    // 画面構成: プレビュー用グループ
    private function make_groups():void {
        var idx:int;
        for (idx = 0; idx < 3; idx++) {
            upper_vgroups[idx] = new Group(pairs[idx][0], screen, null, true , true, idx);
            lower_vgroups[idx] = new Group(pairs[idx][1], screen, null, false, true, idx);
        }
    }

    // 画面構成: ×マーク
    private function make_unmatched():void {
        var i:int;
        for (i = 0; i < 4; i++) {
            var mark:UnmatchedMark = new UnmatchedMark(i);
            unmatched_marks[i] = mark;
            screen.addChild(mark);
        }
    }

    // 配置変更後の状態更新
    private function update():void {
        var i:int, idx:int, next_depth:int;
        // プレビュー用グループの再配置
        for (idx = 0; idx < pairs.length; idx++) {
            upper_vgroups[idx].x = uppers.length;
            lower_vgroups[idx].x = lowers.length;
            move(idx, unmatched[idx] = []);
        }
        // 画面からはみ出ている数の再設定
        next_depth = Math.min(uppers.length, lowers.length);
        // 配置の場合はハートマークを増やす
        for (i = depth; i < next_depth; i++) {
            var heart:HeartMark = new HeartMark();
            screen.addChild(heart);
            heart.x = i;
            heart_marks.push(heart);
        }
        // undo の場合は浮かれ状態を解除する
        for (i = next_depth; i < depth; i++) {
            if (uppers[i]) uppers[i].redraw(0, 0);
            if (lowers[i]) lowers[i].redraw(0, 0);
            screen.removeChild(heart_marks.pop());
        }
        depth = next_depth;

        // 縮尺の調整
        // depth-1 より右が見えていないといけない
        var bottom:int = depth - 1;
        // Math.min(uppers.length, lowers.length) + 5 より左が見えていないといけない
        // Math.max(uppers.length, lowers.length) + 1 より左が見えていないといけない
        var top:int = Math.max(Math.min(uppers.length, lowers.length) + 4, uppers.length, lowers.length) + 1;
        // 余裕があれば調整
        if (top < bottom + 10) bottom = top - 10;
        if (bottom < 0) { bottom = 0; top = 10; }
        screen_scale = 10.0 / (top - bottom);
        screen_x = -bottom * screen_scale;
        screen_count = 8;

        // プレビュー用グループを一旦消す
        preview(-1);
    }

    // 配置
    private function move(idx:int, test:Array=null):void {
        if (clear) return;
        var upper2:String = upper + pairs[idx][0];
        var lower2:String = lower + pairs[idx][1];
        var i:int, end:int = Math.min(upper2.length, lower2.length);
        var well:Boolean = true;
        for (i = 0; i < end; i++) {
            if (upper2.charAt(i) != lower2.charAt(i)) {
                well = false;
                if (test) test[i] = true; else break;
            }
        }
        if (!test && well) {
            upper = upper2.substring(end);
            lower = lower2.substring(end);
            moves.push(idx);

            groups.push(new Group(pairs[idx][0], screen, uppers, true , false, idx));
            groups.push(new Group(pairs[idx][1], screen, lowers, false, false, idx));

            if (upper.length == 0 && lower.length == 0) {
                clear = true;
                clear_msg.text = "Let's party!";
            }

            update();
        }
    }

    // 配置の取り消し
    private function undo():void {
        if (clear || moves.length == 0) return;
        var i:int, idx:int = moves.pop();
        var upper2:String = pairs[idx][0];
        var lower2:String = pairs[idx][1];
        var upper_len:int = upper2.length - upper.length;
        var lower_len:int = lower2.length - lower.length;
        var len:int = Math.min(upper_len, lower_len);
        if (len > 0) {
            lower = upper2.substring(0, upper_len - len);
            upper = lower2.substring(0, lower_len - len);
        }
        else {
            if (upper.length > 0) {
                upper = lower2 + upper.substring(0, -upper_len);
                lower = "";
            }
            else {
                lower = upper2 + lower.substring(0, -lower_len);
                upper = "";
            }
        }

        for (i = 0; i < upper2.length; i++) uppers.pop();
        for (i = 0; i < lower2.length; i++) lowers.pop();
        screen.removeChild(groups.pop());
        screen.removeChild(groups.pop());
        update();
    }

    // 配置のプレビュー
    private function preview(idx:int):void {
        var idx2:int;
        if (clear) idx = -1;
        for (idx2 = 0; idx2 < pairs.length; idx2++) {
            upper_vgroups[idx2].visible = (idx == idx2);
            lower_vgroups[idx2].visible = (idx == idx2);
        }
        var i:int;
        for (i = 0; i < 4; i++) {
            if (idx >= 0 && unmatched[idx][i]) {
                unmatched_marks[i].visible = true;
                unmatched_marks[i].x = depth + i;
                screen.addChildAt(unmatched_marks[i], screen.numChildren - 1);
            }
            else {
                unmatched_marks[i].visible = false;
            }
        }
    }

    // キー押下イベントハンドラ
    public function keydown(e:KeyboardEvent):void {
        switch (e.keyCode) {
            case 85: case 8: undo(); break;
            case 49: case 97: case 90: preview(0); move(0); break;
            case 50: case 98: case 88: preview(1); move(1); break;
            case 51: case 99: case 67: preview(2); move(2); break;
            case 72: Person.toggle(); break;
        }
    }

    // 画面の更新
    private function animate(e:Event):void {
        if (screen_count > 0) {
            var factor:Number = 6 / (screen_count + 1) / (2 * screen_count + 1);
            screen.scaleX += (screen_scale - screen.scaleX) * factor;
            screen.x += (screen_x - screen.x) * factor;
            screen_count--;
        }
        else if (clear) {
            screen.x += 0.25;
            if (screen.x > 10) {
                 next_party();
            }
        }
        count = (count + 1) % 24;
        if (count == 0 || count == 12) {
            var i:int = Math.max(depth - 10, 0);
            var pulse:int = count == 12 ? 1 : -1;
            if (clear) i = 0;
            for (; i < depth; i++) {
                if (uppers[i]) uppers[i].redraw(pulse, -1);
                if (lowers[i]) lowers[i].redraw(pulse,  1);
                var heart:HeartMark = heart_marks[i];
                heart.x = pulse * 0.2 + i;
                heart.y = pulse * 0.1;
            }
        }
    }
}

// ペアを配置するボタン
class Button extends Sprite {
    public function Button(idx:int, pair:Array) {
        var g:Graphics = this.graphics;
        g.beginFill(0x999999);
        g.drawRoundRect(0, 0, Math.max(pair[0].length, pair[1].length), 2, 0.2);
        g.endFill();
        addChild(new Group(pair[0], null, null, true , false, idx));
        addChild(new Group(pair[1], null, null, false, false, idx));
    }
}

// 数人を角丸四角で囲んだグループ
class Group extends Sprite {
    private var color:Array = [ 0xffcccc, 0xccffcc, 0xccccff ];
    public function Group(seq:String, screen:Sprite, persons:Array, upper_p:Boolean, virtual_p:Boolean, background:int) {
        if (screen) screen.addChild(this);

        var y:int = upper_p ? 0 : 1;
        var g:Graphics = this.graphics;
        g.beginFill(color[background]);
        g.drawRoundRect(0.05, y + 0.05, seq.length - 0.1, 0.9, 0.5);
        g.endFill();
        
        if (persons) this.x = persons.length;
        if (virtual_p) this.alpha = 0.3;

        var i:int;
        for (i = 0; i < seq.length; i++) {
            var person:Person = new Person(seq.charAt(i) == "a", upper_p);
            addChild(person);
            person.x = i;
            person.y = y;
            if (persons) persons.push(person);
        }
    }
}

// 男または女
class Person extends Sprite {
    private static var all_sprites:Array = [], hetero:Boolean = true;
    private var sprite:Sprite;
    private var male_p:Boolean, upper_p:Boolean;
    public function Person(male_p:Boolean, upper_p:Boolean) {
        all_sprites.push(this);
        this.male_p = male_p;
        this.upper_p = upper_p;
        sprite = new Sprite();
        addChild(sprite);
        sprite.x = sprite.y = 0.5;
        draw();
    }
    private function draw():void {
        var g:Graphics = sprite.graphics;
        g.clear();
        g.beginFill((male_p == upper_p) || !hetero ? 0x0000ff : 0xff0000);
        g.drawCircle(0, -0.2, 0.15);
        if (male_p == upper_p) {
            g.moveTo(0, 0.35);
            g.lineTo(-0.2, -0.05);
            g.lineTo(0.2, -0.05);
            g.lineTo(0, 0.35);
        }
        else {
            g.moveTo(0, -0.05);
            g.lineTo(-0.2, 0.35);
            g.lineTo(0.2, 0.35);
            g.lineTo(0, -0.05);
        }
        g.endFill();
    }
    public function redraw(type:int, slide:int):void {
        var mat:Matrix = sprite.transform.matrix;
        mat.c = -0.3 * type;
        sprite.transform.matrix = mat;
        sprite.y = 0.5 - 0.15 * slide;
    }
    public static function toggle():void {
        var i:int;
        hetero = !hetero;
        for (i = 0; i < all_sprites.length; i++) {
            all_sprites[i].draw();
        }
    }
    public static function clear():void {
        while (all_sprites.length > 0) all_sprites.pop();
    }
}

// ×マーク
class UnmatchedMark extends Sprite {
    public function UnmatchedMark(x:int) {
        this.x = x;
        this.y = 0.5;
        var g:Graphics = this.graphics;
        g.beginFill(0x990000);
        g.moveTo(0.1, 0.0);
        g.lineTo(0.5, 0.4);
        g.lineTo(0.9, 0.0);
        g.lineTo(1.0, 0.1);
        g.lineTo(0.6, 0.5);
        g.lineTo(1.0, 0.9);
        g.lineTo(0.9, 1.0);
        g.lineTo(0.5, 0.6);
        g.lineTo(0.1, 1.0);
        g.lineTo(0.0, 0.9);
        g.lineTo(0.4, 0.5);
        g.lineTo(0.0, 0.1);
        g.lineTo(0.1, 0.0);
        g.endFill();
    }
}

// ハートマーク
class HeartMark extends Sprite {
    public function HeartMark() {
        var g:Graphics = this.graphics;
        g.lineStyle(0, 0xcc0000);
        g.beginFill(0xff6666);
        g.moveTo(0.5, 0.85);
        g.curveTo(0.61,0.74,0.66,0.84);
        g.curveTo(0.70,0.96,0.5,1.08);
        g.curveTo(0.30,0.96,0.34,0.84);
        g.curveTo(0.39,0.74,0.5,0.85);
        g.endFill();
    }    
}