「ぷよぷよ」のラストになります。
残りは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 続行するには何かキーを押してください・・・
これで完成です。
このような考え方は色々なゲームで使われています。
ゲームをプレイするだけでなく、仕組みについて考え、一部でも作ってみるようにしましょう。
※コンソールなので限界はありますが・・・