minesweeper

by wh0
♥0 | Line 233 | Modified 2010-04-12 16:07:27 | MIT License
play

ActionScript3 source code

/**
 * Copyright wh0 ( http://wonderfl.net/user/wh0 )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/x22A
 */

package {
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.events.KeyboardEvent;
	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 flash.ui.Keyboard;
	import flash.text.TextFormatAlign;
	public class Minesweeper extends Sprite {
		
		private static const w:int = 30;
		private static const h:int = 16;
		private static const m:int = 99;
		private static const s:int = 15;
		private static const X:int = 90; //reversed
		private static const Z:int = 88;
		
		private static const MINES:int = 0xf;
		private static const MARKS:int = 0xf0;
		private static const MINE:int = 0x100;
		private static const OPEN:int = 0x200;
		private static const MARK:int = 0x400;
		
		private const f:Vector.<Vector.<int>> = new Vector.<Vector.<int>>(h, true);
		private const d:BitmapData = new BitmapData(w * s, h * s, false);
		private const g:BitmapData = new BitmapData(180, 15, false);
		
		private var ur:int = -1;
		private var uc:int = -1;
		private var ux:Boolean = false;
		private var uz:Boolean = false;
		
		public function Minesweeper() {
			prepareGraphics();
			addChild(new Bitmap(d));
			for (var r:int = 0; r < h; r++)
				f[r] = new Vector.<int>(w, true);
			stage.addEventListener(MouseEvent.MOUSE_MOVE, mouse);
			stage.addEventListener(KeyboardEvent.KEY_DOWN, keydown);
			stage.addEventListener(KeyboardEvent.KEY_UP, keyup);
			start();
		}
		
		private function prepareGraphics():void {
			var t:TextField = new TextField(); addChild(t); t.x = 1; t.y = -1; t.width = 14;
			t.defaultTextFormat = new TextFormat('Arial', 11, null, true, null, null, null, null, TextFormatAlign.CENTER);
			var m:Matrix = new Matrix();
			graphics.beginFill(0xc0c0c0); graphics.drawRect(0, 0, 15, 15); graphics.endFill();
			graphics.lineStyle(1, 0x808080); graphics.moveTo(15, 0); graphics.lineTo(0, 0); graphics.lineTo(0, 15);
			g.draw(this, m);
			t.textColor = 0x0000ff; t.text = '1'; m.translate(15, 0); g.draw(this, m);
			t.textColor = 0x008000; t.text = '2'; m.translate(15, 0); g.draw(this, m);
			t.textColor = 0xff0000; t.text = '3'; m.translate(15, 0); g.draw(this, m);
			t.textColor = 0x000080; t.text = '4'; m.translate(15, 0); g.draw(this, m);
			t.textColor = 0x800000; t.text = '5'; m.translate(15, 0); g.draw(this, m);
			t.textColor = 0x008080; t.text = '6'; m.translate(15, 0); g.draw(this, m);
			t.textColor = 0x808080; t.text = '7'; m.translate(15, 0); g.draw(this, m);
			t.textColor = 0x000000; t.text = '8'; m.translate(15, 0); g.draw(this, m);
			removeChild(t); graphics.clear();
			graphics.beginFill(0xc0c0c0); graphics.drawRect(0, 0, 15, 15); graphics.endFill();
			graphics.lineStyle(1, 0xffffff); graphics.moveTo(0, 14); graphics.lineTo(0, 0); graphics.lineTo(14, 0);
			graphics.moveTo(1, 13); graphics.lineTo(1, 1); graphics.lineTo(13, 1);
			graphics.lineStyle(1, 0x808080); graphics.moveTo(1, 14); graphics.lineTo(14, 14); graphics.lineTo(14, 1);
			graphics.moveTo(2, 13); graphics.lineTo(13, 13); graphics.lineTo(13, 2);
			m.translate(15, 0); g.draw(this, m);
			graphics.lineStyle(); graphics.beginFill(0xff0000); graphics.moveTo(9, 3); graphics.lineTo(4, 5); graphics.lineTo(9, 8); graphics.endFill();
			graphics.beginFill(0x000000); graphics.moveTo(9, 9); graphics.lineTo(11, 12); graphics.lineTo(4, 12); graphics.endFill();
			m.translate(15, 0); g.draw(this, m);
			graphics.clear();
			graphics.beginFill(0xff0000); graphics.drawRect(0, 0, 15, 15); graphics.endFill();
			graphics.lineStyle(1, 0x808080); graphics.moveTo(15, 0); graphics.lineTo(0, 0); graphics.lineTo(0, 15);
			graphics.lineStyle(); graphics.beginFill(0x000000); graphics.drawCircle(8, 8, 4); graphics.endFill();
			m.translate(15, 0); g.draw(this, m);
			graphics.clear();
		}
		
		private function mouse(e:MouseEvent):void {
			if (ux) {
				release(ur, uc);
				if (uz)
					propagate(release, ur, uc);
			}
			ur = e.stageY / s;
			uc = e.stageX / s;
			if (ux) {
				depress(ur, uc);
				if (uz)
					propagate(depress, ur, uc);
			}
		}
		
		private function keydown(e:KeyboardEvent):void {
			if (e.keyCode == X) {
				ux = true;
				depress(ur, uc);
				if (uz)
					propagate(depress, ur, uc);
			} else if (e.keyCode == Z) {
				if (!uz) {
					uz = true;
					if (ux) {
						depress(ur, uc);
						propagate(depress, ur, uc);
					} else {
						mark(ur, uc);
					}
				}
			}
		}
		
		private function keyup(e:KeyboardEvent):void {
			if (e.keyCode == X) {
				if (ux) {
					ux = false;
					release(ur, uc);
					if (uz) {
						propagate(release, ur, uc);
						special(ur, uc);
					} else {
						open(ur, uc);
					}
				}
			} else if (e.keyCode == Z) {
				uz = false;
				if (ux) {
					ux = false;
					release(ur, uc);
					propagate(release, ur, uc);
					special(ur, uc);
				}
			}
		}
		
		private function start():void {
			var r:int, c:int, i:int;
			for (r = 0; r < h; r++) {
				for (c = 0; c < w; c++) {
					f[r][c] = 0;
					cell(r, c, 9);
				}
			}
			i = 0;
			while (i < m) {
				r = Math.random() * h;
				c = Math.random() * w;
				if (f[r][c] & MINE)
					continue;
				f[r][c] |= MINE;
				i++;
				propagate(incMines, r, c);
			}
		}
		
		private function depress(r:int, c:int):void {
			if (!bound(r, c))
				return;
			if (f[r][c] & (OPEN | MARK))
				return;
			cell(r, c, 0);
		}
		
		private function release(r:int, c:int):void {
			if (!bound(r, c))
				return;
			if (f[r][c] & (OPEN | MARK))
				return;
			cell(r, c, 9);
		}
		
		private function open(r:int, c:int):void {
			if (!bound(r, c))
				return;
			if (f[r][c] & (OPEN | MARK))
				return;
			f[r][c] |= OPEN;
			if (f[r][c] & MINE) {
				cell(r, c, 11);
				propagate(incMarks, r, c);
			} else {
				cell(r, c, f[r][c] & MINES);
				if ((f[r][c] & MINES) == 0)
					propagate(open, r, c);
			}
		}
		
		private function mark(r:int, c:int):void {
			if (!bound(r, c))
				return;
			if (f[r][c] & OPEN)
				return;
			if (f[r][c] & MARK) {
				cell(r, c, 9);
				f[r][c] &= ~MARK;
				propagate(decMarks, r, c);
			} else {
				cell(r, c, 10);
				f[r][c] |= MARK;
				propagate(incMarks, r, c);
			}
		}
		
		private function special(r:int, c:int):void {
			if (!bound(r, c))
				return;
			if (!(f[r][c] & OPEN))
				return;
			if ((f[r][c] & MINES) != (f[r][c] & MARKS) >> 4)
				return;
			propagate(open, r, c);
		}
		
		private function incMines(r:int, c:int):void {
			if (!bound(r, c))
				return;
			f[r][c] += 0x1;
		}
		
		private function incMarks(r:int, c:int):void {
			if (!bound(r, c))
				return;
			f[r][c] += 0x10;
		}
		
		private function decMarks(r:int, c:int):void {
			if (!bound(r, c))
				return;
			f[r][c] -= 0x10;
		}
		
		private function propagate(a:Function, r:int, c:int):void {
			a(r - 1, c - 1);
			a(r - 1, c    );
			a(r - 1, c + 1);
			a(r    , c - 1);
			a(r    , c + 1);
			a(r + 1, c - 1);
			a(r + 1, c    );
			a(r + 1, c + 1);
		}
		
		private function bound(r:int, c:int):Boolean {
			return r >= 0 && r < h && c >= 0 && c < w;
		}
		
		private function cell(r:int, c:int, i:int):void {
			d.copyPixels(g, new Rectangle(i * s, 0, s, s), new Point(c * s, r * s));
		}
		
	}
}

Forked