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

くま、ソリテアになる

古典的パズル「ソリテア」(2010-03-26)
--------------------------------
To do:
1) せめて Undo くらいサポートせにゃ
2) それなら棋譜を残すようしたい
3) PLAY AGAIN ボタンつけなきゃ
4) 手詰りかどうかの判定もしたい
--------------------------------
Get Adobe Flash player
by tenasaku 26 Mar 2010
/**
 * Copyright tenasaku ( http://wonderfl.net/user/tenasaku )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/izMD
 */

// 古典的パズル「ソリテア」(2010-03-26)
// --------------------------------
// To do:
// 1) せめて Undo くらいサポートせにゃ
// 2) それなら棋譜を残すようしたい
// 3) PLAY AGAIN ボタンつけなきゃ
// 4) 手詰りかどうかの判定もしたい
// --------------------------------

package {

	import flash.display.*;
	import flash.events.*;
	import flash.geom.*;

	public class Main extends Sprite {

		private static const NO_DRAG:int = -1;
		private static const _H:Number = 66.4;
		private static const _V:Number = 66.4;
		private static const _dimpleRadius:Number = 24;
		private static const _boundsRect:Rectangle 
			= new Rectangle( 0, 0, _H*7, _V*7 );
		private static const _bgColor:uint = 0xccff99;
		private static const _dimpleColor:uint = 0xffffff;
		private static const _borderColor:uint = 0x008000;

		private var status:Array; // 各マス目の状態の配列
		private var icon:Array; // 各マス目の表示オブジェクトの配列
		private var dragged:KumaIcon; // ドラッグ中に表示されるオブジェクト
		private var dragFrom:int; // どのマス目からドラッグを開始したかを記憶
		private var lastMove:uint; // 直前の一手を記憶

		// どのマス目がクリックされたかを判定する
		private function whichDimple(e:MouseEvent):int {
			var i:int,result:int;
			i = 0;
			while ( i < 49 ) {
				var h:int = i%7;
				var v:int = Math.floor(i/7);
				var dx:Number = e.stageX - _H*(h+0.5);
				var dy:Number = e.stageY - _V*(v+0.5);
				if ( Math.sqrt(dx*dx+dy*dy) < _dimpleRadius ) {
					result = i;
					break;
				} else {
					result = NO_DRAG;
					++i;
				}
			}
			return result;
		}

		// ボードの状態と表示の初期化
		private function initBoard():void {
			var i:int,h:int,v:int;
			status = new Array(49);
			icon = new Array(49);
			for ( i = 0; i < 49; ++i ) {
				h = i%7;
				v = Math.floor(i/7);
				if ( ( Math.abs(h-3)< 2 ) || ( Math.abs(v-3)< 2 ) ) {
					status[i] = ( (h==3)&&(v==3) )?0:1;
					icon[i] = new KumaIcon();
					icon[i].x = _H*(h+0.5);
					icon[i].y = _V*(v+0.5);
					icon[i].visible = !(status[i] == 0);
					this.addChild(icon[i]);
					this.graphics.lineStyle(3,_borderColor);
					this.graphics.beginFill(_dimpleColor);
					this.graphics.drawCircle(icon[i].x,icon[i].y,_dimpleRadius);
					this.graphics.endFill();
				} else {
					status[i] = 2;
					icon[i] = null;
				}
			}
		}

		// マウスボタンが押されたとき
		private function onMouseDown(e:MouseEvent):void {
			dragged.x = e.stageX;
			dragged.y = e.stageY;
			dragFrom = whichDimple(e);
			if ( (dragFrom != NO_DRAG) &&  (status[dragFrom] == 1) ) {
				icon[dragFrom].visible = false;
				dragged.visible = true;
				stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
				stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
				dragged.startDrag(false,_boundsRect);
			} else {
				dragFrom = NO_DRAG;
			}
		}

		// マウスボタンが離されたとき
		private function onMouseUp(e:MouseEvent):void {
			dragged.stopDrag();
			dragged.visible = false;
			var dragTo:int = whichDimple(e);
			if ( moveOK(dragFrom,dragTo) ) {
				makeMove(dragFrom,dragTo);
			} else {
				if ( dragFrom != NO_DRAG ) {
					icon[dragFrom].visible = true;
				}
			}
			stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
		}
		
		// ドラッグ中
		private function onMouseMove(e:MouseEvent):void {
			e.updateAfterEvent();
		}

		// i1 から i2 への動きが可能か判定
		private function moveOK(i1:int,i2:int):Boolean {
			if ( ( i1 < 0 ) || ( i1 >= 49 ) ) { // 出発点が盤上にない
				return false;
			}
			 if ( ( i2 < 0 ) || ( i2 >= 49 ) ) { // 行き先が盤上にない
				return false;
			}
			var h1:int = i1%7;
			var v1:int = Math.floor(i1/7);
			var h2:int = i2%7;
			var v2:int = Math.floor(i2/7);
			if ( Math.max(Math.abs(h1-h2),Math.abs(v1-v2)) != 2 ) { // 二個となりでない
				return false;
			}
			if ( (h1 != h2) && (v1 != v2) ) { // 同じ列や行にない
				return false;
			}
			if ( ( status[i1] != 1 ) ) { // 出発点に玉がない
				return false;
			}
			if ( ( status[i2] != 0 ) ) { // 行き先にすでに玉がある
				return false;
			}
			if ( status[(i1+i2)>>1] != 1 ) { // あいだの一個がない
				return false;
			}
			// 以上のどれでもないときだけ, 真を返す
			return true;
		}

		// i1 から i2 への実際の移動処理 
		// ここでは条件のチェックはしない
		private function makeMove(i1:int,i2:int):void {
			status[i1] = 0;
			status[i2] = 1;
			status[(i1+i2)>>1] = 0;
			icon[i1].visible = false;
			icon[i2].visible = true;
			icon[(i1+i2)>>1].visible = false;
			lastMove = (i1 & 63)<<8|(i2 & 63);
		}

		// プログラム全体の初期化動作
		private function initialize(e:Event):void {
			this.removeEventListener(Event.ADDED_TO_STAGE, initialize);
			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;
			// 全体を背景色で塗る
			this.graphics.clear();
			this.graphics.lineStyle(NaN);
			this.graphics.beginFill(_bgColor);
			this.graphics.drawRect(0,0,_H*7,_V*7);
			this.graphics.endFill();
			// グローバル変数の初期化
			dragFrom = NO_DRAG;
			lastMove = 0;
			// ボードの初期化と表示
			initBoard();
			// ドラッグ中のアイコンの初期化と非表示設定
			dragged = new KumaIcon();
			dragged.visible = false;
			this.addChild(dragged);
			// イベントリスナーの登録
			stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
		}

		// エントリー・ポイント
		public function Main():void {
			if ( stage != null ) {
				initialize(null);
			} else {
				this.addEventListener(Event.ADDED_TO_STAGE, initialize);
			}
		}

	} // end of class Main
} // end of package

// クマ顔アイコン 新バージョン
import flash.display.*;
class KumaIcon extends Sprite {
	private static const _borderColor:uint = 0x000000;
	private static const _fillColor:uint = 0x800000;
	public function KumaIcon():void {
		this.graphics.clear();
		this.graphics.lineStyle(NaN);
		this.graphics.beginFill(_fillColor);
		this.graphics.drawCircle(0,0,20);
		this.graphics.endFill();
		this.graphics.beginFill(_fillColor);
		this.graphics.drawCircle(14,-14,8);
		this.graphics.endFill();
		this.graphics.beginFill(_fillColor);
		this.graphics.drawCircle(-14,-14,8);
		this.graphics.endFill();
		this.graphics.beginFill(0xffffff);
		this.graphics.drawEllipse(-8,0,16,15);
		this.graphics.endFill();
		this.graphics.beginFill(_borderColor);
		this.graphics.drawEllipse(-2,2,4,3);
		this.graphics.endFill();
		this.graphics.beginFill(_borderColor);
		this.graphics.drawEllipse(-12,-5,3,4);
		this.graphics.endFill();
		this.graphics.beginFill(_borderColor);
		this.graphics.drawEllipse( 12,-5,-3,4);
		this.graphics.endFill();
		this.graphics.lineStyle(1,_borderColor);
		this.graphics.moveTo(-4, 12);
		this.graphics.curveTo( 0, 10, 0, 6);
		this.graphics.curveTo( 0, 10, 4, 12);
	}
}