では、早速プログラムを見てみましょう。
// 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関数に変更はありません。今回は簡単でした。記録した手順を再現する機能を作ってみてください。
Update Jun/23/2002 By Y.Kumei