「ぷよぷよ」のラストになります。
残りはCheckDeletePuyo関数内で呼び出す3つの関数を作成するのみです。
4.「ぷよ」のつながりをチェックする
これが再帰呼び出しをする関数になります。
未チェックの「ぷよ」を起点に上下左右のつながりを探し、削除フラグに1(CHECKING)を入れていきます。
必要な引数は以下の通りです。
配列 field 配列 deleteFlag 座標 x, y チェックしたい「ぷよ」の色 sourColor |
前回の塗りつぶしの応用ですから、仕組みは皆さんで考えてみてください。
関数名 CheckConnection 戻り値 なし 引 数 フィールド、削除フラグ、X座標、Y座標、チェックしたい「ぷよ」の色 機 能 同じ色の「ぷよ」のつながりをチェックする |
void CheckConnection(const int field[ROW][COL], int deleteFlag[ROW][COL], const int x, const int y, const int sourColor) { if (deleteFlag[y][x] != NO_CHECK) { return; } deleteFlag[y][x] = CHECKING; if (y - 1 >= 0) { if (field[y - 1][x] == sourColor) { CheckConnection(field, deleteFlag, x, y - 1, sourColor); } } if (x + 1 < COL) { if (field[y][x + 1] == sourColor) { CheckConnection(field, deleteFlag, x + 1, y, sourColor); } } if (y + 1 < ROW) { if (field[y + 1][x] == sourColor) { CheckConnection(field, deleteFlag, x, y + 1, sourColor); } } if (x - 1 >= 0) { if (field[y][x - 1] == sourColor) { CheckConnection(field, deleteFlag, x - 1, y, sourColor); } } } |
これで、つながっている「ぷよ」の個所に1(CHECKING)が格納されます。
この関数をCheckDeletePuyo関数から呼び出します。
void CheckDeletePuyo(const int field[ROW][COL], int deleteFlag[ROW][COL])
{
int i;
int j;
for (i = 0; i < ROW; i++) {
for (j = 0; j < COL; j++) {
if (field[i][j] != NONE && deleteFlag[i][j] == NO_CHECK) {
CheckConnection(field, deleteFlag, j, i, field[i][j]);
}
}
}
}
|
5.つながっている「ぷよ」の個数を調べる
次は、作成した削除フラグを元に1(CHECKING)の個数を調べて戻す関数を作ります。
関数名 CountCheckFlag 戻り値 つながっている「ぷよ」の数 引 数 削除フラグ 機 能 つながっている「ぷよ」の個数を調べる |
int CountCheckFlag(const int deleteFlag[ROW][COL]) { int i; int j; int counter = 0; for (i = 0; i < ROW; i++) { for (j = 0; j < COL; j++) { if (deleteFlag[i][j] == CHECKING) { counter++; } } } return counter; } |
難しい内容ではありませんね。
CheckDeletePuyo関数も更新します。
void CheckDeletePuyo(const int field[ROW][COL], int deleteFlag[ROW][COL]) { int i; int j; int counter; for (i = 0; i < ROW; i++) { for (j = 0; j < COL; j++) { if (field[i][j] != NONE && deleteFlag[i][j] == NO_CHECK) { CheckConnection(field, deleteFlag, j, i, field[i][j]); counter = CountCheckFlag(deleteFlag); } } } } |
6.削除フラグを更新する
個数を元に、削除すべきものは3(DELETE)に、そうでないものは2(CHECKED)に変更します。
関数名 UpdateDeleteFlag 戻り値 なし 引 数 削除フラグ、つながっている「ぷよ」の個数 機 能 削除フラグを更新する |
void UpdateDeleteFlag(int deleteFlag[ROW][COL], const int counter) { int i; int j; for (i = 0; i < ROW; i++) { for (j = 0; j < COL; j++) { if (deleteFlag[i][j] == CHECKING) { if (counter >= 4) { deleteFlag[i][j] = DELETE; } else { deleteFlag[i][j] = CHECKED; } } } } } |
これで関数は全て揃いました。
CheckDeletePuyo関数も完成です。
void CheckDeletePuyo(const int field[ROW][COL], int deleteFlag[ROW][COL])
{
int i;
int j;
int counter;
for (i = 0; i < ROW; i++) {
for (j = 0; j < COL; j++) {
if (field[i][j] != NONE && deleteFlag[i][j] == NO_CHECK) {
CheckConnection(field, deleteFlag, j, i, field[i][j]);
counter = CountCheckFlag(deleteFlag);
UpdateDeleteFlag(deleteFlag, counter);
}
}
}
}
|
それでは、最後にプログラムの全文を書いておきます。
<sample program 153-01>
#include <stdio.h> #define ROW 10 #define COL 6 #define COLOR 6 enum { NONE, RED, BLUE, YELLOW, GREEN, PURPLE, }; enum { NO_CHECK, CHECKING, CHECKED, DELETE, }; void ShowField(const int field[ROW][COL]); void ShowDeleteFlag(const int deleteFlag[ROW][COL]); void CheckDeletePuyo(const int field[ROW][COL], int deleteFlag[ROW][COL]); void CheckConnection(const int field[ROW][COL], int deleteFlag[ROW][COL], const int x, const int y, const int sourColor); int CountCheckFlag(const int deleteFlag[ROW][COL]); void UpdateDeleteFlag(int deleteFlag[ROW][COL], const int counter); int main(void) { int field[ROW][COL] = { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0 }, { 0, 1, 2, 0, 0, 0 }, { 0, 1, 2, 1, 2, 0 }, { 0, 2, 2, 3, 2, 0 }, }; int deleteFlag[ROW][COL] = { NO_CHECK }; ShowField(field); CheckDeletePuyo(field, deleteFlag); ShowDeleteFlag(deleteFlag); return 0; } void ShowField(const int field[ROW][COL]) { const char GRAPHIC[COLOR][3] = { "□", "赤", "青", "黄", "緑", "紫", }; int i; int j; for (i = 0; i < ROW; i++) { for (j = 0; j < COL; j++) { printf("%s", GRAPHIC[field[i][j]]); } printf("\n"); } printf("\n"); } void ShowDeleteFlag(const int deleteFlag[ROW][COL]) { int i; int j; for (i = 0; i < ROW; i++) { for (j = 0; j < COL; j++) { printf("%2d", deleteFlag[i][j]); } printf("\n"); } printf("\n"); } void CheckDeletePuyo(const int field[ROW][COL], int deleteFlag[ROW][COL]) { int i; int j; int counter; for (i = 0; i < ROW; i++) { for (j = 0; j < COL; j++) { if (field[i][j] != NONE && deleteFlag[i][j] == NO_CHECK) { CheckConnection(field, deleteFlag, j, i, field[i][j]); counter = CountCheckFlag(deleteFlag); UpdateDeleteFlag(deleteFlag, counter); } } } } void CheckConnection(const int field[ROW][COL], int deleteFlag[ROW][COL], const int x, const int y, const int sourColor) { if (deleteFlag[y][x] != NO_CHECK) { return; } deleteFlag[y][x] = CHECKING; if (y - 1 >= 0) { if (field[y - 1][x] == sourColor) { CheckConnection(field, deleteFlag, x, y - 1, sourColor); } } if (x + 1 < COL) { if (field[y][x + 1] == sourColor) { CheckConnection(field, deleteFlag, x + 1, y, sourColor); } } if (y + 1 < ROW) { if (field[y + 1][x] == sourColor) { CheckConnection(field, deleteFlag, x, y + 1, sourColor); } } if (x - 1 >= 0) { if (field[y][x - 1] == sourColor) { CheckConnection(field, deleteFlag, x - 1, y, sourColor); } } } int CountCheckFlag(const int deleteFlag[ROW][COL]) { int i; int j; int counter = 0; for (i = 0; i < ROW; i++) { for (j = 0; j < COL; j++) { if (deleteFlag[i][j] == CHECKING) { counter++; } } } return counter; } void UpdateDeleteFlag(int deleteFlag[ROW][COL], const int counter) { int i; int j; for (i = 0; i < ROW; i++) { for (j = 0; j < COL; j++) { if (deleteFlag[i][j] == CHECKING) { if (counter >= 4) { deleteFlag[i][j] = DELETE; } else { deleteFlag[i][j] = CHECKED; } } } } } |
<実行結果>
□□□□□□ □□□□□□ □□□□□□ □□□□□□ □□□□□□ □□□□□□ □□□□□□ □赤青□□□ □赤青赤青□ □青青黄青□ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 3 0 0 0 0 2 3 2 2 0 0 3 3 2 2 0 続行するには何かキーを押してください・・・
これで完成です。
このような考え方は色々なゲームで使われています。
ゲームをプレイするだけでなく、仕組みについて考え、一部でも作ってみるようにしましょう。
※コンソールなので限界はありますが・・・