Index

HOME > プログラムTOP > JavaScript



ゲーム BingoPlus(2)

 コンピュータ対戦型のビンゴゲームの後編です。下図はゲームの終了画面で、コンピュータ側が勝ったところです。(IE5以上/NN6以上)





ページ1
概要
Cell クラス
Player クラス
初期化

ページ2
終了の判断
コンピュータの思考
イベント処理

sasaraan programming

Exposition

■終了の判断

 ゲームの終了は、五個そろった列が五列以上あるかどうかで判断します。それには、Playerオブジェクトの GetLineCount関数で行のそろい具合を取得します。ここで得た値は Linesプロパティに代入されています。以下の例では、0個そろった列が2列、1個そろった列が3列、2個そろった列が2列・・・、という意味になります。したがって、index=5 のところが5以上となればゲーム終了となります。
Lines プロパティ
 ・index : 0 1 2 3 4  : = セルの個数
 ・value : 2 3 2 3 1  : = 列数
 ゲームの進行状況は盤面に表示されます。ステータス文字列を確定した後、Playerオブジェクトの SetStatusメソッドで設定します。上図のセルの上にある、 "CPU : ... " " YOU : ... " の部分です。ゲーム終了の時は、最後に、隠れていた CPU側のセルに数字を表示して関数を終えます。
// 終了判定(戻り値 : 終了...true, 続行...false)
function IsGameOver() 
{
    // 行のそろい具合の取得
    oCPU.GetLineCount();        // CPU側
    oYOU.GetLineCount();        // ユーザー側

    // 五個そろった列が五列ない時 → falseを返してゲーム続行
    if (oCPU.Lines[5] < 5 && oYOU.Lines[5] < 5) {
        oCPU.SetStatus(oCPU.Name + " : " + oCPU.Lines[5] + " lines");
        oYOU.SetStatus(oYOU.Name + " : " + oYOU.Lines[5] + " lines");
        return false;
    }

    // 五個そろった列が五列以上ある時 → trueを返してゲーム終了
    if (oCPU.Lines[5] >= 5 && oYOU.Lines[5] >= 5) {        /* 引き分け */
        oCPU.SetStatus(oCPU.Name + " : " + oCPU.Lines[5] + " === DRAW ===");
        oYOU.SetStatus(oYOU.Name + " : " + oYOU.Lines[5] + " === DRAW ===");
    } else if (oCPU.Lines[5] >= 5) {                                /* コンピュータの勝ち */
        oCPU.SetStatus(oCPU.Name + " : " + oCPU.Lines[5] + " +++ WIN!+++");
        oYOU.SetStatus(oYOU.Name + " : " + oYOU.Lines[5] + " --- LOOSE ---");
    } else {                                                                  /* ユーザーの勝ち */
        oCPU.SetStatus(oCPU.Name + " : " + oCPU.Lines[5] + " --- LOOSE ---");
        oYOU.SetStatus(oYOU.Name + " : " + oYOU.Lines[5] + " +++ WIN!+++");
    }
    for (var i=0; i<25; i++) {        /* CPU側のセルに数字を表示 */
        oCell = document.getElementById(oCPU.Name + i);
        if (oCPU.Cells[i].Selected) {
            oCell.style.backgroundColor = oCPU.SelColor;  // 選択時の背景色
        } else {
            oCell.style.backgroundColor = oCPU.DefColor;  // 非選択時の背景色
        }
        oCPU.Cells[i].SetValue(oCPU.Cells[i].Figure);        // 数字の表示
    }
    return true;
} 

■コンピュータの思考

 コンピュータ側の手番では、Playerオブジェクトの GetNextCellメソッドで次の手を取得します。このメソッド内では、すべての手を仮に打ってみて、GetLineCountメソッドで行のそろい具合を取得します。このそろい具合を点数化し、さらにセル自身の重み(Weightプロパティ)を加えることで最終的なポイントを算出して比較します。この点数が最も高いもののインデックス値が返されてきます。なお、セルの重みは、グローバル変数の aWeightで設定した値(1〜9点)です。
GetNextCellメソッドでのセルの点数評価
 ・列  数  : 0個   1個   2個   3個   4個   5個
 ・ポイントA : 0点/列 1点/列 2点/列 3点/列 4点/列 5点/列
 ・ポイントB : 0点/列 1点/列 2点/列 4点/列 7点/列 10点/列
 上記が設定した点数です。ポイントAは5個の列が3個そろうまでの適用、ポイントBは5個の列が3個以上の時の適用としています。前半ではウェイト重視、後半では5個そろえることを重視するためです。このパターンをさらに細かく設定することで、ゲームの難易度を調整できます。ちなみに、この設定では、コンピュータはあまり強くありません。
 以下の関数では、このようにして取得したインデックスとをもとに、実際に選択状態(Selected=true)にしています。さらに、同じ数字をユーザー側のセルから探し出して選択状態にする必要があります。
 そして最後にゲーム終了の判定をして関数を終えます。
// CPU 側の手番の処理
function CPU_Turn() 
{
    var nIndex = oCPU.GetNextCell();        // 次の手の位置(セルのインデックス)の取得
    oCPU.Cells[nIndex].Selected = true;    // セルを選択状態に設定

    // 同じ数字をユーザー側から探して選択状態にする
    var i;
    for (i=0; i<25; i++) {
        if (oYOU.Cells[i].Figure == oCPU.Cells[nIndex].Figure) {
            oYOU.Cells[i].Selected = true;
            document.getElementById(oYOU.Name + i).style.backgroundColor = oYOU.SelColor;
        }	
    }

    // ゲームが終了していない時はユーザー側の手番をオンにして続行
    if (!IsGameOver()) {
        oYOU.Turn = true;
    }
} 

■イベント処理

 ボタンや要素のクリックイベントとマウスイベントに対応する関数群です。
・Cell_Click : セル(実際はA要素)のクリックイベント(ユーザー側のセルにのみ対応)
・Cell_MouseMove : セルのマウスオーバーとマウスアウトイベント(ユーザー側のセルのみに対応)
・Start_Click : スタートボタンのクリックイベント(ゲームの開始)
・Order_Click : 順番(先攻/後攻)ボタンのクリックイベント(次のゲームから有効)
・Help_Click  : ヘルプボタンのクリック(ルールの表示)
// セルのクリックイベント
function Cell_Click(index) 
{
    // ユーザーの手番でないか選択済みセルなら抜ける
    if (!oYOU.Turn || oYOU.Cells[index].Selected) return;

    // ユーザーの手番をオフにして、クリックしたセルを選択状態に設定
    var oCell = document.getElementById(oYOU.Name + index);
    oYOU.Turn = false;
    oYOU.Cells[index].Selected = true;
    oCell.style.backgroundColor = oYOU.SelColor;

    // CPU側の同じ数字のセルを探して選択状態にする
    var i;
    for (i=0; i<25; i++) {
        if (oCPU.Cells[i].Figure == oYOU.Cells[index].Figure) {
            oCPU.Cells[i].Selected = true;
        }
    }

    // ゲーム続行ならCPUに手番を移す
    if (!IsGameOver()) {
        CPU_Turn();
    }
}

// セルのマウスイベント
// ... 引数index : セルのインデックス
// ... 引数mode : 0=mouseover, 1=mouseout
function Cell_MouseMove(index, mode) 
{
    var oCell = document.getElementById(oYOU.Name + index);
    if (mode == 0) {                /* mouseover時の背景色の変更 */
        if (!oYOU.Cells[index].Selected) {
            oCell.style.backgroundColor = oYOU.OverColor;
        }
    } else if (mode == 1) {        /* mouseout時の背景色の変更 */
        if (oYOU.Cells[index].Selected) {
            oCell.style.backgroundColor = oYOU.SelColor;
        } else {
            oCell.style.backgroundColor = oYOU.DefColor;
        }
    }
}

// スタートボタンのクリックイベント
function Start_Click() 
{
    // ステータス文字列の初期化
    oCPU.SetStatus(oCPU.Name + " : " + "0 lines");
    oYOU.SetStatus(oYOU.Name + " : " + "0 lines");

    // 各セルの数字の入れ替え
    oCPU.Shuffle();
    oYOU.Shuffle();

    // セルの初期化
    var i;
    for (i=0; i<25; i++) {
        // 選択状態をオフに設定
        oCPU.Cells[i].Selected = false;
        oYOU.Cells[i].Selected = false;

        // 文字列の表示
        oCPU.Cells[i].SetValue(" ");                          // CPU側は空の文字列
        oYOU.Cells[i].SetValue(oYOU.Cells[i].Figure);    // ユーザー側は数字を表示

        // テーブルセル(A要素)の背景色の設定
        document.getElementById(oCPU.Name+i).style.backgroundColor = oCPU.DefColor;
        document.getElementById(oYOU.Name+i).style.backgroundColor = oYOU.DefColor;
    }

    // セルの選択の開始
    if (oYOU.Order == 0) {    /* ユーザー先攻時 */
        oYOU.Turn = true;    // ユーザーの手番をオンにする
    } else {                         /* ユーザー後攻時 */
        oYOU.Turn = false;   // ユーザーの手番をオフにする
        CPU_Turn();             // CPUに手番を渡す
    }
}

// 順番(先攻/後攻)ボタンのクリックイベント
function Order_Click() 
{
    if (oYOU.Order == 0) {
        oYOU.Order = 1;                                                    // プロパティ値の変更
        document.getElementById("order").value = "後 攻";  // 表示文字列の変更
    } else {
        oYOU.Order = 0;                                                    // プロパティ値の変更
        document.getElementById("order").value = "先 攻";  // 表示文字列の変更
    }
}

// ヘルプボタンのクリックイベント
function Help_Click() 
{
    // ルールをダイアログボックスに表示
    var s  = "";
    s += "数字を選んでいき、先に5列を完成させた方が勝ちです。 \n";
    s += "そろえる一列は、縦横ななめのいずれでもかまいません。 \n\n";
    s += "ゲームは、[スタート] ボタンで開始します。  \n";
    s += "なお、[先攻/後攻] ボタンで先攻と後攻の切り替えができます。";
    alert(s);
} 

www.sasaraan.net

(c) morijoh