今回は、その基礎として交互に石を置くだけのものを作ってみます。すでに相手が置いてあるところには
石は置けません。碁盤はA,B,C行、1,2,3列で位置指定はA2, C3などのように指定します。
今回のプログラムはコンソールアプリを前提にしており、カーソルの位置指定として
SetConsoleCursorPosition関数を使っています。この関数が使えない環境の時は他のカーソル位置
指定の方法を準備してください。エスケープシーケンスが使える環境の人はこれを利用するのも
一つの方法でしょう。グラフィックスライブラリが使える環境の人は、この中にカーソル位置を指定する
関数が用意されていることもあります。
まず、石の位置と誰の石かを記憶しておく配列を用意します。 ここではint ban[3][3];という配列を用意しておきます。 最初に配列と碁盤の位置関係を自分で決めます。
碁盤のA1をban[0][0], A2をban[0][1], A3をban[0][2], B1をban[1][0], B2をban[1][1], B3をban[1][2] C1をban[2][0], C2をban[2][1], C3をban[2][2]に対応させます。 何も置かれていないときは0,先手の石が置かれているときは1, 後手の石が置かれているときは2を代入することにします。
画面の左上のカーソル位置を(0,0)とすると
ban[0][0]に対応するカーソル位置は(4, 1)となります。
ban[0][1]に対応するカーソル位置は(8, 1)となります。
ban[0][2]に対応するカーソル位置は(12, 1)となります。
ban[1][0]に対応するカーソル位置は(4, 2)となります。
ban[1][1]に対応するカーソル位置は(8, 2)となります。
ban[row][col]に対応するカーソル位置は(col * 4 + 4, row + 1)となります。
rowとcolの関係が紛らわしいので、プログラムを作り始める前に 整理しておきましょう。
では、プログラムを見てみましょう。
コンソールアプリなのでwindows.hをインクルードしておきます。// game01.c #include <windows.h> #include <stdio.h> int banshow(HANDLE); int Locate(HANDLE, int, int); int check_location(int, int); //すでに駒がおかれていないかどうか調べる int ban[3][3];
自作関数はbanshow(盤と石を表示), Locate(カーソル位置を指定), check_location(指定されたところに石が置けるかどうかを判定) とmain関数です。
グローバル変数にban[3][3]の配列を用意しておきます。
まず、標準出力ハンドルを取得しておきます(位置指定を SetConsoleCursorPosition関数を用いない場合は不要)。int main() { HANDLE hOut; BOOL bOrd = TRUE; //FALSE:後手 TRUE:先手 int i, row =0, col=0; char location[8]; //位置指定 A2, B1,など char *sente = "先手", *gote = "後手"; char order[8]; hOut = GetStdHandle(STD_OUTPUT_HANDLE); banshow(hOut); for (i = 0; i < 9; i++) { if (bOrd) strcpy(order, sente); else strcpy(order, gote); INP: Locate(hOut, 28, 5); printf(" "); Locate(hOut, 0, 5); printf("位置を指定してください(%s)", order); gets(location); if (location[0] == 'A' || location[0] == 'a') row = 0; else if (location[0] == 'B' || location[0] == 'b') row = 1; else if (location[0] == 'C' || location[0] == 'c') row = 2; else if (location[0] == 'Q' || location[0] == 'q') break; else { Locate(hOut, 0, 6); printf("指定が違います"); goto INP; } if (location[1] == '1') col = 0; else if (location[1] == '2') col = 1; else if (location[1] == '3') col = 2; else { Locate(hOut, 0, 6); printf("指定が違います"); goto INP; } if (check_location(row, col) != 0) { Locate(hOut, 0, 6); printf("そこには置けません!"); goto INP; } if (bOrd) ban[row][col] = 1; else ban[row][col] = 2; bOrd = !bOrd; banshow(hOut); Locate(hOut, 0, 6); printf(" "); } printf("\n\n"); return 0; }
次に、石が何も置かれていない碁盤を表示(banshow関数)。
碁盤目の数だけ次の動作を繰り返します。
ざっとこんな所です。 なお位置入力でqまたはQと入力すると終了します。0.現在先手の番ならbOrdがTRUE, 後手ならbOrdがFALSEです 1.先手の(または後手)置く石の位置入力を要求 2.入力された位置が正しいかどうかを判定。 間違っていたら1.にもどる 3.入力位置に対応するban[row][col]に 先手なら1, 後手なら2を代入 4.bOrdを先手なら後手に、後手なら先手に変更 5.盤と石を表示
盤と石を表示する関数です。int banshow(HANDLE hStdOut) { int i, j; Locate(hStdOut, 0, 0); printf(" [1][2][3]\n"); printf("[A]\n"); printf("[B]\n"); printf("[C]\n"); for (i = 0; i < 3; i++) { for (j = 0; j < 3; j++) { if (ban[i][j] == 1) { Locate(hStdOut, j * 4 + 4, i + 1); printf("○"); } if (ban[i][j] == 2) { Locate(hStdOut, j * 4 + 4, i + 1); printf("×"); } } } return 0; }
すべてのマス目を調べてban[row][col]が1なら「○」2なら 「×」を表示します。この時○×を表示する位置を混乱しないように してください。
カーソル位置を指定する関数です。第59章を参照してみてください。int Locate(HANDLE hOut, int x, int y) { COORD dwPos; dwPos.X = (SHORT)x; dwPos.Y = (SHORT)y; if (SetConsoleCursorPosition(hOut, dwPos) == 0) return -1; else return 0; }
指定された位置に、すでに石が置かれているかどうか (石を置くことができるかどうか)を調べる関数です。 中身は簡単です。対応するban[row][col]が0以外ならば すでに石が置かれていますので、-1を返します。 0ならば0を返します。int check_location(int row, int col) { if (ban[row][col] == 0) return 0; else return -1; }
今回は、碁盤に石を置くだけのプログラムでした。 石を置いた後に勝ち負けを判定する関数を実行すれば 立派なゲームとなります。挑戦してみてください。
Update Apr/09/2001 By Y.Kumei