続いては、前回、前々回のプログラムを振り返って、関数に分割してみましょう。
迷路の自動生成とダブルポインタを使った関数を作ります。
いつも通り、大まかな流れから考えていきます。
1.迷路のサイズ決定 ↓ 2.領域の確保 ↓ 3.迷路の初期化(外周のみ) ↓ 4.迷路の自動生成 ↓ 5.迷路の表示 ↓ 6.領域の解放 |
まずは、定数とmain関数を作ります。
※これまでと同じく関数ごとに作っていき、main関数のみ更新します。
※プロトタイプ宣言などは、皆さんで追加してください。
<sample program 171-01>
#include <stdio.h> #include <stdlib.h> #include <time.h> #define DIRECTION 4 enum { FLOOR, WALL, }; enum { UP, RIGHT, DOWN, LEFT, }; int main(void) { int row; int col; int *pMaze; srand((unsigned int)time(NULL)); return 0; } |
1.迷路のサイズ決定
関数名 DecideMazeSize 戻り値 なし 引 数 縦方向を格納する変数のアドレス 横方向を格納する変数のアドレス 機 能 迷路の縦横サイズを決定する |
void DecideMazeSize(int *pRow, int *pCol) { *pRow = 7 + (rand() % 5) * 2; *pCol = 7 + (rand() % 5) * 2; } |
単純に迷路のサイズを決定するだけの関数です。
短いプログラムですが、機能ごとに関数分けした方が良いと思います。
<sample program 171-02>
int main(void)
{
int row;
int col;
int *pMaze;
srand((unsigned int)time(NULL));
DecideMazeSize(&row, &col);
return 0;
}
|
2.領域の確保
関数名 AllocateMazeArea 戻り値 成功 1、失敗 0 引 数 迷路用領域を格納するポインタのアドレス 縦方向の要素数、横方向の要素数 機 能 迷路用の領域(1次元配列)を確保する |
int AllocateMazeArea(int **ppMaze, const int size) { *ppMaze = (int*)malloc(sizeof(int) * size); if (!*ppMaze) { return 0; } return 1; } |
前回やったダブルポインタを使った関数です。
<sample program 171-03>
int main(void)
{
int row;
int col;
int *pMaze;
srand((unsigned int)time(NULL));
DecideMazeSize(&row, &col);
if (!AllocateMazeArea(&pMaze, row * col)) {
return 1;
}
return 0;
}
|
3.迷路の初期化(外周のみ)
関数名 InitializeMaze 戻り値 なし 引 数 迷路用領域の先頭アドレス 縦方向の要素数、横方向の要素数 機 能 迷路の床と外周を設定する |
void InitializeMaze(int* const pMaze, const int row, const int col) { int i; int j; for (i = 1; i < row - 1; i++) { for (j = 1; j < col - 1; j++) { pMaze[i * col + j] = FLOOR; } } for (i = 0; i < row; i++) { pMaze[i * col] = WALL; pMaze[i * col + (col - 1)] = WALL; } for (j = 1; j < col - 1; j++) { pMaze[col] = WALL; pMaze[(row - 1) * col + j] = WALL; } } |
今回も「柱」は自動生成の時に作ります。
<sample program 171-04>
int main(void)
{
int row;
int col;
int *pMaze;
srand((unsigned int)time(NULL));
DecideMazeSize(&row, &col);
if (!AllocateMazeArea(&pMaze, row * col)) {
return 1;
}
InitializeMaze(pMaze, row, col);
return 0;
}
|
4.迷路の自動生成
関数名 GenerateMaze 戻り値 なし 引 数 迷路用領域の先頭アドレス 縦方向の要素数、横方向の要素数 機 能 迷路の「柱」と乱数を使って壁を設定する |
void GenerateMaze(int* const pMaze, const int row, const int col) { int i; int j; for (i = 2; i < row - 2; i += 2) { for (j = 2; j < col - 2; j += 2) { pMaze[i * col + j] = WALL; switch (rand() % DIRECTION) { case UP: pMaze[(i - 1) * col + j] = WALL; break; case RIGHT: pMaze[i * col + (j + 1)] = WALL; break; case DOWN: pMaze[(i + 1) * col + j] = WALL; break; case LEFT: pMaze[i * col + (j - 1)] = WALL; break; } } } } |
特に変わったところはありません。
<sample program 171-05>
int main(void)
{
int row;
int col;
int *pMaze;
srand((unsigned int)time(NULL));
DecideMazeSize(&row, &col);
if (!AllocateMazeArea(&pMaze, row * col)) {
return 1;
}
InitializeMaze(pMaze, row, col);
GenerateMaze(pMaze, row, col);
return 0;
}
|
5.迷路の表示
関数名 ShowMaze 戻り値 なし 引 数 迷路用領域の先頭アドレス 縦方向の要素数、横方向の要素数 機 能 迷路を表示する |
void ShowMaze(const int* const pMaze, const int row, const int col) { int i; int j; for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { if (pMaze[i * col + j] == FLOOR) { printf("□"); } else { printf("■"); } } printf("\n"); } } |
スタート、ゴールは今回は設定しません。
<sample program 171-06>
int main(void)
{
int row;
int col;
int *pMaze;
srand((unsigned int)time(NULL));
DecideMazeSize(&row, &col);
if (!AllocateMazeArea(&pMaze, row * col)) {
return 1;
}
InitializeMaze(pMaze, row, col);
GenerateMaze(pMaze, row, col);
ShowMaze(pMaze, row, col);
return 0;
}
|
6.領域の解放
関数名 ReleaseMazeArea 戻り値 なし 引 数 迷路用領域の先頭アドレス 機 能 迷路用領域を解放する |
void ReleaseMazeArea(int *pMaze) { free(pMaze); pMaze = NULL; } |
領域の解放(リリース)とダングリングポインタ対応をします。
<sample program 171-06>
int main(void)
{
int row;
int col;
int *pMaze;
srand((unsigned int)time(NULL));
DecideMazeSize(&row, &col);
if (!AllocateMazeArea(&pMaze, row * col)) {
return 1;
}
InitializeMaze(pMaze, row, col);
GenerateMaze(pMaze, row, col);
ShowMaze(pMaze, row, col);
ReleaseMazeArea(pMaze);
return 0;
}
|
<sample program 171-07>
#include <stdio.h> #include <stdlib.h> #include <time.h> #define DIRECTION 4 enum { FLOOR, WALL, }; enum { UP, RIGHT, DOWN, LEFT, }; void DecideMazeSize(int *pRow, int *pCol); int AllocateMazeArea(int **ppMaze, const int size); void InitializeMaze(int* const pMaze, const int row, const int col); void GenerateMaze(int* const pMaze, const int row, const int col); void ShowMaze(const int* const pMaze, const int row, const int col); void ReleaseMazeArea(int *pMaze); int main(void) { int row; int col; int *pMaze; srand((unsigned int)time(NULL)); DecideMazeSize(&row, &col); if (!AllocateMazeArea(&pMaze, row * col)) { return 1; } InitializeMaze(pMaze, row, col); GenerateMaze(pMaze, row, col); ShowMaze(pMaze, row, col); ReleaseMazeArea(pMaze); return 0; } void DecideMazeSize(int *pRow, int *pCol) { *pRow = 7 + (rand() % 5) * 2; *pCol = 7 + (rand() % 5) * 2; } int AllocateMazeArea(int **ppMaze, const int size) { *ppMaze = (int*)malloc(sizeof(int) * size); if (!*ppMaze) { return 0; } return 1; } void InitializeMaze(int* const pMaze, const int row, const int col) { int i; int j; for (i = 1; i < row - 1; i++) { for (j = 1; j < col - 1; j++) { pMaze[i * col + j] = FLOOR; } } for (i = 0; i < row; i++) { pMaze[i * col] = WALL; pMaze[i * col + (col - 1)] = WALL; } for (j = 1; j < col - 1; j++) { pMaze[col] = WALL; pMaze[(row - 1) * col + j] = WALL; } } void GenerateMaze(int* const pMaze, const int row, const int col) { int i; int j; for (i = 2; i < row - 2; i += 2) { for (j = 2; j < col - 2; j += 2) { pMaze[i * col + j] = WALL; switch (rand() % DIRECTION) { case UP: pMaze[(i - 1) * col + j] = WALL; break; case RIGHT: pMaze[i * col + (j + 1)] = WALL; break; case DOWN: pMaze[(i + 1) * col + j] = WALL; break; case LEFT: pMaze[i * col + (j - 1)] = WALL; break; } } } } void ShowMaze(const int* const pMaze, const int row, const int col) { int i; int j; for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { if (pMaze[i * col + j] == FLOOR) { printf("□"); } else { printf("■"); } } printf("\n"); } } void ReleaseMazeArea(int *pMaze) { free(pMaze); pMaze = NULL; } |
<実行結果>
■■■■■■■■■■■■■ ■□□□□□□□■□■□■ ■□■□■■■■■□■□■ ■□■□■□□□□□■□■ ■□■□■□■■■■■□■ ■□■□□□■□■□□□■ ■■■□■■■□■■■□■ ■□□□□□□□□□□□■ ■■■■■■■■■■■■■ 続行するには何かキーを押してください・・・