「石取りゲーム」を完成する

Font を設定して画面のレイアウトを変更し「石取りゲーム」を完成させます。

前田稔(Maeda Minoru)の超初心者のプログラム入門

プログラムの説明

  1. ページ先頭の画像を参考にして「石取りゲーム」を完成させて下さい。
    見栄えを良くするために Font を設定してタイトルやメッセージを表示します。
    フォントの設定は 文字フォントを設定して描画する を参照して下さい。
  2. グローバル領域にゲームで使用する領域を定義します。
    Count は山に積まれた石の数で、Max は一度に取り除くことができる個数です。
    Teban で人間とコンピュータの手番を識別します。
    pt はマウスがクリックされた座標を格納する領域です。
    Win, Lose でゲームの勝敗を記録します。
    rt1, rt2, rt3, rt4, でメッセージを表示する矩形領域を設定しています。
        int         Count;                  // 山に積まれた石の数
        int         Max;                    // 一度に取り除く最大数
        int         Teban;                  // 手番(0:Comp, 1:人間, 2:終了)
        POINT       pt;                     // クリックされた座標
        int         Win,Lose;               // 勝敗
        RECT        rt1 = { 80,80,400,180 };    // msg の表示
        RECT        rt2 = { 80,160,400,280 };   // 最大個数の表示
        RECT        rt3 = { 80,380,400,420 };   // "現在の勝敗"の表示
        RECT        rt4 = { 120,420,400,460 };  // ?勝  ?敗
    
        LPSTR       msg=
        { "山の石をあなたと私が交互に取り除きます。\n最後の石を取らされた方が負けです。\n\n"
          "今回取り除くことができる石の数は\n"
        };
        
  3. グローバル領域の続きです。
    str[256], wk[80]; は作業用の領域です。
    Log[30]; はプレイを記録しておいて「待った」のときにゲームを戻します。
    L_C が Log に記録されている手数で、R_POS はゲームを再現中の位置です。
    実際のゲームでは「待った」は許されませんが、コンピュータでは必須の機能です。
    hFont, hFontOld; はフォントを格納するハンドルです。
        char        str[256],wk[80];
        int         Log[30];                // Log Table
        int         L_C;                    // Log Count
        int         R_POS;                  // Replay Pos
        HFONT       hFont,hFontOld;
        
  4. マウスをクリックして人間がプレイする処理です。
    POINT 構造体にマウスの座標を格納して、座標から石の数を計算します。
    人間がプレイした後の山の状態を Log[] に記録して行きます。
    if (R_POS!=0) は、待ったからプレイを再開したときの判定です。
    同様にコンピュータのプレイも記録して下さい。
    人間のプレイが終わるとコンピュータの手番に設定してタイマをセットします。
            case WM_LBUTTONDOWN:
                if (Teban!=1)   break;
                pt.x= マウスの座標を格納して下さい
                pt.y= マウスの座標を格納して下さい
                work= 取り除く石の数を格納して下さい
                if (work<=0 || work>Max)
                {   wsprintf(str,"クリックの位置が不正です(最大 %d)",Max);
                    MessageBox(hWnd,str,"Error Message",MB_OK);
                    break;
                }
                Count-= 残った石の数を格納して下さい
                Teban= 0;
                if (R_POS!=0)
                {   L_C= R_POS;
                    R_POS= 0;
                }
                Log[L_C++]= Count;
                InvalidateRect(hWnd,NULL,TRUE);
                UpdateWindow(hWnd);
                SetTimer(hWnd, ID_TIMER, 600, NULL);
                break;
        
  5. ゲームを戻すメニューと戻した手を再現するメニューを追加します。
    「待った」のときは、人間が前回プレイする前(通常は2手)戻します。
        switch( wmId ) 
        {   case IDM_RESET:
                Start();
                InvalidateRect(hWnd,NULL,TRUE);
                break;
            case IDM_BACK:
                if (R_POS==0)   R_POS= L_C;
                if (R_POS>2)
                {   R_POS-= 2;
                    R_POS|= 1;              //奇数番目が人間側
                    Count= Log[R_POS-1];
                    Teban= 1;
                    InvalidateRect(hWnd,NULL,TRUE);
                }
                break;
            case IDM_NEXT:
                if (R_POS!=0 && R_POS<L_C-1)
                {   R_POS+= 2;
                    R_POS|= 1;              //奇数番目が人間側
                    Count= Log[R_POS-1];
                    Teban= 1;
                    InvalidateRect(hWnd,NULL,TRUE);
                }
                break;
        

【演習】

  1. プログラムを完成させて下さい。
  2. 勝敗が一目でわかるように図形で表して下さい。
    例えば、星の画像やにこにこマークなどを並べます。
  3. 強さのレベルを設定するメニューを設けて下さい。
    コンピュータの強さは、乱数で石を取り除く確率で調整します。

超初心者のプログラム入門(Win32API C++)