ナンバーパズル
/**
* Copyright yamadori ( http://wonderfl.net/user/yamadori )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/pRru
*/
/*
数字を順番に並べ替えるあのパズルです。
空白に隣接してるパネルをクリックすると移動します。
また、NumericStepperで縦横の数を調整出来ます。
(縦横ともに最小2、最大5)
RESETボタンで配置し直します。
*/
package
{
import flash.display.Sprite;
import com.bit101.components.NumericStepper;
import com.bit101.components.Label;
import com.bit101.components.PushButton;
import flash.events.Event;
public class Main extends Sprite
{
private var board:Board;
private var wNum:NumericStepper;
private var hNum:NumericStepper;
public function Main()
{
graphics.beginFill(0xFFFFFF);
graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
board = new Board();
addChild(board);
board.x = 20;
board.y = 20;
wNum = new NumericStepper(this, 20);
hNum = new NumericStepper(this);
wNum.scaleX = wNum.scaleY = hNum.scaleX = hNum.scaleY = 1.2;
hNum.x = wNum.x + wNum.width*wNum.scaleX + 20;
wNum.y = hNum.y = stage.stageHeight - wNum.height*wNum.scaleY - 20;
wNum.minimum = hNum.minimum = 2;
wNum.maximum = hNum.maximum = 5;
var wLabel:Label = new Label(this, 20, 0, "wNum");
var hLabel:Label = new Label(this, hNum.x, 0, "hNum");
wLabel.scaleX = wLabel.scaleY = hLabel.scaleX = hLabel.scaleY = 1.5;
wLabel.y = hLabel.y = wNum.y - wLabel.height*wLabel.scaleY;
var button:PushButton = new PushButton(this, 0, 0, "RESET", reset);
button.scaleX = button.scaleY = 1;
button.x = hNum.x + hNum.width*hNum.scaleX + 20;
button.y = stage.stageHeight - button.height*button.scaleY - 20;
}
private function reset(e:Event = null):void
{
board.wNum = wNum.value;
board.hNum = hNum.value;
board.init();
}
}
}
import flash.display.Sprite;
import flash.filters.BevelFilter;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.events.MouseEvent;
import frocessing.math.Random;
import org.libspark.betweenas3.BetweenAS3;
import org.libspark.betweenas3.tweens.ITween;
import com.bit101.components.Label;
import flash.events.Event;
class Board extends Sprite
{
public var wNum:int = 4;
public var hNum:int = 4;
private var tiles:Array;
private var clickable:Boolean;
private var playable:Boolean;
public function Board()
{
init();
}
public function init():void
{
playable = false;
graphics.clear();
graphics.beginFill(0xC0C0C0);
graphics.drawRect(0,0,Tile.SIZE*wNum, Tile.SIZE*hNum);
while(numChildren > 0)
{
removeChild(getChildAt(0));
}
tiles = [];
for(var i:int = 0; i<hNum; i++)
{
tiles[i] = [];
for(var j:int = 0; j<wNum; j++)
{
if(!(i == hNum-1 && j == wNum-1))
{
var tile:Tile = new Tile(i*wNum+(j+1));
tile.x = j*Tile.SIZE;
tile.y = i*Tile.SIZE;
addChild(tile);
tiles[i][j] = tile;
}
}
}
shuffle(wNum*hNum*3);
playable = true;
clickable = true;
addEventListener(MouseEvent.CLICK, onClick);
}
private function onClick(e:MouseEvent):void
{
if(!clickable) return;
var tx:int = mouseX/Tile.SIZE;
var ty:int = mouseY/Tile.SIZE;
if(!onBoard(tx, ty) || tiles[ty][tx] == null) return;
searchArround(tx,ty)
}
// (x, y)がboard上にあるか
private function onBoard(x:int, y:int):Boolean
{
if(x<0 || wNum<=x || y<0 || hNum<=y) return false;
return true;
}
// (x, y)の上下左右に空白があるか調べる
private function searchArround(x:int, y:int):void
{
if(searchSpace(x, y-1)) changePosition(x, y, x, y-1);
if(searchSpace(x+1, y)) changePosition(x, y, x+1, y);
if(searchSpace(x, y+1)) changePosition(x, y, x, y+1);
if(searchSpace(x-1, y)) changePosition(x, y, x-1, y);
}
// (x, y)が空白か
private function searchSpace(x:int, y:int):Boolean
{
if(!onBoard(x, y)) return false;
if(tiles[y][x] == null) return true;
return false;
}
// (x, y)と空白(tx, ty)を入れ替える
private function changePosition(x:int, y:int, tx:int, ty:int):void
{
clickable = false;
if(playable)
{
var t:ITween = BetweenAS3.tween(tiles[y][x], {x:tx*Tile.SIZE, y:ty*Tile.SIZE}, null, 0.1);
t.play();
t.onComplete = onComplete;
}
// shuffleではtweenさせない
else
{
tiles[y][x].x = tx*Tile.SIZE;
tiles[y][x].y = ty*Tile.SIZE;
}
tiles[ty][tx] = tiles[y][x];
tiles[y][x] = null;
}
// times回shuffle
private function shuffle(times:int):void
{
const DIR:Array = [
[0, -1],
[1, 0],
[0, 1],
[-1, 0],
];
// 空白の初期値
var x:int = wNum-1;
var y:int = hNum-1;
for(var i:int = 0; i<times; i++) {
var random:Array = Random.shakedIntegers(4);
// 空白を基準にrandomで上下左右調べ、そこがboard上であれば入れ替える
for(var j:int = 0; j<random.length; j++)
{
var dx:int = DIR[random[j]][0];
var dy:int = DIR[random[j]][1];
if(!onBoard(x+dx, y+dy)) continue;
changePosition(x+dx, y+dy, x, y);
x = x+dx;
y = y+dy;
break;
}
}
}
// 順番が正しいか
private function checkCorrect():Boolean
{
if(!(tiles[hNum-1][wNum-1] == null)) return false;
for(var i:int = 0; i<hNum; i++)
{
for(var j:int = 0; j<wNum; j++)
{
if(i == hNum-1 && j == wNum-1) continue;
if(!(tiles[i][j].number == i*wNum+(j+1))) return false;
}
}
return true;
}
private function onComplete():void
{
clickable = true;
if(checkCorrect())
{
clickable = false;
trace("GAME CLEAR!");
var txt:Label = new Label(this, 0, 0, "GAME CLEAR!");
txt.scaleX = txt.scaleY = 5;
txt.x = this.parent.width/2 - txt.width/2*txt.scaleX - 10;
txt.y = this.parent.height/2 - txt.height/2*txt.scaleY - 10;
}
}
}
class Tile extends Sprite
{
public static const SIZE:int = 70;
public var number:int;
public function Tile(number:int)
{
this.number = number;
graphics.beginFill(0xEEEEEE);
graphics.drawRect(0, 0, SIZE, SIZE);
graphics.endFill();
var tf:TextField = new TextField();
tf.defaultTextFormat = new TextFormat("_ゴシック", 36);
tf.text = String(number);
tf.autoSize = "left";
tf.selectable = false;
//tf.border = true;
addChild(tf);
tf.x = SIZE/2 - tf.width/2;
tf.y = SIZE/2 - tf.height/2 - 2;
this.filters = [new BevelFilter(5, 45, 0xFFFFFF, 0.5, 0x0, 0.5, 5, 5, 1, 3)];
}
}