//============================================================================= // UpperHandGame.java // Copyright(c) 1998 Satoshi Kobayashi, All rights reserved. //============================================================================= //============================================================================= // UpperHandGame // UpperHandのゲーム盤を定義するクラス。 //============================================================================= public class UpperHandGame extends Object { //----------------------------------------------------------------------------- // クラス変数定義 //----------------------------------------------------------------------------- // 状態を示す定数の定義 public final static int FIRST = 0; // 先手の玉がある状態 public final static int SECOND = 1; // 後手の玉がある状態 public final static int NUTRAL = 2; // 中立の玉がある状態 public final static int MOVABLE = 3; // 玉が置ける状態 public final static int UNMOVABLE = 4; // 玉が置けない状態 // 1つ下の位置を示す定数の定義 public final static int downPosition[][] = { // 位置 - ( x, y, z) {-1, -1, -1, -1}, // 0 - ( 0, 0, 4) {-1, -1, -1, -1}, // 1 - ( 1, 0, 4) {-1, -1, -1, -1}, // 2 - ( 2, 0, 4) {-1, -1, -1, -1}, // 3 - ( 3, 0, 4) {-1, -1, -1, -1}, // 4 - ( 4, 0, 4) {-1, -1, -1, -1}, // 5 - ( 0, 1, 4) {-1, -1, -1, -1}, // 6 - ( 1, 1, 4) {-1, -1, -1, -1}, // 7 - ( 2, 1, 4) {-1, -1, -1, -1}, // 8 - ( 3, 1, 4) {-1, -1, -1, -1}, // 9 - ( 4, 1, 4) {-1, -1, -1, -1}, // 10 - ( 0, 2, 4) {-1, -1, -1, -1}, // 11 - ( 1, 2, 4) {-1, -1, -1, -1}, // 12 - ( 2, 2, 4) {-1, -1, -1, -1}, // 13 - ( 3, 2, 4) {-1, -1, -1, -1}, // 14 - ( 4, 2, 4) {-1, -1, -1, -1}, // 15 - ( 0, 3, 4) {-1, -1, -1, -1}, // 16 - ( 1, 3, 4) {-1, -1, -1, -1}, // 17 - ( 2, 3, 4) {-1, -1, -1, -1}, // 18 - ( 3, 3, 4) {-1, -1, -1, -1}, // 19 - ( 4, 3, 4) {-1, -1, -1, -1}, // 20 - ( 0, 4, 4) {-1, -1, -1, -1}, // 21 - ( 1, 4, 4) {-1, -1, -1, -1}, // 22 - ( 2, 4, 4) {-1, -1, -1, -1}, // 23 - ( 3, 4, 4) {-1, -1, -1, -1}, // 24 - ( 4, 4, 4) { 0, 1, 5, 6}, // 25 - ( 0, 0, 3) { 1, 2, 6, 7}, // 26 - ( 1, 0, 3) { 2, 3, 7, 8}, // 27 - ( 2, 0, 3) { 3, 4, 8, 9}, // 28 - ( 3, 0, 3) { 5, 6, 10, 11}, // 29 - ( 0, 1, 3) { 6, 7, 11, 12}, // 30 - ( 1, 1, 3) { 7, 8, 12, 13}, // 31 - ( 2, 1, 3) { 8, 9, 13, 14}, // 32 - ( 3, 1, 3) {10, 11, 15, 16}, // 33 - ( 0, 2, 3) {11, 12, 16, 17}, // 34 - ( 1, 2, 3) {12, 13, 17, 18}, // 35 - ( 2, 2, 3) {13, 14, 18, 19}, // 36 - ( 3, 2, 3) {15, 16, 20, 21}, // 37 - ( 0, 3, 3) {16, 17, 21, 22}, // 38 - ( 1, 3, 3) {17, 18, 22, 23}, // 39 - ( 2, 3, 3) {18, 19, 23, 24}, // 40 - ( 3, 3, 3) {25, 26, 29, 30}, // 41 - ( 0, 0, 2) {26, 27, 30, 31}, // 42 - ( 1, 0, 2) {27, 28, 31, 32}, // 43 - ( 2, 0, 2) {29, 30, 33, 34}, // 44 - ( 0, 1, 2) {30, 31, 34, 35}, // 45 - ( 1, 1, 2) {31, 32, 35, 36}, // 46 - ( 2, 1, 2) {33, 34, 37, 38}, // 47 - ( 0, 2, 2) {34, 35, 38, 39}, // 48 - ( 1, 2, 2) {35, 36, 39, 40}, // 49 - ( 2, 2, 2) {41, 42, 44, 45}, // 50 - ( 0, 0, 1) {42, 43, 45, 46}, // 51 - ( 1, 0, 1) {44, 45, 47, 48}, // 52 - ( 0, 1, 1) {45, 46, 48, 49}, // 53 - ( 1, 1, 1) {50, 51, 52, 53} // 54 - ( 0, 0, 0) }; //----------------------------------------------------------------------------- // インスタンス変数定義 //----------------------------------------------------------------------------- // 位置ごとの状態 private int boardStatus[] = new int [55]; // プレーヤーごとの持ち玉の数 private int ball[] = new int[2]; // 次のプレーヤー private int nextPlayer; //----------------------------------------------------------------------------- // コンストラクタ定義 //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // public UpperHandGame() // ゲーム盤を初期状態にする。 //----------------------------------------------------------------------------- public UpperHandGame() { System.err.println("UpperHandGame() called."); // 位置ごとの状態を初期化する。 for (int p = 0; p < boardStatus.length; p++) { if (downPosition[p][0] == -1) { // 最下段の場合 boardStatus[p] = MOVABLE; // 玉が置ける } else { // その他 boardStatus[p] = UNMOVABLE; // 玉は置けない } } boardStatus[12] = NUTRAL; // 最下段の中央に中立の玉を置く。 // 持ち玉の数を初期化する。 ball[FIRST] = 27; ball[SECOND] = 27; // 次のプレーヤーを初期化する。 nextPlayer = FIRST; System.err.println("UpperHandGame() done."); } //----------------------------------------------------------------------------- // メソッド定義 //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // public boolean isFinish() // ゲームが終了しているときtrueを返す。 //----------------------------------------------------------------------------- public boolean isFinish() { // どちらかのプレーヤーの持ち玉がないとき、ゲームは終了している。 return (ball[FIRST] == 0 || ball[SECOND] == 0); } //----------------------------------------------------------------------------- // public int nextPlayer() // 次のプレーヤーを返す。 //----------------------------------------------------------------------------- public int nextPlayer() { if (isFinish()) { // ゲームが終了していたとき。 throw new Error("Game already finished"); // エラーとする。 } return nextPlayer; } //----------------------------------------------------------------------------- // public int[] moves() // 着手可能な手の一覧を返す。 //----------------------------------------------------------------------------- public int[] moves() { if (isFinish()) { // ゲームが終了していたとき。 throw new Error("Game already finished"); // エラーとする。 } // すべての位置について着手可能か調べ、着手可能な手を配列に入れる。 // すべての位置について調べ終わったとき、nには着手可能な手の数が入って // いる。 int tmpMoves[] = new int[boardStatus.length]; int n = 0; for (int p = 0; p < boardStatus.length; p++) { if (boardStatus[p] == MOVABLE) { tmpMoves[n] = p; n++; } } // 着手可能な手と同じ数の要素をもつ配列に移し替える。 int moves[] = new int[n]; for (int i = 0; i < moves.length; i++) { moves[i] = tmpMoves[i]; } return moves; } //----------------------------------------------------------------------------- // private void putBall(int p, int player) // pで指定された位置にplayerの玉を置く。 //----------------------------------------------------------------------------- private void putBall(int p, int player) { if (ball[player] == 0) { // 持ち玉がない場合 return; // 何もしない。 } // 持ち玉を減らす。 ball[player]--; // 盤に玉を置く。 boardStatus[p] = player; } //----------------------------------------------------------------------------- // public void makeMove(int p) // pで指定された手を打つ。 //----------------------------------------------------------------------------- public void makeMove(int p) { if (isFinish()) { // ゲームが終了していたとき。 throw new Error("Game already finished"); // エラーとする。 } else if (boardStatus[p] != MOVABLE) { // 着手不能な場所の場合 throw new Error("Bad move"); // エラーとする。 } // まず、指定された位置に玉を置く。 putBall(p, nextPlayer()); // 次に、ボーナス玉を置く。 checkBonus: for (int i = 0; i < boardStatus.length; i++) { if (boardStatus[i] == UNMOVABLE) { // 着手不可能な位置の場合、ボーナス玉の判定を行う。 int first = 0; // 1つ下の先手の玉の数(0で初期化) int second = 0; // 1つ下の後手の玉の数(0で初期化) // 1つ下の玉の状態を調べる。 for (int d = 0; d < 4; d++) { switch (boardStatus(downPosition[i][d])) { case FIRST: first++; break; case SECOND: second++; break; case NUTRAL: break; default: // 1箇所でも下に玉がない場合、ボーナス玉の判定は不要。 // 次の位置のボーナス玉の判定を行う。 continue checkBonus; } } if (first >= 3) { // 先手の玉が3つ以上あった場合 putBall(i, FIRST); // 先手のボーナス玉を置く。 } else if (second >= 3) { // 後手の玉が3つ以上あった場合 putBall(i, SECOND); // 後手のボーナス玉を置く。 } else { // どちらの玉も3つ以上ない場合 boardStatus[i] = MOVABLE; // 玉が置けるようにする。 } } } // プレーヤーを交代する。 nextPlayer = (nextPlayer == FIRST) ? SECOND : FIRST; } //----------------------------------------------------------------------------- // public int boardStatus(int p) // 位置pの状態を返す。 //----------------------------------------------------------------------------- public int boardStatus(int p) { return boardStatus[p]; } //----------------------------------------------------------------------------- // public int ball(int player) // プレーヤーplayerの持ち玉の数を返す。 //----------------------------------------------------------------------------- public int ball(int player) { return ball[player]; } }