/**
 * IntBoard クラスは、碁盤に見立てた行列で石の配置を表します。
 * @author Jiro Suzuki
 */
public class IntBoard{

    private static final int ROSU=19;
    private static final int SQUARENUM=ROSU*ROSU;
    private int[][] intBoard=new int[ROSU][ROSU];
    private int bhama;
    private int whama;

    private int lastTurn;
    private int dame;
    private int[][] agehamaPT;
    private int nxtR;
    private int nxtC;
    private int ixAG;        //アゲハマ着点テーブル用インデックス初期化
    private int ixAGMax;     //アゲハマ着点テーブルデータ数最大値初期化
    private int row;
    private int col;

    /**
     * 石が置かれていない空のインスタンスを生成します。
     */
    IntBoard(){
        initializeBan();
        bhama=0;
        whama=0;
        agehamaPT=new int[SQUARENUM][2];
    }

    /**
     * インスタンスを初期化します。
     */
    public void initialize(){
        initializeBan();
        bhama=0;
        whama=0;
        agehamaPT=new int[SQUARENUM][2];
    }

    private void initializeBan(){
        for(int r=0;r<ROSU;r++){
            for(int c=0;c<ROSU;c++){
                intBoard[r][c]=0;
            }
        }
    }

    /**
     * 盤面を一手更新します。入力の座標はJava添字形式(0〜18)で受取ります。
     * @param inColor 石の色
     * @param inRow 行番号
     * @param inCol 列番号
     */
    public void update(int inColor,int inRow,int inCol){
        lastTurn=inColor;
        //本当はここで着点エラー判定を行う予定。エラーでないときは石を置く。
        returnValue();  //前回最終手を、表示用の値(11or12)から通常の値(1or2)に戻す。
        if(intBoard[inRow][inCol]==0){
            intBoard[inRow][inCol]=inColor;
            procAgehama();  //アゲハマ処理
        }
        //今回の最終手を表示用の値(11or12)に変換する。
        translateValue(inColor,inRow,inCol);
    }

    private void returnValue(){
        for(int row=0;row<ROSU;row++){
            for(int col=0;col<ROSU;col++){
                if(intBoard[row][col]>10){
                    intBoard[row][col]=intBoard[row][col]-10;
                }
            }
        }
    }

    private void translateValue(int inColor,int inRow,int inCol){
        intBoard[inRow][inCol]=inColor + 10;
    }

    //----- アゲハマ処理 START -----
    private void procAgehama(){           //盤上に配置された石すべてについて
        for(row=0;row<ROSU;row++){
            for(col=0;col<ROSU;col++){
                if(intBoard[row][col]!=0 & intBoard[row][col]!=lastTurn){
                    checkAgehama();
                }
            }
        }
    }

    private void checkAgehama(){
        countDame();
        removeAgehama();
    }

    private void countDame(){
        //アゲハマ着点テーブル初期化
        for(int i=0;i<SQUARENUM;i++){
            agehamaPT[i][0]=-1;
            agehamaPT[i][1]=-1;
        }
        agehamaPT[0][0]=row;  //検索開始着点設定
        agehamaPT[0][1]=col;
        dame=0;             //ダメ個数初期化
        ixAG=0;             //アゲハマ着点テーブル用インデックス初期化
        ixAGMax=0;          //アゲハマ着点テーブルデータ数最大値初期化

        while(ixAG<=ixAGMax){
            if(dame==0){
                nxtR=agehamaPT[ixAG][0]-1;   //検索基点の上の点
                nxtC=agehamaPT[ixAG][1];
                countDameSub();
            }
            if(dame==0){
                nxtR=agehamaPT[ixAG][0]+1;   //検索基点の下の点
                nxtC=agehamaPT[ixAG][1];
                countDameSub();
            }
            if(dame==0){
                nxtR=agehamaPT[ixAG][0];
                nxtC=agehamaPT[ixAG][1]-1;   //検索基点の左の点
                countDameSub();
            }
            if(dame==0){
                nxtR=agehamaPT[ixAG][0];
                nxtC=agehamaPT[ixAG][1]+1;   //検索基点の右の点
                countDameSub();
            }
            ixAG=ixAG+1;
        }

    }

    private void countDameSub(){
        boolean isNotMatch=true;
        if(nxtR>=0 && nxtR<ROSU &&   //盤上の着点の場合のみ処理続行
           nxtC>=0 && nxtC<ROSU){
            if(intBoard[nxtR][nxtC]==0){   //検索点に石がないときはダメをカウント
                dame++;
            }
            else{
                if(intBoard[nxtR][nxtC]!=lastTurn){  //最終手番の反対色のとき処理続行
                    for(int i=0;i<SQUARENUM;i++){
                        if(nxtR==agehamaPT[i][0] && nxtC==agehamaPT[i][1]){
                            isNotMatch=false;
                        }
                    }
                    if(isNotMatch){
                        ixAGMax=ixAGMax+1;
                        agehamaPT[ixAGMax][0]=nxtR;
                        agehamaPT[ixAGMax][1]=nxtC;
                    }
                }
            }
        }
    }

    private void removeAgehama(){
        if(dame==0){ //石群のダメが空いていないとき
            for(ixAG=0;ixAG<=ixAGMax;ixAG++){
                switch(intBoard[agehamaPT[ixAG][0]][agehamaPT[ixAG][1]]){
                    case 1:whama=whama+1;
                         break;
                    case 2:bhama=bhama+1;
                         break;
                }
                intBoard[agehamaPT[ixAG][0]][agehamaPT[ixAG][1]]=0;
            }
        }
    }
    //----- アゲハマ処理 END -----

    /**
     * 盤面データを取得します。
     * @return 盤面データ
     */
    public int[][] getIntBoard(){
        return intBoard;
    }

    /**
     * 黒番のアゲハマ数を取得します。
     * @return 黒番のアゲハマ数
     */
    public int getBhama(){
        return bhama;
    }

    /**
     * 白番のアゲハマ数を取得します。
     * @return 白番のアゲハマ数
     */
    public int getWhama(){
        return whama;
    }
}