Mine Sweepr Like
特に変わったところはないです。
左クリック→オープン
右クリック→フラグ
/**
* 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);
}
}