続いては、前回、前々回のプログラムを振り返って、関数に分割してみましょう。
迷路の自動生成とダブルポインタを使った関数を作ります。
いつも通り、大まかな流れから考えていきます。
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;
}
|
<実行結果>
■■■■■■■■■■■■■ ■□□□□□□□■□■□■ ■□■□■■■■■□■□■ ■□■□■□□□□□■□■ ■□■□■□■■■■■□■ ■□■□□□■□■□□□■ ■■■□■■■□■■■□■ ■□□□□□□□□□□□■ ■■■■■■■■■■■■■ 続行するには何かキーを押してください・・・