Reversi
/**
* Copyright flashrod ( http://wonderfl.net/user/flashrod )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/cnIQ
*/
package {
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
public class Reversi extends Sprite {
private static const UNIT:int = 18;
private static const ORIENTATION:Array = [[-1, -1], [0, -1], [1, -1], [-1, 0], [1, 0], [-1, 1], [0, 1], [1, 1]];
private static const PRIORITY:Array = [[0, 6, 3, 2], [6, 5, 4, 2], [3, 4, 1, 1], [2, 2, 1, 7]];
private static const WHITE:int = 1;
private static const BLACK:int = 2;
private var board:Array = [];
private var queue:Array = [];
/** リバーシ */
public function Reversi() {
for (var j:int = 0; j < 8; ++j) {
board[j] = [];
for (var i:int = 0; i < 8; ++i) {
board[j][i] = 0;
}
}
put(3, 3, WHITE);
put(3, 4, BLACK);
put(4, 3, BLACK);
put(4, 4, WHITE);
// クリックした位置に黒(先手)が打つ
stage.addEventListener(MouseEvent.CLICK, function(e:MouseEvent):void {
i = e.localX / UNIT;
j = e.localY / UNIT;
if (canPut(i, j, BLACK)) {
place(i, j, BLACK);
queue.push(move);
} else {
if (!search(BLACK)) {
queue.push(move);
}
}
});
// 非同期処理
addEventListener(Event.ENTER_FRAME, function(e:Event):void {
if (queue.length > 0) {
queue.shift()();
}
});
}
/** 盤の外側かどうか調べます
* @param (x,y) 調べる位置
* @return (x,y)が盤の内側なら真
*/
private function out(x:int, y:int):Boolean {
return x < 0 || x > 7 || y < 0 || y > 7;
}
/** 白(後手)が自動的に打ちます
*/
private function move():void {
var v:Array = search(WHITE);
if (v) {
place(v[0], v[1], WHITE);
}
}
/** 着手できる場所を探す
* @param stone 石
* @return 着手できるときは(x,y),無いときはnull
*/
private function search(stone:int):Array {
for (var k:int = 0; k < 7; ++k) {
for (var j:int = 0; j < 8; ++j) {
for (var i:int = 0; i < 8; ++i) {
if (k == PRIORITY[j>3 ? 7-j : j][i>3 ? 7-i : i]) {
if (canPut(i, j, stone)) {
return [i, j];
}
}
}
}
}
return null;
}
/** 指定位置に石を置けるかどうか調べます
* @param (x,y) 指定位置
* @param stone 石
* @return 指定位置に石が着手できるときは真
*/
private function canPut(x:int, y:int, stone:int):Boolean {
if (!out(x, y) && board[y][x]==0) {
for each (var v:Array in ORIENTATION) {
if (canPutV(v, x, y, stone)) {
return true;
}
}
}
return false;
}
/** 指定位置から指定方向に石を置いてはさめるかどうか調べます
* @param v 方向
* @param (x,y) 指定位置
* @param stone 石
* @return 指定位置に石が着手できるときは真
*/
private function canPutV(v:Array, x:int, y:int, stone:int):Boolean {
var t:String = "";
for (;;) {
x += v[0];
y += v[1];
if (out(x, y)) {
break;
}
t += board[y][x];
}
return t.search(stone==WHITE ? /2+1/ : /1+2/) == 0;
}
/** 指定位置に石を置きます。
* @param (x,y) 指定位置
* @param stone 石
*/
private function put(x:int, y:int, stone:int):void {
queue.push(function():void {
board[y][x] = stone;
graphics.clear();
graphics.lineStyle(1, 0);
for (var j:int = 0; j < 8; ++j) {
for (var i:int = 0; i < 8; ++i) {
if (board[j][i]) {
graphics.beginFill(board[j][i]==BLACK ? 0x000000 : 0xFFFFFF);
graphics.drawCircle(i*UNIT+UNIT/2, j*UNIT+UNIT/2, UNIT/2);
}
}
}
for (i = 0; i < 9; ++i) {
graphics.moveTo(i*UNIT, 0);
graphics.lineTo(i*UNIT, 8*UNIT);
graphics.moveTo(0, i*UNIT);
graphics.lineTo(8*UNIT, i*UNIT);
}
});
}
/** 指定位置に石を置いて挟んだ相手の石をひっくり返します。
* @param (x,y) 指定位置
* @param stone 石
*/
private function place(x:int, y:int, stone:int):void {
put(x, y, stone);
for each (var v:Array in ORIENTATION) {
if (canPutV(v, x, y, stone)) {
for (var i:int = x, j:int = y;;) {
i += v[0];
j += v[1];
if (out(i, j) || board[j][i]!=(stone^3)) {
break;
}
put(i, j, stone);
}
}
}
}
}
}