第5回
ゲームを完成させよう
IsClear()で完成状態を判定して、作ってきた関数をゲームループに組み込んでみよう!
1.クリアしたか調べよう
完成状態では、InitBoard()で入れたときと同じように、どの場所でも
正しい値 = 配列の添字 + 1
になっています。
1か所でも違う場所があれば、まだクリアしていません。
穴埋め
int IsClear(Board* board)
{
for (int i = 0; i < BOARD_WIDTH * BOARD_HEIGHT; i++)
{
if (__________________________________________)
{
return 0;
}
}
return 1;
}
模範解答
模範解答を見る
int IsClear(Board* board)
{
for (int i = 0; i < BOARD_WIDTH * BOARD_HEIGHT; i++)
{
if (board->tile[i] != i + 1)
{
return 0;
}
}
return 1;
}
2.関数が増えてきたので、プロトタイプ宣言を使おう!
C言語では、基本的に上から順番にプログラムを読んでいきます。
例えば、先に関数を作っておけば、
void Test(void)
{
}
int main(void)
{
Test();
}
main()を読む時点で、コンパイラはすでにTest()を知っているので呼び出せます。
でも、順番を逆にすると、
int main(void)
{
Test();
}
void Test(void)
{
}
main()を読んでいる時点では、まだTest()という関数を知りません。
そこで使うのがプロトタイプ宣言です。
void Test(void);
と先に書いておけば、その時点でコンパイラは、
Test()という関数がある
と分かります。
すると、関数本体を後ろに書いても呼び出せるようになります。
void Test(void); // プロトタイプ宣言
int main(void)
{
Test();
}
void Test(void)
{
}
つまり、
- 関数は、書いた順番に呼べるようになる
- その時点で知らない関数は呼べない
- プロトタイプ宣言しておけば、その時点で知っていることになる
- だから、関数の定義はあとに書いてもよくなる
ということです。
スライドパズルでも、ここまでに作った関数を先に宣言しておこう!
void InitBoard(Board* board);
void PrintBoard(Board* board);
Position SearchTile(Board* board, int number);
int CanMoveTile(Board* board, int number);
void MoveTile(Board* board, int number);
int IsClear(Board* board);
これで、main()を先に書いて、そのあとに各関数の本体を書けます。
今までmain()より上に書いていたInitBoard()やPrintBoard()などの関数本体は、main()の下へ移動しておこう!
ソースコード全体は、
#define
↓
#include
↓
構造体
↓
プロトタイプ宣言
↓
main()
↓
各関数の定義
という順番で整理できます。
3.ゲーム全体の流れを作ろう
ここまでに作った関数を並べると、
InitBoard() 盤面を初期化
PrintBoard() 盤面を表示
MoveTile() タイルを移動
IsClear() クリア判定
があります。
それでは、この流れをゲームループにしてみよう!
盤面を初期化する
↓
盤面を表示する
↓
動かすタイルを入力する
↓
タイルを動かす
↓
クリアしたか調べる
↓
まだなら繰り返す
4.main()を完成させよう
numberには、scanf()で入力した「動かしたいタイル番号」を入れます。
どの関数をどこで呼び出せばよいか考えて、main()を完成させよう!
int main(void)
{
Board board;
________________________________;
while (1)
{
int number;
________________________________;
printf("動かすタイル番号 > ");
scanf("%d", &number);
________________________________;
if (______________________________)
{
break;
}
}
________________________________;
printf("CLEAR!\n");
return 0;
}
模範解答
模範解答を見る
int main(void)
{
Board board;
InitBoard(&board);
while (1)
{
int number;
PrintBoard(&board);
printf("動かすタイル番号 > ");
scanf("%d", &number);
MoveTile(&board, number);
if (IsClear(&board))
{
break;
}
}
PrintBoard(&board);
printf("CLEAR!\n");
return 0;
}
これでゲームループは完成しました。
ただし、今のままではInitBoard()した直後から完成状態です。
最後に、ゲーム開始時の盤面を崩して問題を作ります。