forked from: flash on 2009-9-6
昔、遊んだゲームを再現(タイトル忘れた)
*
* オセロのように互いに盤面へ駒を打つゲーム
* 打った場所が自分の陣地になり、NEXTの値が自分の数字になる
*
* 打った周りの8方向を見る
* -敵の陣地でかつ自分の数字より小さかったら、そのマスを自分の陣地に出来る(色を変更させる
* -自分の陣地があったら、そのマスの数値を1つ増やして補強できる
*
* ボードのマスが全て埋まった状態で、スコアが多いほうが勝ち
// forked from rsakane's flash on 2009-9-6
/*
* 昔、遊んだゲームを再現(タイトル忘れた)
*
* オセロのように互いに盤面へ駒を打つゲーム
* 打った場所が自分の陣地になり、NEXTの値が自分の数字になる
*
* 打った周りの8方向を見る
* -敵の陣地でかつ自分の数字より小さかったら、そのマスを自分の陣地に出来る(色を変更させる
* -自分の陣地があったら、そのマスの数値を1つ増やして補強できる
*
* ボードのマスが全て埋まった状態で、スコアが多いほうが勝ち
*/
package
{
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.events.TimerEvent;
import flash.geom.Point;
import flash.utils.Timer;
import flash.text.TextField;
public class Main extends Sprite
{
private var board:Board;
private var canvas:Sprite;
// private var ai:AI;
private var ai2 : AI2;
private var timer:Timer;
private var _tf : TextField;
public function Main()
{
canvas = new Sprite();
addChild(canvas);
board = new Board(canvas);
// ai = new AI(board);
timer = new Timer(1000, 1);
timer.addEventListener(TimerEvent.TIMER_COMPLETE, onComplete);
stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
_tf = new TextField();
_tf.width = 1000;
_tf.height = 1000;
addChild(_tf);
ai2 = new AI2(_tf);
}
private function onMouseDown(event:MouseEvent):void
{
if (board.endFlag) return;
if (board.turn != Color.BLUE) return;
var xx:int = mouseX / Board.MSIZE;
var yy:int = mouseY / Board.MSIZE;
if (Board.onBoard(xx, yy) && board.board[yy][xx].color == Color.NONE)
{
board.putPiece(xx, yy);
// ai.removePoint(xx, yy);
ai2.put(xx, yy, board.board[yy][xx].count);
timer.start();
}
}
private function onComplete(event:TimerEvent):void
{
if (board.endFlag) return;
// var point:Point = ai.next();
var a : Array = ai2.algo(-board.next, 2);
var point : Point = new Point(a[0], a[1]);
board.putPiece(point.x, point.y);
// ai.removePoint(point.x, point.y);
ai2.put(point.x, point.y, -board.board[point.y][point.x].count);
}
}
}
import flash.display.Sprite;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.text.TextFieldAutoSize;
class AI
{
public var points:Array;
public var board:Board;
public function AI(board:Board)
{
this.board = board;
points = new Array();
for (var y:int = 0; y < Board.SIZE; y++)
{
for (var x:int = 0; x < Board.SIZE; x++)
{
var point:Point = new Point(x, y);
points.push(point);
}
}
}
public function removePoint(x:int, y:int):void
{
for (var i:int = 0; i < points.length; i++)
{
if (points[i].x == x && points[i].y == y)
{
points.splice(i, 1);
return;
}
}
}
public function next():Point
{
var max:int = check(points[0]);
var maxPoint:Point = points[0];
for (var i:int = 1; i < points.length; i++)
{
var value:int = check(points[i]);
if (value > max)
{
max = value;
maxPoint = points[i];
}
}
return (max == 0) ? points[int(Math.random() * points.length)] :maxPoint;
}
private function check(point:Point):int
{
var total:int = 0;
for (var y:int = -1; y <= 1; y++)
{
for (var x:int = -1; x <= 1; x++)
{
if (y == 0 && x == 0) continue;
if (!Board.onBoard(point.x + x, point.y + y)) continue;
var piece:Piece = board.board[point.y + y][point.x + x];
if (piece.color == Color.BLUE && piece.count < board.next) total += piece.count;
}
}
return total;
}
}
class AI2
{
private var _f : Array;
private var _sum : int;
private var _tf : TextField;
public function AI2(tf : TextField = null)
{
_f = new Array(9);
for(var i : int = 0;i < 9;i++){
_f[i] = new Array(9);
for(var j : int = 0;j < 9;j++){
_f[i][j] = 0;
}
}
_sum = 0;
_tf = tf;
}
public function put(x : int, y : int, c : int) : void
{
var o : int = _f[x][y];
_f[x][y] = c;
_sum += c - o;
}
public function algo(c : int, depth : int) : Array
{
var init : int = c > 0 ? int.MIN_VALUE : int.MAX_VALUE;
var candi : Array = [];
var max : int = init;
var maxi : int, maxj : int;
for(var i : int = 0;i < 9;i++){
for(var j : int = 0;j < 9;j++){
if(_f[i][j] != 0)continue;
candi.push([i, j]);
var prevsum : int = _sum;
_f[i][j] = c;
_sum += c;
var prev : Array = infect(i, j);
var v : int = rec(c > 0 ? -1 : 1, depth - 1);
// _tf.appendText("" + i + "\t" + j + "\t" + v + "\n");
if(c > 0){
if(max < v){
max = v;
maxi = i;
maxj = j;
}
}else{
if(max > v){
max = v;
maxi = i;
maxj = j;
}
}
infectBack(i, j, prev);
_sum = prevsum;
// _f[i][j] = 0;
}
}
if(max == init){
return candi[Math.random() * candi.length];
}else{
return [maxi, maxj];
}
}
private function infect(x : int, y : int) : Array
{
var step : int = (_f[x][y] >> 5 << 1) + 1;
var ret : Array = [];
for(var i : int = x - 1;i <= x + 1;i++){
for(var j : int = y - 1;j <= y + 1;j++){
if(i < 0 || i > 8 || j < 0 || j > 8)continue;
if(i == x && j == y)continue;
ret.push(_f[i][j]);
if(_f[i][j] == 0)continue;
if((_f[i][j] ^ _f[x][y]) < 0){
var s : int = _f[x][y] + _f[i][j];
if((s ^ _f[x][y]) > 0){
_sum += -_f[i][j] * 2;
_f[i][j] = -_f[i][j];
}
}else{
_sum += step;
_f[i][j] += step;
}
}
}
return ret;
}
private function infectBack(x : int, y : int, a : Array) : void
{
var ind : int = 0;
for(var i : int = x - 1;i <= x + 1;i++){
for(var j : int = y - 1;j <= y + 1;j++){
if(i < 0 || i > 8 || j < 0 || j > 8)continue;
if(i == x && j == y)continue;
_f[i][j] = a[ind];
ind++;
}
}
_f[x][y] = 0;
}
private function rec(c : int, depth : int) : int
{
if(depth == 0)return _sum;
var max : int = c > 0 ? int.MIN_VALUE : int.MAX_VALUE;
for(var i : int = 0;i < 9;i++){
for(var j : int = 0;j < 9;j++){
if(_f[i][j] != 0)continue;
var prevsum : int = _sum;
var p : int = 0;
for(var k : int = 1;k <= 9;k++){
_f[i][j] = c * k;
_sum += c * k;
var prev : Array = infect(i, j);
p += rec(-c, depth - 1);
infectBack(i, j, prev);
_sum = prevsum;
// _f[i][j] = 0;
}
if(c > 0){
if(max < p){
max = p;
}
}else{
if(max > p){
max = p;
}
}
}
}
return max;
}
}
class Board
{
public static const SIZE:int = 9; // 盤面マス数(縦横共有)
public static const MSIZE:int = 400 / SIZE; // 一マスのサイズ(縦横共有)
public var board:Array;
public var turn:int = Color.BLUE;
public var next:int = Math.random() * 9 + 1;
public var endFlag:Boolean = false;
private var nextTF:TextField;
private var countTF:TextField;
private var countRED:int = 0;
private var countBLUE:int = 0;
private var count:int = 0;
public function Board(canvas:Sprite)
{
board = new Array(SIZE);
for (var y:int = 0; y < SIZE; y++)
{
board[y] = new Array(SIZE);
for (var x:int = 0; x < SIZE; x++)
{
var piece:Piece = new Piece();
piece.x = x * MSIZE;
piece.y = y * MSIZE;
board[y][x] = piece;
canvas.addChild(piece);
}
}
var str:String = (turn == Color.BLUE) ? "BLUE" : "RED";
nextTF = createTextField(str + " - NEXT: " + String(next), 20, 0x0);
nextTF.y = 420;
canvas.addChild(nextTF);
countTF = createTextField("BLUE - " + countBLUE + " / RED - " + countRED, 20, 0x0);
countTF.y = 420, countTF.x = 200;
canvas.addChild(countTF);
}
public static function createTextField(text:String, size:int, color:int):TextField
{
var tf:TextField = new TextField();
tf.defaultTextFormat = new TextFormat("typeWriter_", 20, color, true);
tf.text = text;
tf.width = Board.MSIZE;
tf.autoSize = TextFieldAutoSize.LEFT;
tf.selectable = false;
return tf;
}
public static function onBoard(x:int, y:int):Boolean
{
if (x < 0 || x >= SIZE) return false;
if (y < 0 || y >= SIZE) return false;
return true;
}
public function putPiece(x:int, y:int):void
{
count++;
board[y][x].count = next;
board[y][x].draw(turn);
var str:String = "";
if (turn == Color.BLUE)
{
str = "RED";
countBLUE += next;
}
else
{
str = "BLUE";
countRED += next;
}
for (var yy:int = -1; yy <= 1; yy++)
{
for (var xx:int = -1; xx <= 1; xx++)
{
if (xx == 0 && yy == 0) continue;
if (!onBoard(x + xx, y + yy)) continue;
var piece:Piece = board[y + yy][x + xx];
if (piece.color == Color.NONE) continue;
else if (piece.color == turn)
{
piece.tf.text = String(++piece.count);
if (turn == Color.BLUE) countBLUE++;
else countRED++;
}
else
{
if (board[y][x].count > piece.count)
{
piece.draw(turn);
if (turn == Color.BLUE) countBLUE += piece.count, countRED -= piece.count;
else countRED += piece.count, countBLUE -= piece.count;
}
}
}
}
countTF.text = "BLUE - " + countBLUE + " / RED - " + countRED;
if (count >= SIZE * SIZE)
{
endFlag = true;
if (countBLUE > countRED) nextTF.text = "BLUE WIN !!!";
else if (countBLUE < countRED) nextTF.text = "RED WIN !!!";
else nextTF.text = "DRAW ... ";
}
else
{
next = Math.random() * 9 + 1;
nextTF.text = str + " - NEXT: " + String(next), 20, 0x0;
}
if (turn == Color.BLUE) turn = Color.RED;
else turn = Color.BLUE;
}
}
class Piece extends Sprite
{
public var color:int;
public var count:int;
public var tf:TextField;
public function Piece()
{
color = Color.NONE;
count = 0;
graphics.lineStyle(1.0);
graphics.drawRect(0, 0, Board.MSIZE, Board.MSIZE);
graphics.endFill();
tf = createTextField("", 17, 0x0);
addChild(tf);
}
public static function createTextField(text:String, size:int, color:int):TextField
{
var tf:TextField = new TextField();
tf.defaultTextFormat = new TextFormat("typeWriter_", 20, color, true);
tf.text = text;
tf.width = Board.MSIZE;
tf.y = 8;
tf.autoSize = TextFieldAutoSize.CENTER;
tf.selectable = false;
return tf;
}
public function draw(color:int):void
{
this.tf.text = String(count);
this.color = color;
graphics.clear();
var matrix:Matrix = new Matrix();
matrix.createGradientBox(Board.MSIZE, Board.MSIZE, 90 * Math.PI / 180);
graphics.lineStyle(1.0);
graphics.beginGradientFill("linear", Color.COLORS[color], [1.0, 1.0], [0, 255], matrix);
graphics.drawRect(0, 0, Board.MSIZE, Board.MSIZE);
graphics.endFill();
}
}
class Color
{
public static const NONE:int = 2;
public static const RED:int = 0;
public static const BLUE:int = 1;
public static var COLORS:Array =
[
[0xf26b53, 0xef4123],
[0x09bbff, 0x009AD6],
[0xf9f9f9, 0xFFFFFF]
]
}