今回は、前章で作ったプログラムに
「必勝法もどき」を適応して、かなり強くします。
「必勝法もどき」についてはC言語編第77章を参照してください。
では、プログラムを見てみましょう。
リソース・スクリプトに変更はありません。
//        35702.cpp
#ifndef STRICT
    #define STRICT
#endif
#include <windows.h>
#include <windowsx.h>
#include <stdlib.h>
#include <time.h>
#include "resource.h"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK MyDlgProc(HWND, UINT, WPARAM, LPARAM);
ATOM InitApp(HINSTANCE);
BOOL InitInstance(HINSTANCE, int);
BOOL StartGame(HWND);
BOOL ShowStone(HWND);
int comp_take(HWND);
int human_take(HWND);
int judge(HWND);
int no_of_0();
int ShowCompMsg(HWND, int, int);
char szClassName[] = "game35702";    //ウィンドウクラス
HINSTANCE hInst;
int nStone[3]; //各山の石の数
char szTxt[3][8], szStone[3][32];
BOOL bSente, bOrder;//コンピュータが先手かどうか, 現在の差し手
int nMtOrder, nTakeStone;
no_of_0, ShowCompMsg関数が増えました。前者は石が0である山の数を
調べ、後者はコンピュータがどの山からいくつ石を取るかをメッセージボックスで
表示する関数です。(ま、名前の通りです)
WinMain, InitApp, InitInstance, WndProc, StartGame, ShowStone, MyDlgProc の各関数に変更はありません。
int comp_take(HWND hWnd)
{
    int mtorder, stone, i;
    char szBuf[256];
    srand((unsigned)time(NULL));
    
    if (no_of_0() == 0) { //どの山も0ではない
        //2-4-6パターンにする
        if (nStone[0] == 3 && nStone[1] == 4 && nStone[2] == 6) {
            mtorder = 0;
            stone = 1;
            nStone[0] = 2;
            ShowCompMsg(hWnd, mtorder, stone);
        }
        if (nStone[1] == 5 && nStone[0] == 2 && nStone[2] == 6) {
            mtorder = 1;
            stone = 1;
            nStone[1] = 4;
            ShowCompMsg(hWnd, mtorder, stone);
        }
        if (nStone[2] == 7 && nStone[0] == 2 && nStone[1] == 4) {
            mtorder = 2;
            stone = 1;
            nStone[2] = 6;
            ShowCompMsg(hWnd, mtorder, stone);
        }
        //1-4-5パターンにする
        if (nStone[0] > 1 && nStone[1] + nStone[2] == 9 && nStone[1] * nStone[2] == 20) {
            mtorder = 0;
            stone = nStone[0] - 1;
            nStone[0] = 1;
            ShowCompMsg(hWnd, mtorder, stone);
        }
        if (nStone[1] > 4 && nStone[0] == 1 && nStone[2] == 5) {
            mtorder = 1;
            stone = nStone[1] - 4;
            nStone[1] = 4;
            ShowCompMsg(hWnd, mtorder, stone);
        }
        if (nStone[2] > 4 && nStone[0] == 1 && nStone[1] == 5) {
            mtorder = 2;
            stone = nStone[2] - 4;
            nStone[2] = 4;
            ShowCompMsg(hWnd, mtorder, stone);
        }
        if (nStone[2] > 5 && nStone[0] == 1 && nStone[1] == 4) {
            mtorder = 2;
            stone = nStone[2] - 4;
            nStone[2] = 4;
            ShowCompMsg(hWnd, mtorder, stone);
        }
        //1-2-3パターンにする
        if (nStone[0] > 1 && nStone[1] + nStone[2] == 5 && nStone[1] * nStone[2] == 6) {
            mtorder = 0;
            stone = nStone[0] - 1;
            nStone[0] = 1;
            ShowCompMsg(hWnd, mtorder, stone);
        }
        if (nStone[0] > 2 && nStone[1] + nStone[2] == 4 && nStone[1] * nStone[2] == 3) {
            mtorder = 0;
            stone = nStone[0] - 2;
            nStone[0] = 2;
            ShowCompMsg(hWnd, mtorder, stone);
        }
        if (nStone[0] == 3 && nStone[1] + nStone[2] == 3 && nStone[1] * nStone[2] == 2) {
            mtorder = 0;
            stone = nStone[0] - 3;
            nStone[0] = 3;
            ShowCompMsg(hWnd, mtorder, stone);
        }
        if (nStone[1] > 1 && nStone[0] + nStone[2] == 5 && nStone[0] * nStone[2] == 6) {
            mtorder = 1;
            stone = nStone[1] - 1;
            nStone[1] = 1;
            ShowCompMsg(hWnd, mtorder, stone);
        }
        if (nStone[1] > 2 && nStone[0] + nStone[2] == 4 && nStone[0] * nStone[2] == 3) {
            mtorder = 1;
            stone = nStone[1] - 2;
            nStone[1] = 2;
            ShowCompMsg(hWnd, mtorder, stone);
        }
        if (nStone[1] > 3 && nStone[0] + nStone[2] == 3 && nStone[0] * nStone[2] == 2) {
            mtorder = 1;
            stone = nStone[1] - 3;
            nStone[1] = 3;
            ShowCompMsg(hWnd, mtorder, stone);
        }
        if (nStone[2] > 1 && nStone[0] + nStone[1] == 5 && nStone[0] * nStone[1] == 6) {
            mtorder = 2;
            stone = nStone[2] - 1;
            nStone[2] = 1;
            ShowCompMsg(hWnd, mtorder, stone);
        }
        if (nStone[2] > 2 && nStone[0] + nStone[1] == 4 && nStone[0] * nStone[1] == 3) {
            mtorder = 2;
            stone = nStone[2] - 2;
            nStone[2] = 2;
            ShowCompMsg(hWnd, mtorder, stone);
        }
        if (nStone[2] > 3 && nStone[0] + nStone[1] == 3 && nStone[0] * nStone[1] == 2) {
            mtorder = 2;
            stone = nStone[2] - 3;
            nStone[2] = 3;
            ShowCompMsg(hWnd, mtorder, stone);
        }
        //1-1-1パターンにする
        if (nStone[0] == nStone[1] && nStone[0] == 1 && nStone[2] > 1) {
            mtorder = 2;
            stone = nStone[2] - 1;
            nStone[2] = 1;
            ShowCompMsg(hWnd, mtorder, stone);
        }
        if (nStone[1] == nStone[2] && nStone[1] == 1 && nStone[0] > 1) {
            mtorder = 0;
            stone = nStone[0] - 1;
            nStone[0] = 1;
            ShowCompMsg(hWnd, mtorder, stone);
        }
        if (nStone[0] == nStone[2] && nStone[0] == 1 && nStone[1] > 1) {
            mtorder = 1;
            stone = nStone[1] - 1;
            nStone[1] = 1;
            ShowCompMsg(hWnd, mtorder, stone);
        }
        if (nStone[0] == nStone[1]) {
            mtorder = 2;
            stone = nStone[2];
            nStone[mtorder] = 0;
            ShowCompMsg(hWnd, mtorder, stone);
        }
        if (nStone[1] == nStone[2]) {
            mtorder = 0;
            stone = nStone[0];
            nStone[mtorder] = 0;
            ShowCompMsg(hWnd, mtorder, stone);
        }
        if (nStone[2] == nStone[0]) {
            mtorder = 1;
            stone = nStone[1];
            nStone[mtorder] = 0;
            ShowCompMsg(hWnd, mtorder, stone);
        }
    }
    //0の山が1つだけである
    if (no_of_0() == 1) {
        if (nStone[0] == 0) {
            if (nStone[1] == 1) {
                mtorder = 2;
                stone = nStone[2];
                nStone[2] = 0;
                ShowCompMsg(hWnd, mtorder, stone);
            }
            if (nStone[2] == 1) {
                mtorder = 1;
                stone = nStone[1];
                nStone[1] = 0;
                ShowCompMsg(hWnd, mtorder, stone);
            }
            if (nStone[1] > nStone[2]) {
                mtorder = 1;
                stone = nStone[1] - nStone[2];
                nStone[mtorder] -= stone;
                ShowCompMsg(hWnd, mtorder, stone);
            }
            if (nStone[2] > nStone[1]) {
                mtorder = 2;
                stone = nStone[2] - nStone[1];
                nStone[mtorder] -= stone;
                ShowCompMsg(hWnd, mtorder, stone);
            } 
            if (nStone[2] == nStone[1]){
                mtorder = 1;
                stone = 1;
                nStone[mtorder] -= stone;
                ShowCompMsg(hWnd, mtorder, stone);
            }
        }
        if (nStone[1] == 0) {
            if (nStone[0] == 1) {
                mtorder = 2;
                stone = nStone[2];
                nStone[2] = 0;
                ShowCompMsg(hWnd, mtorder, stone);
            }
            if (nStone[2] == 1) {
                mtorder = 0;
                stone = nStone[0];
                nStone[0] = 0;
                ShowCompMsg(hWnd, mtorder, stone);
            }
            if (nStone[0] > nStone[2]) {
                mtorder = 0;
                stone = nStone[0] - nStone[2];
                nStone[mtorder] -= stone;
                ShowCompMsg(hWnd, mtorder, stone);
            }
            if (nStone[2] > nStone[0]) {
                mtorder = 2;
                stone = nStone[2] - nStone[0];
                nStone[mtorder] -= stone;
                ShowCompMsg(hWnd, mtorder, stone);
            }
            if (nStone[0] == nStone[2]) {
                mtorder = 2;
                stone = 1;
                nStone[mtorder] -= stone;
                ShowCompMsg(hWnd, mtorder, stone);
            }
        }
        if (nStone[2] == 0) {
            if (nStone[1] == 1) {
                mtorder = 0;
                stone = nStone[0];
                nStone[0] = 0;
                ShowCompMsg(hWnd, mtorder, stone);
            }
            if (nStone[0] == 1) {
                mtorder = 1;
                stone = nStone[1];
                nStone[1] = 0;
                ShowCompMsg(hWnd, mtorder, stone);
            }
            if (nStone[0] > nStone[1]) {
                mtorder = 0;
                stone = nStone[0] - nStone[1];
                nStone[mtorder] -= stone;
                ShowCompMsg(hWnd, mtorder, stone);
            }
            if (nStone[1] > nStone[0]) {
                mtorder = 1;
                stone = nStone[1] - nStone[0];
                nStone[mtorder] -= stone;
                ShowCompMsg(hWnd, mtorder, stone);
            }
            if (nStone[1] == nStone[0]) {
                mtorder = 0;
                stone = 1;
                nStone[mtorder] -= 1;
                ShowCompMsg(hWnd, mtorder, stone);
            }
        }
    }
    if (no_of_0() == 2) {
        for (i = 0; i < 3; i++) {
            if (nStone[i] != 0) {
                stone = nStone[i] - 1;
                mtorder = i;
                nStone[i] = 1;
                ShowCompMsg(hWnd, mtorder, stone);
            }
        }
    }
    while (1) {
        mtorder = rand() % 3;
        if (nStone[mtorder] == 0)
            continue;
        else
            break;
    }
    while (1) {
        stone = 1;
        nStone[mtorder] -= stone;
        if (nStone[0] + nStone[1] + nStone[2] == 0) {
            nStone[mtorder] += stone;
            continue;
        } else {
            break;
        }
    }
    return 0;
}
こりゃ、ちょっと長い関数ですが、中身はC言語編第77章と
同じです。どこが違うかというと、C言語編では、コンピュータが取る石の数が決まったら
gotoで関数の最後の方にあるend:に行っていましたが、今度はShowCompMsg関数を
呼び出すことにしました。結局のところGUIだろうが何だろうが、基本的な部分は大して
変わりません。
int ShowCompMsg(HWND hWnd, int mtorder, int stone)
{
    char szBuf[256];
    wsprintf(szBuf, "コンピュータは%cから%d個取りました\n", mtorder + 'A', stone);
    MessageBox(hWnd, szBuf, "コンピュータ", MB_OK);
    ShowStone(hWnd);
    if (judge(hWnd) == 0) {
        MessageBox(hWnd, "コンピュータの勝ちです", "判定", MB_OK);
        return -1;
    }
    bOrder = !bOrder;
    return 0;
}
コンピュータが、どの山からいくつ石を取るかを表示する関数です。
すべて前出のcomp_take関数から呼ばれます。特に説明は不要ですね。
int no_of_0()
{
    int no, i;
    no = 0;
    for (i = 0; i < 3; i++) {
        if (nStone[i] == 0)
            no++;
    }
    return no;
}
これも簡単です。山を一つ一つ調べて石のない山の数を返します。
human_take, judge関数に変更はありません。と、いうことで前章のプログラムはかなり強くなりました。あとは、対戦成績を ファイルに記録するとか、いろいろ付加機能をつけてみてください。
Update 04/Jun/2002 By Y.Kumei