関数宣言(再帰有り時)の書式について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ろん
記事: 18
登録日時: 8年前

関数宣言(再帰有り時)の書式について

#1

投稿記事 by ろん » 8年前

初めて質問させて頂きます。
OS:win7(64bit),Vc++2008 Dxライブラリ環境にて作成した物ですが、map_walk()にて再帰処理されずにそのまま抜けてしまう状態です。
戻り値の宣言(voidでの宣言)がおかしいのかな?と推察したのですがmap_walk( x,y, hosuu);と宣言するとビジー状態になったり
int map_walk(int,int,int);等いくつか試したのですがコンパイルが通らなかったりと意図した通りに動きません。

9/6からC++の勉強を始め、まだ日も浅く書式や文法が分からないので、引数と戻り値がある時の宣言の仕方をお教えては頂けないでしょうか?

意図:波状走査開始地点(x,y)から障害物・壁(99)を避けて通った歩数をmw[12][12]に収める

コード:

#include "DxLib.h"
#include <math.h>

//速度調整
int g_lastcalltime = 0;
float g_frametime = 0;
//プロトタイプ宣言
void Getpointer();
void Map_Line_Print();
void Map_enemy_move();
void Map_myship_move();
void m_map_sea();
void m_map_sea2();
void map_walk(int, int, int);

int timetime=0;

int Sx , Sy , Cb ;
int pointerx=0;
int pointery=0;

//マップ処理
//マップデータ(y-xに注意)
int mapgridx = 12;
int mapgridy = 12;
int mappoint[12][12]={
	{1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1},
	{1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1},//2列目
	{1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0},
	{1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0},
	{1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0},
	{1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1},//6
	{0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1},
	{0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1},//8
	{0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1},
	{0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1},//10
	{0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1},
	{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}};

int map_enemyx=1,map_enemyy=0;
//マップサーチ用変数
int i,j,color;
int mw[12][12]={{},{},{},{},{},{},{},{},{},{},{},{}};
int map_enemy_targetx=6, map_enemy_targety=1;
int x=map_enemy_targetx;
int y=map_enemy_targety;

int hosuu=0;
int flag =1;


// プログラムは WinMain から始まります
int WINAPI WinMain( HINSTANCE hI, HINSTANCE hP, LPSTR lpC, int nC){
	ChangeWindowMode(TRUE);
	if( DxLib_Init() == -1 ) return -1;	// エラーが起きたら直ちに終了

	/* メイン処理 */
	
	g_lastcalltime = GetNowCount() & INT_MAX;
	SetDrawScreen(DX_SCREEN_BACK);
	while(ProcessMessage() == 0 ){
		//現在時間を計測
		int curtime = GetNowCount() & INT_MAX;
		int curinterval =
			curtime - g_lastcalltime;
		ClsDrawScreen();
		//1ループにかかった時間(秒数)を求める
		g_frametime = (float)(curinterval) / 1000.0f;
		//メイン処理
	
		Getpointer();
		Map_Line_Print();
		
		m_map_sea();
		m_map_sea2();

		if(flag == 1){
			map_walk(x,y, hosuu);
		}
		/* メインループここまで*/
		ScreenFlip();
	}
	DxLib_End() ;				// DXライブラリ使用の終了処理
	return 0 ;				// ソフトの終了 
}

void Getpointer(){
	int Cr = GetColor( 255 , 255 , 255 );	// 白色の値を取得
	for(i = 0; i < mapgridx+1; ++i){
		for(j = 0; j < mapgridy+1; j++){
			DrawLine( i*32, j*32, Sx, j*32, Cr);
			DrawLine( i*32, j*32, i*32, Sy, Cr);
		}
	}
}
//壁扱いの要素(1)を表示
void Map_Line_Print(){
	int color = GetColor( 255 , 0 , 0 );
	for(int i = 0; i < mapgridx; i++){
		for(int j = 0; j < mapgridy; j++){
			if(mappoint[i][j]==1){
				DrawFormatString( j*32, i*32, color, "壁");
				DrawFormatString( j*32, i*32+16, color, "%d-%d", j,i);
			}
		}
	
	}
}

//初期配列mappoint[][]の要素(1)を要素(99)へ変換
void m_map_sea(){
	color = GetColor( 255 , 0 , 0 );
	for(i = 0; i < mapgridx; i++){
		for(j = 0; j < mapgridy; j++){
			if(mappoint[i][j]==1){
				mw[i][j]=99;
				}
		}
	}
}
//配列mw[][]の内容表示
void m_map_sea2(){
	color = GetColor(  0, 255 , 0 );
	for(i = 0; i < mapgridx; i++){
		for(j = 0; j < mapgridy; j++){
				DrawFormatString( j*32+16, i*32, color, "%d", mw[i][j]);			
		}
	}
}
void map_walk( int, int, int){
	color = GetColor( 0 , 0, 200 );
	DrawFormatString( x*32+16, y*32, color, "%d", hosuu);
	flag=0;
	hosuu=hosuu+1;
	if( 0 < y || mw[y-1][x] !=99){
		if( mw[y-1][x] == 0 || mw[y-1][x] > hosuu){

			mw[y-1][x] = hosuu;
			map_walk( x, y-1, hosuu+1);
			hosuu=hosuu-1;
		}
	}
	if( 11 < y || mw[y+1][x] !=99){
		if( mw[y+1][x] == 0 || mw[y+1][x] > hosuu){
			mw[y+1][x] = hosuu;
			map_walk( x,y+1, hosuu+1);
			hosuu=hosuu-1;
		}
	}
	if( 0 > x || mw[y][x-1] !=99){
		if( mw[y][x-1] == 0 || mw[y][x-1] > hosuu){
			mw[y][x-1]= hosuu;
			map_walk( x-1,y, hosuu+1);
			hosuu=hosuu-1;
		}
	}
	if( 11 > x || mw[y][x+1] !=99){
		if( mw[y][x+1] == 0 || mw[y][x+1] > hosuu){
			mw[y][x+1] = hosuu;
			map_walk( x+1, y, hosuu+1);
			hosuu=hosuu-1;
		}
	}

}

ろん
記事: 18
登録日時: 8年前

Re: 関数宣言(再帰有り時)の書式について

#2

投稿記事 by ろん » 8年前

投稿直後に戻り値でぐぐったら一部、書式については自己解決しました。

プログラムは走るものの右上方向にしか探査してないようで、これからさらに改善する予定です。

コード:

int map_walk( int x, int y, int hosuu){
	color = GetColor( 255 , 0 , 0 );
	DrawFormatString( x*32+16, y*32, color, "%d", hosuu);
	if( 0 < y && mw[y-1][x] !=99){
		if( mw[y-1][x] == 0 || mw[y-1][x] > hosuu){

			mw[y-1][x] = hosuu;
			map_walk( x, y-1, hosuu+1);
		}
	}
	if( 11 < y && mw[y+1][x] !=99){
		if( mw[y+1][x] == 0 || mw[y+1][x] > hosuu){
			mw[y+1][x] = hosuu;
			map_walk( x,y+1, hosuu+1);
		}
	}
	if( 0 > x && mw[y][x-1] !=99){
		if( mw[y][x-1] == 0 || mw[y][x-1] > hosuu){
			mw[y][x-1]= hosuu;
			map_walk( x-1,y, hosuu+1);
		}
	}
	if( 11 > x && mw[y][x+1] !=99){
		if( mw[y][x+1] == 0 || mw[y][x+1] > hosuu){
			mw[y][x+1] = hosuu;
			map_walk( x+1, y, hosuu+1);
		}
	}
	return x, y, hosuu;
}

アバター
パコネコ
記事: 139
登録日時: 9年前
住所: 大阪

Re: 関数宣言(再帰有り時)の書式について

#3

投稿記事 by パコネコ » 8年前

コード:

//宣言部
int map_walp(int,int,int);

コード:

//関数実態
int map_walp(int a,int b,int c){
     //省略
}
と言う風に創っていただければ良いと思います。
戻り値が必要なときは、関数の前に「int」と書けば良いです。
(整数が戻り値ならですが)
ただし、戻り値は必ず必要になります。
よって、return 0;を書いておきましょう。
(0である必要はありません)

宣言部を

コード:

//宣言部
int map_walp(int a,int b,int c);
と書いても問題ありません。

/////////////
追記
return はほんとにそれで良いんですか?
期待道理の値ですか?
ニャン!!\(゜ロ\)(/ロ゜)/

アバター
パコネコ
記事: 139
登録日時: 9年前
住所: 大阪

Re: 関数宣言(再帰有り時)の書式について

#4

投稿記事 by パコネコ » 8年前

すいません
追記です。

コード:

    if( 11 < y && mw[y+1][x] !=99){
        if( mw[y+1][x] == 0 || mw[y+1][x] > hosuu){
            mw[y+1][x] = hosuu;
            map_walk( x,y+1, hosuu+1);
        }
    }
    if( 0 > x && mw[y][x-1] !=99){
        if( mw[y][x-1] == 0 || mw[y][x-1] > hosuu){
            mw[y][x-1]= hosuu;
            map_walk( x-1,y, hosuu+1);
        }
    }
コレはまずいです。
まず。
「11<y」のとき必ずmv[12][12]の範囲である0~11を超えてしまいます。
ほかもです。
少し見直してみた方が良いかもしれません。
ニャン!!\(゜ロ\)(/ロ゜)/

ろん
記事: 18
登録日時: 8年前

Re: 関数宣言(再帰有り時)の書式について

#5

投稿記事 by ろん » 8年前

レスありがとうございます。
下のように修正をかけた所、意図した通りに動きました。
ですが12×12すべてのデータを0にして処理したところ、いきなり99~102という数字が出てきます。
これは、再帰に寄る処理が重なりすぎての事なのでしょうか?

コード:

int map_walk( int a, int b, int c){
	color = GetColor( 255 , 0 , 0 );	
	if( 0 != b ){
		if( mw[b-1][a] !=99){
			if( mw[b-1][a] == 0 || mw[b-1][a] >= c){
				mw[b][a] = c;
				map_walk( a, b-1, c+1);
			}
		}
	}
	if( a != 0 ){
		if( mw[b][a-1] !=99){
			if( mw[b][a-1] == 0 || mw[b][a-1] >= c){
				mw[b][a]= c;
				map_walk( a-1,b, c+1);
			}
		}
	}
	if( 11 != b){
		if( mw[b+1][a] !=99){
			if( mw[b+1][a] == 0 || mw[b+1][a] >= c){
				mw[b][a] = c;
				map_walk( a,b+1, c+1);
			}
		}
	}
	if( 11 != a){
		if( mw[b][a+1] !=99){
			if( mw[b][a+1] == 0 || mw[b][a+1] >= c){
				mw[b][a] = c;
				map_walk( a+1, b, c+1);
			}
		}
	}
	return 0;
}

box
記事: 1745
登録日時: 9年前

Re: 関数宣言(再帰有り時)の書式について

#6

投稿記事 by box » 8年前

再帰呼び出しであろうがなかろうが、
引数として何を渡して(あるいは何も渡さないで)
戻り値として何を返すか(あるいは何も返さないか)
がちゃんと設計できていれば何も迷うことはないと思います。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

アバター
パコネコ
記事: 139
登録日時: 9年前
住所: 大阪

Re: 関数宣言(再帰有り時)の書式について

#7

投稿記事 by パコネコ » 8年前

復帰はプログラムを読むのが厄介なので、中身の理解はしませんが、
(式とか理論知ってたら簡単なんですが...)
とりあえず、前よりいい気はしますが、それでも

コード:

    if( a != 0 ){
は、あまりよくありません。
今回なぜaは0ではいけないのでしょうか。
それはa-1の値を配列の添え字に使うからですよね。
つまり0<=a-1<12でなければなりません。
0<a<13となります。
つまり値は-になる可能性があるのでそれも考慮すべきではないでしょうか?
逆に12を超える可能性も考慮すべきではないでしょうか?
*(ミスです。11を超える可能性もですね)
ニャン!!\(゜ロ\)(/ロ゜)/

ろん
記事: 18
登録日時: 8年前

Re: 関数宣言(再帰有り時)の書式について

#8

投稿記事 by ろん » 8年前

掲示板の書き込み方が間違えていたようで昨日、解決とお礼書いたつもりでいました、返事遅れてすみません。
98~100という数字は再帰のステップ数が軽く100を超える場合があった為と判明し、そのへんを書き換えた所全て無事解決しました。
今は、目標地点から求めた最大歩数を元に降順で歩かせるアルゴリズム考えてます。
また分からない所があったら質問しに来ますので宜しくお願いします。

閉鎖

“C言語何でも質問掲示板” へ戻る