第334章 357ゲーム その2


今回は、前章で作ったプログラムに 「必勝法もどき」を適応して、かなり強くします。 「必勝法もどき」については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関数に変更はありません。
と、いうことで前章のプログラムはかなり強くなりました。あとは、対戦成績を ファイルに記録するとか、いろいろ付加機能をつけてみてください。
[SDK第4部 Index] [総合Index] [Previous Chapter] [Next Chapter]

Update 04/Jun/2002 By Y.Kumei
当ホーム・ページの一部または全部を無断で複写、複製、 転載あるいはコンピュータ等のファイルに保存することを禁じます。