第60章 357の山 その4


今回は、どの山からいくつ取ったかを一手ごとに記録して 勝敗がついたら、これを表示する機能を付けます。



では、早速プログラムを見てみましょう。

// game35704.cpp

#include <windows.h>
#include <time.h>
#include <conio.h>

class Mountain
{
    HANDLE hOut, hIn;
    struct _mt{
        int mt[15];
        int st[15];
    }mtst;

    int te;
    int mt[3];
    int sente, order;
    int judge();
    int show_stone();
    int init();
    int take_stone();
    int comp_take();
    int no_of_0();
    int locate(int, int);
    int print(char *);
    int input(char *, int);
    int show_list();
    int cls();
public:
    Mountain();
    int play();
};
Mountainクラスにmtst構造体が増えました。これに、 記録を残していくようにします。

teメンバも増えました。これは、現在何手目かを示します(第n手の時n-1)。

show_listメンバ関数は、勝敗がついたらそれまでの手を表示します。

clsメンバ関数は画面を全消去します。

Mountain, show_stone, judgeの各メンバ関数に変更はありません。
int Mountain::take_stone()
{
    char ans[8];
    int i, stone, mtorder;

    for (i = 4; i <= 5; i++) {
        locate(0, i);
        print("                                       ");
    }
    
    if (sente != order) {
        comp_take();
        if (judge() == 0) {
            for (i = 4; i < 6; i++) {
                locate(0, i);
                print("                               ");
            }
            locate(0, 7);
            print("コンピュータの勝ちです");
            show_list();
            _getch();
            return 1;
        }
        if (order == 1)
            order = 0;
        else
            order = 1;
        te++;
        return 0;
    }

    while (1) {
        locate(0, 6);
        print("                                   ");
        locate(0, 4);
        print("どの山からとりますか(A,B,C)---");
        if (input(ans, 8) == -1) {
            locate(0, 6);
            print("内部エラーです");
            _getch();
            exit(-1);
        }
        if (strcmp(ans, "A") != 0 && strcmp(ans, "B") != 0 && strcmp(ans, "C") != 0 &&
            strcmp(ans, "a") != 0 && strcmp(ans, "b") != 0 && strcmp(ans, "c") != 0) {
            for (i = 4; i <= 5; i++) {
                locate(0, i);
                print("                                       ");
            }
            locate(0, 6);
            print("山の指定が正しくありません");
            _getch();
            continue;
        } else {
            ans[0] = toupper(ans[0]);
            mtorder = ans[0] - 'A';
            if (mt[mtorder] == 0) {
                for (i = 4; i <= 5; i++) {
                    locate(0, i);
                    print("                                       ");
                }
                locate(0, 6);
                print("その山にはもう石はありません");
                _getch();
                continue;
            }
            break;
        }
    }
    
    while (1) {
        locate(0, 6);
        print("                                    ");
        locate(0, 5);
        print( "いくつとりますか---");
        if (input(ans, 8) == -1) {
            locate(0, 6);
            print("内部エラーです");
            _getch();
            exit(-1);
        }
        stone = atoi(ans);
        mt[mtorder] -= stone;
        if (mt[0] + mt[1] + mt[2] == 0) {
            locate(0, 5);
            print("                                       ");
            locate(0, 6);
            print("その取り方では山の石が全部0になります");
            _getch();
            mt[mtorder] += stone;
            continue;
        }
        mt[mtorder] += stone;
        if (mt[mtorder] - stone < 0 || stone <= 0) {
            locate(0, 5);
            print("                                       ");
            locate(0, 6);
            print("取る石の数が不正です");
            _getch();
            continue;
        } else {
            break;
        }
    }
    mt[mtorder] -= stone;
    show_stone();

    mtst.mt[te] = mtorder;
    mtst.st[te] = stone;

    if (judge() == 0) {
        for (i = 4; i <= 5; i++) {
            locate(0, i);
            print("                                       ");
        }
        locate(0, 7);
        print("あなたの勝ちです");
        show_list();
        return 1;
    }
        
    if (order == 1)
        order = 0;
    else
        order = 1;
    
    te++;
    return 0;
}
勝敗がついたらshow_listメンバ関数を呼んで、それまでの経過を表示させます。

人間が1手指すと(山から石を取ると)それをmtst構造体に記録します。

どちらかが1手終わる毎にteの数を1増やします。

int Mountain::init()
{
    char ans[8];

    mt[0] = 3;
    mt[1] = 5;
    mt[2] = 7;

    memset(&mtst, 0, sizeof(mtst));
    te = 0;
    
    cls();
    locate(0, 0);
    print("あなたが先手になりますか(Y/N)---");
    if (input(ans, 8) == -1) {
        locate(0, 6);
            print("内部エラーです");
            _getch();
            exit(-1);
    }

    if (ans[0] == 'y' || ans[0] == 'Y') {
        sente = 1;
    } else {
        sente = 0;
    }
    order = 1;
    return 0;
}
ゲームの初期化関数です。

構造体を全部0で埋めます。teも0に戻します。 clsメンバ関数を使って画面を消去しています。

その後、どちらが先手になるかを決めています。

int Mountain::comp_take()
{
    int mtorder, stone;
    char mtname, szBuf[64];
    int jump = 0, i;


    srand((unsigned)time(NULL));
    
    if (no_of_0() == 0) { //どの山も0ではない
        //2-4-6パターンにする
        if (mt[0] == 3 && mt[1] == 4 && mt[2] == 6) {
            mtorder = 0;
            stone = 1;
            mt[0] = 2;
            goto end;
        }
        if (mt[1] == 5 && mt[0] == 2 && mt[2] == 6) {
            mtorder = 1;
            stone = 1;
            mt[1] = 4;
            goto end;
        }
        if (mt[2] == 7 && mt[0] == 2 && mt[1] == 4) {
            mtorder = 2;
            stone = 1;
            mt[2] = 6;
            goto end;
        }
        //1-4-5パターンにする
        if (mt[0] > 1 && mt[1] + mt[2] == 9 && mt[1] * mt[2] == 20) {
            mtorder = 0;
            stone = mt[0] - 1;
            mt[0] = 1;
            goto end;
        }
        if (mt[1] > 4 && mt[0] == 1 && mt[2] == 5) {
            mtorder = 1;
            stone = mt[1] - 4;
            mt[1] = 4;
            goto end;
        }
        if (mt[2] > 4 && mt[0] == 1 && mt[1] == 5) {
            mtorder = 2;
            stone = mt[2] - 4;
            mt[2] = 4;
            goto end;
        }
        if (mt[2] > 5 && mt[0] == 1 && mt[1] == 4) {
            mtorder = 2;
            stone = mt[2] - 4;
            mt[2] = 4;
            goto end;
        }
        //1-2-3パターンにする
        if (mt[0] > 1 && mt[1] + mt[2] == 5 && mt[1] * mt[2] == 6) {
            mtorder = 0;
            stone = mt[0] - 1;
            mt[0] = 1;
            goto end;
        }
        if (mt[0] > 2 && mt[1] + mt[2] == 4 && mt[1] * mt[2] == 3) {
            mtorder = 0;
            stone = mt[0] - 2;
            mt[0] = 2;
            goto end;
        }
        if (mt[0] == 3 && mt[1] + mt[2] == 3 && mt[1] * mt[2] == 2) {
            mtorder = 0;
            stone = mt[0] - 3;
            mt[0] = 3;
            goto end;
        }
        if (mt[1] > 1 && mt[0] + mt[2] == 5 && mt[0] * mt[2] == 6) {
            mtorder = 1;
            stone = mt[1] - 1;
            mt[1] = 1;
            goto end;
        }
        if (mt[1] > 2 && mt[0] + mt[2] == 4 && mt[0] * mt[2] == 3) {
            mtorder = 1;
            stone = mt[1] - 2;
            mt[1] = 2;
            goto end;
        }
        if (mt[1] > 3 && mt[0] + mt[2] == 3 && mt[0] * mt[2] == 2) {
            mtorder = 1;
            stone = mt[1] - 3;
            mt[1] = 3;
            goto end;
        }
        if (mt[2] > 1 && mt[0] + mt[1] == 5 && mt[0] * mt[1] == 6) {
            mtorder = 2;
            stone = mt[2] - 1;
            mt[2] = 1;
            goto end;
        }
        if (mt[2] > 2 && mt[0] + mt[1] == 4 && mt[0] * mt[1] == 3) {
            mtorder = 2;
            stone = mt[2] - 2;
            mt[2] = 2;
            goto end;
        }
        if (mt[2] > 3 && mt[0] + mt[1] == 3 && mt[0] * mt[1] == 2) {
            mtorder = 2;
            stone = mt[2] - 3;
            mt[2] = 3;
            goto end;
        }
        //1-1-1パターンにする
        if (mt[0] == mt[1] && mt[0] == 1 && mt[2] > 1) {
            mtorder = 2;
            stone = mt[2] - 1;
            mt[2] = 1;
            goto end;
        }
        if (mt[1] == mt[2] && mt[1] == 1 && mt[0] > 1) {
            mtorder = 0;
            stone = mt[0] - 1;
            mt[0] = 1;
            goto end;
        }
        if (mt[0] == mt[2] && mt[0] == 1 && mt[1] > 1) {
            mtorder = 1;
            stone = mt[1] - 1;
            mt[1] = 1;
            goto end;
        }
        if (mt[0] == mt[1]) {
            mtorder = 2;
            stone = mt[2];
            mt[mtorder] = 0;
            goto end;;
        }
        if (mt[1] == mt[2]) {
            mtorder = 0;
            stone = mt[0];
            mt[mtorder] = 0;
            goto end;;
        }
        if (mt[2] == mt[0]) {
            mtorder = 1;
            stone = mt[1];
            mt[mtorder] = 0;
            goto end;;
        }
    }

    //0の山が1つだけである
    if (no_of_0() == 1) {
        if (mt[0] == 0) {
            if (mt[1] == 1) {
                mtorder = 2;
                stone = mt[2];
                mt[2] = 0;
                goto end;
            }
            if (mt[2] == 1) {
                mtorder = 1;
                stone = mt[1];
                mt[1] = 0;
                goto end;
            }

            if (mt[1] > mt[2]) {
                mtorder = 1;
                stone = mt[1] - mt[2];
                mt[mtorder] -= stone;
                goto end;
            }
            if (mt[2] > mt[1]) {
                mtorder = 2;
                stone = mt[2] - mt[1];
                mt[mtorder] -= stone;
                goto end;
            } 
            if (mt[2] == mt[1]){
                mtorder = 1;
                stone = 1;
                mt[mtorder] -= stone;
                goto end;
            }
        }
        if (mt[1] == 0) {
            if (mt[0] == 1) {
                mtorder = 2;
                stone = mt[2];
                mt[2] = 0;
                goto end;
            }
            if (mt[2] == 1) {
                mtorder = 0;
                stone = mt[0];
                mt[0] = 0;
                goto end;
            }
            if (mt[0] > mt[2]) {
                mtorder = 0;
                stone = mt[0] - mt[2];
                mt[mtorder] -= stone;
                goto end;
            }
            if (mt[2] > mt[0]) {
                mtorder = 2;
                stone = mt[2] - mt[0];
                mt[mtorder] -= stone;
                goto end;
            }
            if (mt[0] == mt[2]) {
                mtorder = 2;
                stone = 1;
                mt[mtorder] -= stone;
                goto end;
            }
        }
        if (mt[2] == 0) {
            if (mt[1] == 1) {
                mtorder = 0;
                stone = mt[0];
                mt[0] = 0;
                goto end;
            }
            if (mt[0] == 1) {
                mtorder = 1;
                stone = mt[1];
                mt[1] = 0;
                goto end;
            }
            if (mt[0] > mt[1]) {
                mtorder = 0;
                stone = mt[0] - mt[1];
                mt[mtorder] -= stone;
                goto end;
            }
            if (mt[1] > mt[0]) {
                mtorder = 1;
                stone = mt[1] - mt[0];
                mt[mtorder] -= stone;
                goto end;
            }
            if (mt[1] == mt[0]) {
                mtorder = 0;
                stone = 1;
                mt[mtorder] -= 1;
                goto end;
            }
        }
    }

    if (no_of_0() == 2) {
        for (i = 0; i < 3; i++) {
            if (mt[i] != 0) {
                stone = mt[i] - 1;
                mtorder = i;
                mt[i] = 1;
                goto end;
            }
        }
    }
    while (1) {
        mtorder = rand() % 3;
        if (mt[mtorder] == 0)
            continue;
        else
            break;
    }
    while (1) {
        stone = 1;
        mt[mtorder] -= stone;
        if (mt[0] + mt[1] + mt[2] == 0) {
            mt[mtorder] += stone;
            continue;
        } else {
            break;
        }
    }
end:
    mtst.mt[te] = mtorder;
    mtst.st[te] = stone;
    mtname = mtorder + 'A';
    locate(0, 4);
    wsprintf(szBuf, "コンピュータは%cから%d個取ります", mtname, stone);
    print(szBuf);
    _getch();
    show_stone();
    return 0;
}
変更点は、コンピュータの取る石が決まったら、mtst構造体に記録している点だけです。
int Mountain::play()
{
    int ret;
    char ans[8];

    while (1) {
        init();
        show_stone();
        while (1) {
            ret = take_stone();
            if (ret == 1)
                break;
        }
        
        print("\nもう一度やりますか(Y/N) ");
        if (input(ans, 8) == -1) {
            print("\n内部エラーです");
            _getch();
            exit(-1);
        }
        if (ans[0] == 'y' || ans[0] == 'Y') {
            continue;
        } else {
            cls();
            break;
        }
    }
    return 0;
}
画面消去にclsメンバ関数を使っています。
no_of_0, locate, print, inputの各メンバ関数に変更はありません。
int Mountain::show_list()
{
    int i;
    char szBuf[64], szSashite[8];

    print("\n\n");
    print("*** 今回の勝負 ***\n");
    for (i = 0; i < 15; i++) {
        if (mtst.st[i] == 0)
            break;
        if ((sente == 1 && i % 2 == 0) || (sente == 0 && i % 2 != 0))
            strcpy(szSashite, "You");
        else
            strcpy(szSashite, "Com");
        wsprintf(szBuf, "第%0d手 %s %cより%d個\n", i + 1, szSashite, mtst.mt[i] + 'A', mtst.st[i]);
        print(szBuf);
    }
    return 0;
}
手をmtst構造体から読み出して表示しています。
int Mountain::cls()
{
    COORD  coset;
    DWORD dwWritten;

    CONSOLE_SCREEN_BUFFER_INFO cinf;
    GetConsoleScreenBufferInfo(hOut, &cinf);

    coset.X = 0;
    coset.Y = 0;
    
    if (FillConsoleOutputCharacter(hOut, ' ', cinf.dwSize.X * cinf.dwSize.Y, coset, &dwWritten) ==0)
        return -1;
    return 0;
}
画面消去関数です。
main関数に変更はありません。
今回は簡単でした。記録した手順を再現する機能を作ってみてください。
[C++Index] [総合Index] [Previous Chapter] [Next Chapter]

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