/**
* Copyright hi.kurosawa ( http://wonderfl.net/user/hi.kurosawa )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/jxHd
*/
package {
//------------------------------------------
//黒白ゲーム(Reversi)の盤のクラス試験用
// 黒も白も人間が打ちます
// URL:http://programmingatelier.net/
//------------------------------------------
import flash.display.Sprite;
import flash.events.Event;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.events.Event;
import flash.events.MouseEvent;
public class ReversiBoard extends Sprite {
public var txtMess1:TextField;
public var txtMess2:TextField;
//ボードクラス(ボードとルール)
private var objBoard:clsBoard;
//打つプレイヤー(1:黒先行、2:白後攻)
private var ip:int;
public function ReversiBoard():void {
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void {
removeEventListener(Event.ADDED_TO_STAGE, init);
txtMess1 = new TextField();
addChild(txtMess1);
txtMess1.x = 0;
txtMess1.y = 0;
txtMess1.width = 300;
txtMess1.height = 20;
txtMess1.border =true;
txtMess2 = new TextField();
addChild(txtMess2);
txtMess2.x = 300;
txtMess2.y = 0;
txtMess2.width = 150;
txtMess2.height = 450;
txtMess2.border = true;
txtMess2.multiline = true;
objBoard = new clsBoard();
addChild(objBoard);
objBoard.x = 0;
objBoard.y = 20;
fncStart();
}
//ゲーム開始
public function fncStart(e:*= null):void {
fncMess2Clear();
fncMess2Set("盤の初期化");
objBoard.initDataSet();
ip = clsRevCom.getFirstPlayer(); //1:黒先行
fncMess1Set(clsRevCom.getPlColNam(ip) + "が打つ番です。");
//盤がクリックしたときの関数定義
objBoard.fncSetFnc(fncOnxy);
}
//盤がクリックしたとき
// iti:クリックした升目("a1"~"h8")
public function fncOnxy(itiNam:String):void {
var n:int = objBoard.okuIti(itiNam, ip);
if (n > 0) { //升目がOKか,駒を置く
fncMess2Set(clsRevCom.getPlColNam(ip) + ":" + itiNam + ":" + (n-1) + "個変更");
ip = clsRevCom.getOtherPlayer(ip); //次に打つプレイヤー
} else {
return; //打てない升目をクリック
}
//次に打つプレイヤーが打てる場所があるか?
if ( objBoard.chkPlayer(ip) >0) {
fncMess1Set(clsRevCom.getPlColNam(ip) + "が打つ番です。");
return;
}
//次の次のプレイヤーが打てる場所があるか?
ip = clsRevCom.getOtherPlayer(ip); //次に打つプレイヤー
if ( objBoard.chkPlayer(ip) >0) {
fncMess1Set(clsRevCom.getPlColNam(ip) + "が打つ番です。");
return;
}
//二人とも打てる場所なし->終了
var ip1:int = clsRevCom.getFirstPlayer();
var ip2:int = clsRevCom.getOtherPlayer(ip1);
var ip1n:int = objBoard.Kekka(ip1);
var ip2n:int = objBoard.Kekka(ip2);
var strWin:String = "引き分けです。";
if (ip1n > ip2n) { strWin = clsRevCom.getPlColNam(ip1)+"の勝ちです。"; }
if (ip1n < ip2n) { strWin = clsRevCom.getPlColNam(ip2)+"の勝ちです。"; }
fncMess2Set("終了しました。" +strWin+"\n"+ clsRevCom.getPlColNam(ip1) + ":" + ip1n +
"/" + clsRevCom.getPlColNam(ip2) + ":" + ip2n);
fncMess1Set("盤をクリックしてください、再開します。");
objBoard.fncSetFnc(fncReStart);
}
//ゲーム再開
private function fncReStart(iti:String):void {
fncStart();
}
//メッセージ表示
private function fncMess1Set(strMess:String):void {
txtMess1.text = strMess;
}
private function fncMess2Clear():void {
txtMess2.text = "";
}
private function fncMess2Set(strMess:String):void {
txtMess2.text = strMess+"\n"+txtMess2.text;
}
}
}
//===============================================================================
//黒白ゲーム(リバーシ)
//共通関数
class clsRevCom {
//枡目の名称
static private const arrYokoName:Array = ["a", "b", "c", "d", "e", "f", "g", "h" ];
static private const arrTateName:Array = ["1", "2", "3", "4", "5", "6", "7", "8" ];
//升目の横方向の名称
static public function getYokoNam(iti:int):String {
var strRet:String = "";
if (iti >= 0 && iti < arrYokoName.length) { strRet = arrYokoName[iti];}
return strRet;
}
//升目の縦方向の名称
static public function getTateNam(iti:int):String {
var strRet:String = "";
if (iti >= 0 && iti < arrTateName.length) { strRet = arrTateName[iti];}
return strRet;
}
//升目の名称より横方向の位置を求める
static public function getYokoIti(itiNam:String):int {
var iti:int = -1;
if (itiNam.length != 2) { return iti; }
var s:String = itiNam.substr(0, 1);
for (var i:int = 0; i < arrYokoName.length;i++ ) {
if (arrYokoName[i] == s) { iti = i;}
}
return iti;
}
//升目の名称より縦方向の位置を求める
static public function getTateIti(itiNam:String):int {
var iti:int = -1;
if (itiNam.length != 2) { return iti; }
var s:String = itiNam.substr(1, 1);
for (var i:int = 0; i < arrTateName.length;i++ ) {
if (arrTateName[i] == s) { iti = i ;}
}
return iti;
}
//プレイヤーの色名称
// ip:プレイヤー
static public function getPlColNam(ip:int):String {
if (ip == 1) { return "黒"; }
if (ip == 2) { return "白"; }
return "";
}
//最初に打つプレイヤー
// ip:プレイヤー
static public function getFirstPlayer():int {
return 1;
}
//相手のプレイヤー
// ip:プレイヤー
static public function getOtherPlayer(ip:int):int {
if (ip == 1) { return 2;}
return 1;
}
}
//=============================================================================
//黒白ゲーム(リバーシ)
//盤クラス(ボードとルール)
import flash.display.Sprite;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.events.Event;
import flash.events.MouseEvent;
class clsBoard extends Sprite {
//盤データ(先手黒:1、後手白:2、未配置:0、盤の外:-1)
//initDataSet()関数を参照
private var boardData:Array;
//打った升目の履歴
// {Player:プレイヤー(1,2),MasuIti:升目の名称("a1"~"h8"),KomaSuu:反転した数+1}
private var arrRireki:Array;
//升目のサイズ
private const mSize:Number = 30;
//盤をクリックしたときに呼び出す関数(クラス外部の関数を登録)
// func(itiNam:String):void
// itiNam:升目の名称("a1"~"h8")
private var fncMouseDown:Function = null;
//コンストラクター================================================
public function clsBoard():void {
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
//初期化
private function init(e:Event = null):void {
disText();
stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
initDataSet();
}
//升目の名称表示
private function disText():void {
var i:int;
var textField:TextField;
for (i = 1; i < 9; i++) {
textField = new TextField();
textField.autoSize = TextFieldAutoSize.LEFT;
textField.width = 20;
textField.wordWrap = true;
textField.x = mSize-10;
textField.y = mSize*i;
textField.text = clsRevCom.getTateNam(i-1);
addChild(textField);
textField = new TextField();
textField.autoSize = TextFieldAutoSize.LEFT;
textField.width = 20;
textField.wordWrap = true;
textField.x = mSize*i;
textField.y = mSize-18;
textField.text = clsRevCom.getYokoNam(i-1);
addChild(textField);
}
}
//盤をクリックしたときに呼び出す関数の登録==============================
public function fncSetFnc(fnc:Function):void {
fncMouseDown = fnc;
}
//盤をクリックしたときの処理
private function onMouseDown(event:MouseEvent):void {
if(fncMouseDown==null) { return;}
var itiX:int = mouseX / mSize;
var itiY:int = mouseY / mSize;
if (itiX <= 0 || itiX > 8 || itiY <= 0 || itiY > 8) { return;}
fncMouseDown(clsRevCom.getYokoNam(itiX-1)+clsRevCom.getTateNam(itiY-1));
}
//盤の初期化==================================================
public function initDataSet():void {
var ip1:int = clsRevCom.getFirstPlayer();
var ip2:int = clsRevCom.getOtherPlayer(ip1);
boardData = new Array(
new Array( -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
new Array( -1, 0, 0, 0, 0, 0, 0, 0, 0, -1),
new Array( -1, 0, 0, 0, 0, 0, 0, 0, 0, -1),
new Array( -1, 0, 0, 0, 0, 0, 0, 0, 0, -1),
new Array( -1, 0, 0, 0, ip2, ip1, 0, 0, 0, -1),
new Array( -1, 0, 0, 0, ip1, ip2, 0, 0, 0, -1),
new Array( -1, 0, 0, 0, 0, 0, 0, 0, 0, -1),
new Array( -1, 0, 0, 0, 0, 0, 0, 0, 0, -1),
new Array( -1, 0, 0, 0, 0, 0, 0, 0, 0, -1),
new Array( -1, -1, -1, -1, -1, -1, -1, -1, -1, -1));
arrRireki = new Array();
disBoard();
}
//盤の表示(升目の名称以外)
private function disBoard():void {
var i:int;
var j:int;
var ip1:int = clsRevCom.getFirstPlayer();
var ip2:int = clsRevCom.getOtherPlayer(ip1);
graphics.clear();
graphics.lineStyle(1, 0x000000);
for (i = 0; i < 9; i++) {
graphics.moveTo(mSize, i*mSize+mSize);
graphics.lineTo(mSize*9, i*mSize+mSize);
graphics.moveTo(i*mSize+mSize,mSize );
graphics.lineTo(i*mSize+mSize,mSize*9);
}
for (i = 1; i < 9; i++) {
for (j = 1; j < 9; j++) {
if (boardData[i][j] == ip1) {
// 黒:円を描く (中を塗りつぶす)
graphics.lineStyle(1, 0x000000);
graphics.beginFill(0x000000);
graphics.drawCircle(mSize*i+mSize/2, mSize*j+mSize/2, mSize*0.4);
graphics.endFill();
}else if (boardData[i][j] == ip2) {
// 白:円を描く (中を塗りつぶさない)
graphics.lineStyle(1, 0x000000);
graphics.drawCircle(mSize*i+mSize/2, mSize*j+mSize/2, mSize*0.4);
graphics.endFill();
}
}
}
}
//指定升目に打てるかチェック=====================================
// itiNam:升目の名称("a1"~"h8")
// ip:プレイヤー(1,2)
// 戻り値:反転する升目数+1(打った駒)、0=置けません
public function chkIti(itiNam:String, ip:int):int {
var intRet:int = 0;
var itiX:int = clsRevCom.getYokoIti(itiNam)+1;
var itiY:int = clsRevCom.getTateIti(itiNam)+1;
if (itiX == 0 || itiY == 0) { return intRet; }
intRet = chkItiXY(itiX, itiY, ip);
return intRet;
}
// itiX,itiY:チェックする升目
// ip:プレイヤー
// 戻り値:反転する升目数+1(打った駒)、0=置けません
private function chkItiXY(itiX:int,itiY:int, ip:int):int {
var intRet:int = 0;
var ip2:int =clsRevCom.getOtherPlayer(ip);
//指定升目に何もない
if (boardData[itiX][itiY] != 0) { return intRet; }
//8方向をチェック、まず敵の色(繰り返し)、自分の色のチェックを行う
for (var idx:int = -1; idx <= 1; idx++) {
for (var idy:int = -1; idy <= 1; idy++) {
if (idx != 0 || idy != 0) {
if (boardData[itiX+idx][itiY+idy] == ip2) {
var n:int = chkItiXYnext(itiX+idx, itiY+idy, idx, idy, ip,ip2);
if( n>0) { intRet+=n;}
}
}
}
}
if (intRet > 0) { intRet++;}
return intRet;
}
//指定升目に打てるかチェック(再起関数)
// itiX,itiY:チェックする升目
// idx,idy:チェックする方向(8方向の1方向)
// ip,ip2:自分と相手
// 戻り値:true:配置できる
private function chkItiXYnext(itiX:int, itiY:int,
idx:int, idy:int, ip:int, ip2:int):int {
var intRet:int = 0;
//自分の色ならOK
if (boardData[itiX + idx][itiY + idy] == ip) {
intRet = 0;
//敵の色なら次をチェック
} else if(boardData[itiX + idx][itiY + idy] == ip2) {
intRet=chkItiXYnext(itiX+idx, itiY+idy, idx, idy, ip, ip2);
} else {
//その他(空、盤の外)ならNG
intRet = -1;
}
if (intRet >= 0) {
intRet++;
}
return intRet;
}
//指定升目に駒を置く=====================================
// itiNam:升目の名称("a1"~"h8")
// ip:プレイヤー(1,2)
// 戻り値:反転する升目数+1(打った駒)、0=置けません
public function okuIti(itiNam:String, ip:int):int {
var intRet:int = 0;
var itiX:int = clsRevCom.getYokoIti(itiNam)+1;
var itiY:int = clsRevCom.getTateIti(itiNam)+1;
if (itiX == 0 || itiY == 0) { return intRet; }
intRet = okuItiXY(itiX, itiY, ip);
if (intRet>0) {
disBoard();
arrRireki.push({Player:ip,MasuIti:itiNam,KomaSuu:intRet});
}
return intRet;
}
// itiX,itiY:チェックする升目
// ip:プレイヤー
// 戻り値:反転する升目数+1(打った駒)、0=置けません
private function okuItiXY(itiX:int,itiY:int, ip:int):int {
var intRet:int = 0;
var ip2:int =clsRevCom.getOtherPlayer(ip);
if (chkItiXY(itiX, itiY, ip) ==0) { return intRet; }
//8方向をチェックと駒を反転
for (var idx:int = -1; idx <= 1; idx++) {
for (var idy:int = -1; idy <= 1; idy++) {
if (idx != 0 || idy != 0) {
if (boardData[itiX + idx][itiY + idy] == ip2) {
var n:int = setItiXYnext(itiX + idx, itiY + idy, idx, idy, ip, ip2);
if( n>0) { intRet+=n;}
}
}
}
}
//反転した駒があるとき指定場祖にお置く
if (intRet > 0) {
boardData[itiX][itiY] = ip;
intRet++;
}
return intRet;
}
//指定升目に打てるかチェック、駒の反転(再起関数)
// itiX,itiY:チェックする升目
// idx,idy:チェックする方向(8方向の1方向)
// ip,ip2:自分と相手
// 戻り値:true:駒の反転あり
private function setItiXYnext(itiX:int, itiY:int,
idx:int, idy:int, ip:int, ip2:int):int {
var intRet:int = 0;
//自分と同じ駒ならOK
if (boardData[itiX + idx][itiY + idy] == ip) {
intRet = 0;
//相手と同じなら次をチェック
} else if (boardData[itiX + idx][itiY + idy] == ip2) {
intRet=setItiXYnext(itiX+idx, itiY+idy, idx, idy, ip, ip2);
} else {
intRet = -1;
}
//その他(空、盤の外)ならNG
//OKなら戻るとき反転する
if (intRet >= 0) {
boardData[itiX][itiY] = ip;
intRet++;
}
return intRet;
}
//指定プレーヤに打つ場所があるか=======================================
// ip:プレイヤー
// 戻り値:打つ場所の有(true)/無(false)
public function chkPlayer(ip:int):Boolean {
for (var itiX:int = 1; itiX < 9; itiX++) {
for (var itiY:int = 1; itiY < 9; itiY++) {
if (chkItiXY(itiX, itiY, ip) >0) { return true; }
}
}
return false;
}
//指定プレーヤ、未配置の駒数=================================================
// ip:プレイヤー(1,2)、0で未配置
// 戻り値:駒数
public function Kekka(ip:int):int {
var kazu:int = 0;
for (var itiX:int = 1; itiX < 9; itiX++) {
for (var itiY:int = 1; itiY < 9; itiY++) {
if (boardData[itiX][itiY] == ip) { kazu++;}
}
}
return kazu;
}
//指定位置の枡の状態================================================
// itiNam:升目の名称("a1"~"h8")
// 戻り値:黒(1)、白(2)、未(0)、升目不正(-1)
public function masuJyoutai(itiNam:String):int {
var itiX:int = clsRevCom.getYokoIti(itiNam)+1;
var itiY:int = clsRevCom.getTateIti(itiNam)+1;
if (itiX == 0 || itiY == 0) { return -1; }
return boardData[itiX][itiY];
}
//打った升目の履歴の取得=====================================================
// no:no回前(0が一回前)の履歴を取得
// 戻り値:履歴{Player:プレイヤー(1,2),MasuIti:升目名("a1","b5"),KomaSuu:反転した数+1}
// noが正しくないときnull
public function getRireki(no:int):Object {
var objRet:Object = null;
if (no >= 0 && no < arrRireki.length) {
objRet = arrRireki[arrRireki.length-no-1];
}
return objRet;
}
}