今回は、前章で作ったプログラムに
「必勝法もどき」を適応して、かなり強くします。
「必勝法もどき」については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