再帰的な関数を使った処理
再帰関数・・・関数の中で、同じ関数を実行することのある関数
作成時のルール
①引数などのデータを使い、同じ関数を
実行するかどうか決める。
②実行しない場合、returnで処理を終了させる。
例、※Win32 Console Applicationで作成
#include <stdio.h>
void func1(int)
void main()
{
func1(3);
printf(“\n”);
func1(5);
printf(“\n”);
}
void func1(int Num)
{
if(Num > 0) //もし、引数が0より大きかったら、
{
printf(“Num = %d\n”,Num); //引数を表示
func(Num-1); //今の引数より1少ない数で、同じ関数を実行
}
return; //0以下だったら、return;
}
func1(3)
・Num=3、と表示
・Num>0なので、func1(3-1)を実行
↑|
|∟→func1(2)
| ・Num=2、と表示
∟――・Num>0なので、func1(2-1)を実行
↑ |
| ∟→func1(1)
| ・Num=1
∟―――・Num>0なので、func1(1-1)を実行
↑ |
| ∟→func1(0)
∟―――・Num>0ではないので、return;
●ゲームでの使用例、シミュレーションゲームの移動
選択されたキャラが移動可能な範囲を
先に表示する。
移動可能な範囲を扱う配列を作る。
キャラのいる場所が3
1歩動くごとに2,1,0と減っていく。
(0でない場所は、移動可能)
このような配列を作るのに、再帰関数を用いる。
関数の機能
キャラの場所や、移動量(どれくらい動けるか)などのデータを元に、
移動可能な範囲を表す配列を作る。
[2][2]の場所に移動量3のキャラ
関数内の処理
・配列内の、指定された要素に、
キャラの移動量の数値を代入する。
・代入ができた場合、代入した要素の
上下左右のマスを、
移動量-1、で、同じように処理する。
(1マス動くたびに、移動量は1ずつ下に下がっていく)
・移動量が0になったら、そこで終了(return)。
・指定したマスに、他の数値が入っていた場合、
大きい方を使用。
・配列から、はみ出ないようにする。
関数の例、
※マップチップの縦の枚数・・・MapH
横の枚数・・・MapW で、マクロ定義されているものとして説明
※int MapMoveData[MapH][MapW];
//移動可能な範囲を表す配列。マップと同じ大きさ。
を外部変数として宣言しておく。
void Move(int x,int y,int MoveNum)
配列のどの要素を調べるか 移動量
{
//移動量が残っているか判定
if(MoveNum <= 0) return; //移動量が0以下なら、returnする。
//配列からはみ出ていないか判定
if(x >= MapW || y >= MapH || x < 0 || y < 0)
return; //x,yが配列の要素の範囲外だったら、return
//すでに、より大きな値が入っていないか判定(より効率の良いルートがあるかどうか)
if(MapMoveData[y][x] > MoveNum)
return;
//移動量を、配列に代入
MapMoveData[y][x] = MoveNum;
//移動量を1減らして、現在のマスの左右上下を、同じように調べる
Move(x,y-1,MoveNum-1); //上
Move(x,y+1,MoveNum-1); //下
Move(x-1,y,MoveNum-1); //左
Move(x+1,y,MoveNum-1); //右
return;
}
実行例
※Move関数のプロトタイプ宣言、
MapW、MapHのマクロ定義、
MapMoveData[][]の宣言は、各自で行うこと。
#include <stdio.h>
・
・
・
void main()
{
int i,j;
Zeromory(&MapMoveData[0][0],sizeof(itn)*MapH*MapW);
Move(2,2,3); //x=2、y=2の場所に、
移動量3のキャラがいるものとして、配列に値を設定
for(i=0;i<MapH;i++) //配列を表示
{
for(j=0;j<MapW;j++)
{
printf(“%d”,MapMoveData[i][j]);
}
printf(“\n”);
}
}