今回は、必勝法もどきを使ってコンピュータを無敵(?)状態にします。
これは、C言語編第77章のC++版です。
必勝パターンに持ち込む方法C言語版と全く同じです。
では、早速プログラムを見てみましょう。
// game35702.cpp
#include <iostream.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
class Mountain
{
int mt[3];
int sente, order;
int judge();
int show_stone();
int init();
int take_stone();
int comp_take();
int no_of_0();
public:
int play();
};
Mountainクラスにno_of_0メンバ関数が増えました。これは、石の数が0である
山の数を返します。
int Mountain::show_stone()
{
cout << "[A]---" << mt[0] << ", [B]---" << mt[1] << ", [C]---" << mt[2] << endl;
return 0;
}
int Mountain::judge()
{
if (mt[0] + mt[1] + mt[2] == 1)
return 0;
else
return 1;
}
int Mountain::take_stone()
{
char ans[8];
int stone, mtorder;
if (sente != order) {
comp_take();
if (judge() == 0) {
cout << "コンピュータの勝ちです" << endl;
return 1;
}
if (order == 1)
order = 0;
else
order = 1;
return 0;
}
while (1) {
cout << "どの山からとりますか(A,B,C)---";
cin >> ans;
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) {
cout << "山の指定が正しくありません" << endl;
continue;
} else {
ans[0] = toupper(ans[0]);
mtorder = ans[0] - 'A';
if (mt[mtorder] == 0) {
cout << "その山にはもう石はありません" << endl;
continue;
}
break;
}
}
while (1) {
cout << "いくつとりますか---";
cin >> ans;
stone = atoi(ans);
mt[mtorder] -= stone;
if (mt[0] + mt[1] + mt[2] == 0) {
cout << "その取り方では山の石が全部0になります" << endl;
mt[mtorder] += stone;
continue;
}
mt[mtorder] += stone;
if (mt[mtorder] - stone < 0 || stone <= 0) {
cout << "取る石の数が不正です" << endl;
continue;
} else {
break;
}
}
mt[mtorder] -= stone;
show_stone();
if (judge() == 0) {
cout << "あなたの勝ちです" << endl;
return 1;
}
if (order == 1)
order = 0;
else
order = 1;
return 0;
}
int Mountain::init()
{
char ans[8];
mt[0] = 3;
mt[1] = 5;
mt[2] = 7;
cout << "あなたが先手になりますか(Y/N)---";
cin >> ans;
if (ans[0] == 'y' || ans[0] == 'Y') {
sente = 1;
} else {
sente = 0;
}
order = 1;
return 0;
}
これらのメンバ関数に変更はありません。
int Mountain::comp_take()
{
int mtorder, stone;
char mtname;
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:
mtname = mtorder + 'A';
cout << "コンピュータは" << mtname << "から" << stone << "個取りました" << endl;
show_stone();
return 0;
}
コンピュータが取る石を決定するメンバ関数です。具体的考え方は
C言語編第77章を参照してください。
int Mountain::play()
{
int ret;
char ans[8];
while (1) {
init();
show_stone();
while (1) {
ret = take_stone();
if (ret == 1)
break;
}
cout << endl << "もう一度やりますか(Y/N)";
cin >> ans;
if (ans[0] == 'y' || ans[0] == 'Y')
continue;
else
break;
}
return 0;
}
このメンバ関数に変更はありません。
int Mountain::no_of_0()
{
int no, i;
no = 0;
for (i = 0; i < 3; i++) {
if (mt[i] == 0)
no++;
}
return no;
}
石の数が0である山の数を返す関数です。特に説明は不要ですね。
int main()
{
Mountain m;
m.play();
return 0;
}
main関数はいつもと同じです。今回のプログラムでは、コンピュータは相当強くなったはずです。 必勝法もどきを知らない人と対戦するとまず100%コンピュータが勝つはずです。
対戦中、石の数を「○」で表示するなど、視覚に訴えられるように改良してみてください。
Update Apr/29/2002 By Y.Kumei