1.4 返せる石数を調べる処理 |
本節では実際には石を返さずに、何石返るのかを調べる処理について説明します。
この関数を使うのは後になってからですが、何石返るのかを調べるだけなら、1手戻す処理がない分実際に石を返すよりも高速です。
また、着手できるかどうかの判定にも使用できます。
返せる石数を調べるBoard_CountFlips()は、Board_Flip()と同様に1方向に対して返せる石数を調べる関数を全方向に対して呼び出します。
まずはこの1方向に対して返せる石数を調べる関数Board_CountFlipsLine()を見てみましょう。
static int Board_CountFlipsLine(const Board *self, int in_color, int in_pos, int in_dir) { int result = 0; int op = OPPONENT_COLOR(in_color); int pos; for (pos = in_pos + in_dir; self->Disk[pos] == op; pos += in_dir) { result++; } if (self->Disk[pos] != in_color) { return 0; } return result; }
Board_FlipLine()と処理が似ているので、何をしているのかはすぐにわかると思います。
違うのは最初のforループで石数を数えている点と、石を返す処理がない点です。
それでは返せる石数を調べる処理Board_CountFlips()を見てみましょう。
int Board_CountFlips(const Board *self, int in_color, int in_pos) { int result = 0; if (self->Disk[in_pos] != EMPTY) { return 0; } result += Board_CountFlipsLine(self, in_color, in_pos, DIR_UP_LEFT); result += Board_CountFlipsLine(self, in_color, in_pos, DIR_UP); result += Board_CountFlipsLine(self, in_color, in_pos, DIR_UP_RIGHT); result += Board_CountFlipsLine(self, in_color, in_pos, DIR_LEFT); result += Board_CountFlipsLine(self, in_color, in_pos, DIR_RIGHT); result += Board_CountFlipsLine(self, in_color, in_pos, DIR_DOWN_LEFT); result += Board_CountFlipsLine(self, in_color, in_pos, DIR_DOWN); result += Board_CountFlipsLine(self, in_color, in_pos, DIR_DOWN_RIGHT); return result; }
これもBoard_Flip()と似ています。
石を返す処理がない分Board_Flip()よりも処理が少なくなっています。
行っているのは、全方向に対してBoard_CountFlipsLine()を呼び出し、戻り値を足しているだけです。
次に着手できるかどうか調べる関数Board_CanFlip()を見てみましょう。
int Board_CanFlip(const Board *self, int in_color, int in_pos) { if (self->Disk[in_pos] != EMPTY) { return 0; } if (Board_CountFlipsLine(self, in_color, in_pos, DIR_UP_LEFT)) { return 1; } if (Board_CountFlipsLine(self, in_color, in_pos, DIR_UP)) { return 1; } if (Board_CountFlipsLine(self, in_color, in_pos, DIR_UP_RIGHT)) { return 1; } if (Board_CountFlipsLine(self, in_color, in_pos, DIR_LEFT)) { return 1; } if (Board_CountFlipsLine(self, in_color, in_pos, DIR_RIGHT)) { return 1; } if (Board_CountFlipsLine(self, in_color, in_pos, DIR_DOWN_LEFT)) { return 1; } if (Board_CountFlipsLine(self, in_color, in_pos, DIR_DOWN)) { return 1; } if (Board_CountFlipsLine(self, in_color, in_pos, DIR_DOWN_RIGHT)) { return 1; } return 0; }
各方向に対してBoard_CountFlipsLine()を呼び出しているだけです。
そしてどれか1方向でも石を返せるならば1を返し、どの方向にも石を返せない場合には0を返します。
本節の最後は、着手可能かどうかを調べる関数Board_CanPlay()です。
int Board_CanPlay(const Board *self, int in_color) { int x, y; for (x = 0; x < BOARD_SIZE; x++) { for (y = 0; y < BOARD_SIZE; y++) { if (Board_CanFlip(self, in_color, Board_Pos(x, y))) { return 1; } } } return 0; }
各マスに対して着手できるかどうかを調べているだけです。 本節は、前節の内容に比べると簡単だったと思います。