関数を立てたらbreak文でビルドが止まった

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

関数を立てたらbreak文でビルドが止まった

#1

投稿記事 by dast » 13年前

こんにちは。プログラミングの勉強をしている者です。
メニュー表示→ゲームスタートを選ぶとゲーム画面に移行→ゲーム画面で左右キーを押すと自機が動きAボタンを押すとショットを打つ というプログラムを作ったのですが、少々長いのでメニューでの操作の計算を関数化しようと次のように変えたらビルドできなくなりました。

変更前

コード:

#include "DxLib.h"

#define PI 3.141592654

int Key[256]; // キーが押されているフレーム数を格納する

// キーの入力状態を更新する
int gpUpdateKey(){
        char tmpKey[256]; // 現在のキーの入力状態を格納する
        GetHitKeyStateAll( tmpKey ); // 全てのキーの入力状態を得る
        for( int i=0; i<256; i++ ){ 
                if( tmpKey[i] != 0 ){ // i番のキーコードに対応するキーが押されていたら
                        Key[i]++;     // 加算
                } else {              // 押されていなければ
                        Key[i] = 0;   // 0にする
                }
        }
        return 0;
}

//変数の用意
//システム
int mode;//モード切り替え用
//タイトル画面
int SelectNum;//メニュー選択用
//ゲーム画面
int ziki_img[16];//自機画像格納用
int smode;//自機攻撃用
int Back1;//背景画像格納用(タイトル画面共通)
int Waku1;//ゲーム枠画像格納用
int Waku2;//パラメーター枠画像格納用
int ztama;//自機弾画像格納用
int ztamakage;//自機弾影画像格納用
int gcnt;//操作許可判定用

//構造体の用意
// タイトル画面
// メニュー用構造体
typedef struct{
	int x, y;       // 座標格納用変数
	char name[128]; // 項目名格納用変数
} MenuElement_t ;
MenuElement_t MenuElement[4]={// メニュー項目要素
	{ 260, 285, "ゲームスタート" }, // タグの中身の順番で格納される。xにが、yにが、nameに"ゲームスタート"が
	{ 280, 335, "おまけ" },
	{ 280, 385, "コンフィグ" },
	{ 280, 435, "ゲーム終了" },
};
// ゲーム画面
// 自機データ構造体
typedef struct{
	int x, y;       // 座標格納用変数
	int maxx;       // 移動範囲右端
	int minx;       // 移動範囲左端
	int cnt;        // 画像ループ用変数
	int no;         // 画像ループ用変数
	int z;          // 残機数
	int b;          // 残りボム数
} ziki_t ;
ziki_t ziki={200,444,609,30,0,0,3,3};// 自機データ
//自機弾用構造体
typedef struct{
	int x, y;       // 自機弾座標
	int flag;       // 発射済みかどうか
} shot_t ;
shot_t tama[10]={
	{200,444,0},{200,444,0},{200,444,0},{200,444,0},{200,444,0},{200,444,0},{200,444,0},{200,444,0},{200,444,0},{200,444,0}
};

//関数の用意
//ゲーム画面
//自機操作関数
void Zmove(){
	gcnt++;
	ziki.no=(ziki.cnt%48)/12;
	if(gcnt>=48){
		ziki.cnt++;
	}
	if(Key[KEY_INPUT_LEFT]>=1 && ziki.x>=ziki.minx && Key[KEY_INPUT_RIGHT]==0 && smode!=1 && ziki.cnt>0){    //右キーが押されている間
		ziki.no += 8;
		ziki.x -=2;
	}
	if(Key[KEY_INPUT_RIGHT]>=1 && ziki.x<=ziki.maxx && Key[KEY_INPUT_LEFT]==0 && smode!=1 && ziki.cnt>0){
		ziki.no += 4;
		ziki.x +=2;
	}
	if(Key[KEY_INPUT_A]==1 && ziki.cnt>0 && smode!=1){
		smode=1;
		ziki.cnt=0;
	}
	if(smode==1){
		ziki.no=(ziki.cnt%16)/4;
		ziki.no += 12;
		if(ziki.cnt==8){//
		}
		if(ziki.cnt==15){
			smode=0;
		}
	}
}
//自機弾計算関数
void zikitama(){
	int i;
	for(i=0;i<10;i++){
		if(tama[i].flag==0){
			tama[i].x=ziki.x;
		}
	}
	if(smode==1 && ziki.cnt==8){
		for(i=0;i<10;i++){
			if(tama[i].flag==0){
				tama[i].flag=1;
				break;
			}
		}
	}
	for(i=0;i<10;i++){
		if(tama[i].flag==1){
			tama[i].y-=8;
			if(tama[i].y<79){
				tama[i].y=ziki.y-28;
				tama[i].flag=0;
			}
		}
	}
}

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
        ChangeWindowMode(TRUE),DxLib_Init(),SetDrawScreen( DX_SCREEN_BACK );
		//ウィンドウモードに設定,DXライブラリ初期化処理,描画先を裏画面に設定

//変数
		//変数への数値の代入
		int i;//ループ用
		mode = 0;
		SelectNum = 0;                   // 現在の選択番号
		ziki.x = (ziki.maxx+ziki.minx)/2;// 自機初期位置
		ziki.no =(ziki.cnt%48)/12;            // 画像ループ用変数設定
		smode = 0;
		gcnt = 0;

		//変数への画像の格納
		Back1 = LoadGraph("画像/システム/神社周辺.png");
		Waku1 = LoadGraph("画像/システム/枠.png");
		Waku2 = LoadGraph("画像/システム/パラメータ表示部分.png");
		LoadDivGraph("画像/キャラ/自機.png",16,4,4,66,66,ziki_img);
		ztama = LoadGraph("画像/弾/自機弾.png");
		ztamakage = LoadGraph("画像/弾/自機弾影.png");

//構造体
		//shot tama[10]の設定
		for(i=0;i<10;i++){
			tama[i].x=ziki.x;
			tama[i].y=ziki.y-28;
			tama[i].flag=0;
		}

		//ループ部分
        while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 & gpUpdateKey()==0 ){//while(裏画面の物を表画面に写す,メッセージ処理,画面を消去,キーの状態の更新)
			if(mode==0){
				mode=10;
			}
//タイトル画面
			else if(mode==10){
				                                     //計算フェーズ
				
				                                      //下方向への移動
				if( Key[ KEY_INPUT_DOWN ] == 1 ){      // 下キーが押された瞬間だけ処理
					SelectNum = ( SelectNum + 1 ) % 4; // 現在の選択項目を一つ下にずらす(ループする)
					
					for( int i=0; i<4; i++ ){          // メニュー項目数である個ループ処理
						if( i == SelectNum ){          // 今処理しているのが、選択番号と同じ要素なら
							MenuElement[i].x = 260;     // 座標をにする
						} else {                       // 今処理しているのが、選択番号以外なら
							MenuElement[i].x = 280;    // 座標をにする
						}
					}
				}
				                                      //上方向への移動
				if( Key[ KEY_INPUT_UP ] == 1 ){        // 上キーが押された瞬間だけ処理
					SelectNum = ( SelectNum + 3 ) % 4; // 現在の選択項目を一つ上にずらす(逆ループする)
					for( int i=0; i<4; i++ ){          // メニュー項目数である個ループ処理
						if( i == SelectNum ){          // 今処理しているのが、選択番号と同じ要素なら
							MenuElement[i].x = 260;     // 座標をにする
						} else {                       // 今処理しているのが、選択番号以外なら
							MenuElement[i].x = 280;    // 座標をにする
						}
					}
				}
				if( Key[ KEY_INPUT_A] == 1 ){
					if(SelectNum == 0){
						mode=20;
					}
					if(SelectNum == 3){
						break;
					}
				}
				                                     //描画フェーズ
				for( int i=0; i<4; i++ ){ // メニュー項目を描画
					DrawFormatString( MenuElement[i].x, MenuElement[i].y, GetColor(255,255,255), MenuElement[i].name );
				}

			}
//ゲーム画面
            else if(mode==20){
                                                     //計算フェーズ
                                                                //自機の設定
				Zmove();
				zikitama();

                                                     //描画フェーズ
                DrawGraph(20,80,Back1,TRUE);
				for(i=0;i<10;i++){
					if(tama[i].flag==1){
						DrawRotaGraph(tama[i].x,tama[i].y,1.0,gcnt*PI/5,ztama,TRUE);
						SetDrawBlendMode(DX_BLENDMODE_ALPHA, 128);
						DrawRotaGraph(tama[i].x,tama[i].y,1.0,0.0,ztamakage,TRUE);
						SetDrawBlendMode(DX_BLENDMODE_NOBLEND, 0);
					}
				}
                DrawRotaGraph(ziki.x,444,1.0,0.0,ziki_img[ziki.no],TRUE);
				DrawGraph(0,0,Waku1,TRUE);
				DrawGraph(20,15,Waku2,TRUE);
            }
 
    }
 
        DxLib_End();    // DXライブラリ終了処理
        return 0;
} 


変更後

コード:

#include "DxLib.h"

#define PI 3.141592654

int Key[256]; // キーが押されているフレーム数を格納する

// キーの入力状態を更新する
int gpUpdateKey(){
        char tmpKey[256]; // 現在のキーの入力状態を格納する
        GetHitKeyStateAll( tmpKey ); // 全てのキーの入力状態を得る
        for( int i=0; i<256; i++ ){ 
                if( tmpKey[i] != 0 ){ // i番のキーコードに対応するキーが押されていたら
                        Key[i]++;     // 加算
                } else {              // 押されていなければ
                        Key[i] = 0;   // 0にする
                }
        }
        return 0;
}

//変数の用意
//システム
int mode;//モード切り替え用
//タイトル画面
int SelectNum;//メニュー選択用
//ゲーム画面
int ziki_img[16];//自機画像格納用
int smode;//自機攻撃用
int Back1;//背景画像格納用(タイトル画面共通)
int Waku1;//ゲーム枠画像格納用
int Waku2;//パラメーター枠画像格納用
int ztama;//自機弾画像格納用
int ztamakage;//自機弾影画像格納用
int gcnt;//操作許可判定用

//構造体の用意
// タイトル画面
// メニュー用構造体
typedef struct{
	int x, y;       // 座標格納用変数
	char name[128]; // 項目名格納用変数
} MenuElement_t ;
MenuElement_t MenuElement[4]={// メニュー項目要素
	{ 260, 285, "ゲームスタート" }, // タグの中身の順番で格納される。xにが、yにが、nameに"ゲームスタート"が
	{ 280, 335, "おまけ" },
	{ 280, 385, "コンフィグ" },
	{ 280, 435, "ゲーム終了" },
};
// ゲーム画面
// 自機データ構造体
typedef struct{
	int x, y;       // 座標格納用変数
	int maxx;       // 移動範囲右端
	int minx;       // 移動範囲左端
	int cnt;        // 画像ループ用変数
	int no;         // 画像ループ用変数
	int z;          // 残機数
	int b;          // 残りボム数
} ziki_t ;
ziki_t ziki={200,444,609,30,0,0,3,3};// 自機データ
//自機弾用構造体
typedef struct{
	int x, y;       // 自機弾座標
	int flag;       // 発射済みかどうか
} shot_t ;
shot_t tama[10]={
	{200,444,0},{200,444,0},{200,444,0},{200,444,0},{200,444,0},{200,444,0},{200,444,0},{200,444,0},{200,444,0},{200,444,0}
};

//関数の用意
//タイトル画面
//タイトルメニュー操作
void Tmove(){
	//下方向への移動
	if( Key[ KEY_INPUT_DOWN ] == 1 ){      // 下キーが押された瞬間だけ処理
		SelectNum = ( SelectNum + 1 ) % 4; // 現在の選択項目を一つ下にずらす(ループする)
		for( int i=0; i<4; i++ ){          // メニュー項目数である個ループ処理
			if( i == SelectNum ){          // 今処理しているのが、選択番号と同じ要素なら
				MenuElement[i].x = 260;     // 座標をにする
			} else {// 今処理しているのが、選択番号以外なら
				MenuElement[i].x = 280;    // 座標をにする
			}
		}
	}
	//上方向への移動
	if( Key[ KEY_INPUT_UP ] == 1 ){        // 上キーが押された瞬間だけ処理
		SelectNum = ( SelectNum + 3 ) % 4; // 現在の選択項目を一つ上にずらす(逆ループする)
		for( int i=0; i<4; i++ ){          // メニュー項目数である個ループ処理
			if( i == SelectNum ){          // 今処理しているのが、選択番号と同じ要素なら
				MenuElement[i].x = 260;     // 座標をにする
			} else {// 今処理しているのが、選択番号以外なら
				MenuElement[i].x = 280;    // 座標をにする
			}
		}
	}
	if( Key[ KEY_INPUT_A] == 1 ){
		if(SelectNum == 0){
			mode=20;
		}
		if(SelectNum == 3){
			break;
		}
	}
}
//ゲーム画面
//自機操作関数
void Zmove(){
	gcnt++;
	ziki.no=(ziki.cnt%48)/12;
	if(gcnt>=48){
		ziki.cnt++;
	}
	if(Key[KEY_INPUT_LEFT]>=1 && ziki.x>=ziki.minx && Key[KEY_INPUT_RIGHT]==0 && smode!=1 && ziki.cnt>0){    //右キーが押されている間
		ziki.no += 8;
		ziki.x -=2;
	}
	if(Key[KEY_INPUT_RIGHT]>=1 && ziki.x<=ziki.maxx && Key[KEY_INPUT_LEFT]==0 && smode!=1 && ziki.cnt>0){
		ziki.no += 4;
		ziki.x +=2;
	}
	if(Key[KEY_INPUT_A]==1 && ziki.cnt>0 && smode!=1){
		smode=1;
		ziki.cnt=0;
	}
	if(smode==1){
		ziki.no=(ziki.cnt%16)/4;
		ziki.no += 12;
		if(ziki.cnt==8){//
		}
		if(ziki.cnt==15){
			smode=0;
		}
	}
}
//自機弾計算関数
void zikitama(){
	int i;
	for(i=0;i<10;i++){
		if(tama[i].flag==0){
			tama[i].x=ziki.x;
		}
	}
	if(smode==1 && ziki.cnt==8){
		for(i=0;i<10;i++){
			if(tama[i].flag==0){
				tama[i].flag=1;
				break;
			}
		}
	}
	for(i=0;i<10;i++){
		if(tama[i].flag==1){
			tama[i].y-=8;
			if(tama[i].y<79){
				tama[i].y=ziki.y-28;
				tama[i].flag=0;
			}
		}
	}
}

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
        ChangeWindowMode(TRUE),DxLib_Init(),SetDrawScreen( DX_SCREEN_BACK );
		//ウィンドウモードに設定,DXライブラリ初期化処理,描画先を裏画面に設定

//変数
		//変数への数値の代入
		int i;//ループ用
		mode = 0;
		SelectNum = 0;                   // 現在の選択番号
		ziki.x = (ziki.maxx+ziki.minx)/2;// 自機初期位置
		ziki.no =(ziki.cnt%48)/12;            // 画像ループ用変数設定
		smode = 0;
		gcnt = 0;

		//変数への画像の格納
		Back1 = LoadGraph("画像/システム/神社周辺.png");
		Waku1 = LoadGraph("画像/システム/枠.png");
		Waku2 = LoadGraph("画像/システム/パラメータ表示部分.png");
		LoadDivGraph("画像/キャラ/自機.png",16,4,4,66,66,ziki_img);
		ztama = LoadGraph("画像/弾/自機弾.png");
		ztamakage = LoadGraph("画像/弾/自機弾影.png");

//構造体
		//shot tama[10]の設定
		for(i=0;i<10;i++){
			tama[i].x=ziki.x;
			tama[i].y=ziki.y-28;
			tama[i].flag=0;
		}

		//ループ部分
        while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 & gpUpdateKey()==0 ){//while(裏画面の物を表画面に写す,メッセージ処理,画面を消去,キーの状態の更新)
			if(mode==0){
				mode=10;
			}
//タイトル画面
			else if(mode==10){
				                                     //計算フェーズ
				Tmove();
				                                     //描画フェーズ
				for( int i=0; i<4; i++ ){ // メニュー項目を描画
					DrawFormatString( MenuElement[i].x, MenuElement[i].y, GetColor(255,255,255), MenuElement[i].name );
				}

			}
//ゲーム画面
            else if(mode==20){
                                                     //計算フェーズ
                                                                //自機の設定
				Zmove();
				zikitama();

                                                     //描画フェーズ
                DrawGraph(20,80,Back1,TRUE);
				for(i=0;i<10;i++){
					if(tama[i].flag==1){
						DrawRotaGraph(tama[i].x,tama[i].y,1.0,gcnt*PI/5,ztama,TRUE);
						SetDrawBlendMode(DX_BLENDMODE_ALPHA, 128);
						DrawRotaGraph(tama[i].x,tama[i].y,1.0,0.0,ztamakage,TRUE);
						SetDrawBlendMode(DX_BLENDMODE_NOBLEND, 0);
					}
				}
                DrawRotaGraph(ziki.x,444,1.0,0.0,ziki_img[ziki.no],TRUE);
				DrawGraph(0,0,Waku1,TRUE);
				DrawGraph(20,15,Waku2,TRUE);
            }
 
    }
 
        DxLib_End();    // DXライブラリ終了処理
        return 0;
} 

エラーメッセージにはTmove関数のbreakがおかしいと言われたのですが、書き換える前は普通に動いていました。一体どういう間違いがあるのでしょうか?そしてどうすればビルドできるようになるのでしょうか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: 関数を立てたらbreak文でビルドが止まった

#2

投稿記事 by softya(ソフト屋) » 13年前

Tmoveは新たに作成された関数ですよね?
breakはswitchやwhileやforの出てこないところには許されない命令ですのでエラーなのは当たり前とし言えません。
break;で何処に抜けるつもりだったのでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

dast
記事: 41
登録日時: 13年前

Re: 関数を立てたらbreak文でビルドが止まった

#3

投稿記事 by dast » 13年前

「Selectが3の時にAが押されたらプログラムを終了」という結果を出すためにmainのwhileを抜けるのに使っていました。
よくよく考え直してみたらこの部分を別の関数にそのままそっくり移してエラーが出るのは当たり前ですね。
すみません、見直しが甘かったようで…。
ではこのbreakの部分をどう変えたらプログラムが同じ働きをしてくれるのでしょうか?
やっぱり新しくスイッチになる変数を用意するしかないでしょうか?
なんかこう「この文を通過したら即終了する」みたいな文ってありませんかね。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: 関数を立てたらbreak文でビルドが止まった

#4

投稿記事 by softya(ソフト屋) » 13年前

Tmove()の戻り値がTRUEなら終了、FALSEなら継続ではどうでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

dast
記事: 41
登録日時: 13年前

Re: 関数を立てたらbreak文でビルドが止まった

#5

投稿記事 by dast » 13年前

すみません、「そこを聞くのかよ」って反応が来そうなくらい初歩的なことを聞いていいですか?

戻り値って何ですか?

いや、何となくニュアンスは分かるんですよ。関数の中で1+1をやったら戻り値は2になるんだろうなーって感じで。
でもこの内容の関数の戻り値ってどうなるのかがイメージが沸きにくいので……。softyaさんのご指摘からTRUEかFALSEで帰ってくるのかなーって想像しましたけど。
そして戻り値ってどういう風に参照するのですか?
Tmove関数の次のところでif(Tmove=~){~}みたいな感じでいいんですか?
ごちゃごちゃした文ですみません。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: 関数を立てたらbreak文でビルドが止まった

#6

投稿記事 by softya(ソフト屋) » 13年前

戻り値は関数側での状況をメインに返すために使います。

コード:

//	関数側
int Tmove() {
	return TRUE;	//終了する。break;のところに。
	return FALSE;	//終了しない。それ以外の場合。
}

//メインで
if( Tmove() ) {	//TRUEなら終了
	break;
}
C言語の勉強は入門書や下記サイトを参考にしてください。
「引数と戻り値」
http://wisdom.sakura.ne.jp/programming/c/c28.html
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

dast
記事: 41
登録日時: 13年前

Re: 関数を立てたらbreak文でビルドが止まった

#7

投稿記事 by dast » 13年前

ご紹介ありがとうございます。参考にさせていただきます。

閉鎖

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