フラグを多用するとコードがぐちゃぐちゃ

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
YM

フラグを多用するとコードがぐちゃぐちゃ

#1

投稿記事 by YM » 14年前

初めまして。 始めてゲームを作っています。作らないといけない事情で。DXLIBを利用しています。
C++の知識は以前はifforwhile ~ 配列まで,ゲームを作りながらクラスを覚えました。
ポインタはコンソールでは納得しながらも,実用するに至っていません。構造体も使いこなしていません。現状クラスだけです。

Q.ゲームの流れをコントロールするのはフラグ,という認識でいいのでしょうか?

たとえばゲームをオープニング→ゲーム→エンディング→スコア表示
としようとすると,

コード:

bool flag[10] = {0};
// ↑どこかで用意したグローバルなフラグを

while(flag[3] == 0){
    if(flag[0] == 0)
        intro(); // → これが終わるとflag[0] = 1;
    if(flag[0] == 1 && flag[1] == 0)
        game();  // → 終わるとflag[1] = 1;
    if(flag[1] == 1 && flag[2] == 0)
        ending(); // →終わるとflag[2] = 1
    if(flag[2] == 1 && flag[3] == 0)
        score();   // →終わるとflag[3] = 1; ループも抜ける
}
メインループはこんな感じで,その他処理にもフラグを使いまくっています。
例えば条件を満たすフレームが何度もあるが,うち1回だけ処理を行いたい時

コード:

if(flag[i] == 0){
    PlaySoundMem(...);
    flag[i] = 1;
}
else{}
if(flag==)が余りにも多いのでごちゃごちゃしていて,書き方がまずいのではないかと疑った次第です。
これはこういうものだと思ってもいいのでしょうか?

フラグの管理方法はflagのiをテキストファイルに書いておき,どのフラグがどのような役割を与えられているか
簡単な説明をする方法でやっています。

別例(今作っているゲームから自機の操作関数の一部分を抜き出しました)
並列した3本の道路の上を敵が流れてくるので自機が避けるゲームだと思ってください。

コード:


// ↓ これは館にあるキーボード状態取得系処理のサンプルを利用しています
if(flag[3] == 0){
	if(key[KEY_INPUT_LEFT] == 1 && flag[1] == 0){
		// 自機が左レーンにいないなら左を移動するためのフラグを立てる
		if(x != xinit - 54){
			flag[0] = 1;	// 左移動を有効化
			flag[3] = 1;	// 移動終了までキー入力を無効化。
			flag[10] = 1;	// 移動終了まであたり判定を無効化。移動中に敵と当たると座標が狂う
			reset_count();	// count = 0; の処理		}
	}
}

int t = count;

if(flag[0] == 1){
	if(t <= 5){
		// 6フレーム目(最終)のみに行われる処理
		if(t == 5){
			flag[0] = 0;	// 6フレーム目で左移動フラグを倒す
			flag[3] = 0;	// キー入力を有効化
			flag[10] = 0;	// あたり判定を有効化
		}
		x+=5;
		y-=5;
		count++;
	}
}

アバター
h2so5
副管理人
記事: 2212
登録日時: 14年前
住所: 東京
連絡を取る:

Re: フラグを多用するとコードがぐちゃぐちゃ

#2

投稿記事 by h2so5 » 14年前

YM さんが書きました: if(flag==)が余りにも多いのでごちゃごちゃしていて,書き方がまずいのではないかと疑った次第です。
これはこういうものだと思ってもいいのでしょうか?

elseやelse if や switch を使えばもう少し簡単に書けます。

YM さんが書きました: フラグの管理方法はflagのiをテキストファイルに書いておき,どのフラグがどのような役割を与えられているか
簡単な説明をする方法でやっています。

その方法ではフラグの役割が全く分からないので配列を使わないで、具体的な変数名でフラグを宣言してください。

見た感じではC言語の基礎が出来ていないようなので、
ちゃんと文法を学習することをお勧めします。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: フラグを多用するとコードがぐちゃぐちゃ

#3

投稿記事 by みけCAT » 14年前

フラグの説明をテキストファイルに書くのではなく、
enumで簡単な説明をソースコードに書き込むのがいいと思います。

コード:

enum {
    FLAG_TITLE=0,
    FLAG_OPENING,
    FLAG_MAIN,
    FLAG_ENDING,
    FLAG_SCORE,
    /*以下略*/
}
h2so5 さんが書きました:
YM さんが書きました: フラグの管理方法はflagのiをテキストファイルに書いておき,どのフラグがどのような役割を与えられているか
簡単な説明をする方法でやっています。

その方法ではフラグの役割が全く分からないので配列を使わないで、具体的な変数名でフラグを宣言してください。

もちろんこれでもいいと思います。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

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

Re: フラグを多用するとコードがぐちゃぐちゃ

#4

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

クラスがわかるなら、構造体もわかると思うんですけどね。
少なくとも構造体で自機と敵の情報変数を分けたほうが良いと思います。

「新・C言語 ~ゲームプログラミングの館~ [DXライブラリ]」
http://dixq.net/g/
ここに出てくるC言語の文法は理解すべきでしょうね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

YM

Re: フラグを多用するとコードがぐちゃぐちゃ

#5

投稿記事 by YM » 14年前

h2so5さん
フラグが分かりにくいというのは実感しています。というかこれがごちゃごちゃしている問題の根本か。
ただ,フラグに番号は付けたいと思っています。
全体で30本近いフラグが8枚程度に分割されたソースファイル内に散らばっているので,個々に個性のある名前をつけると管理が大変です。

elseやelse ifも適材適所で使っています。主にフラグのTRUE/FALSEのどちらでも処理を行う時に。


みけCATさん
enumは簡単な役割は知っていましたが,頂いた例の使い方がイマイチ分かりません。
enum {FLAG_TITLE = 0; ...} ならば,その先は {... FLAG_OPENING = 1;} となるのでしょうが・・・。SO WHAT状態。
それとも単に管理方法の一種ならば良いんですが。
ちょっと気になるので一言良ければお願いしますmm


朗報といえば,とある考えが浮かんだことでしょうか。
別名をつける,ということとenumの中身からヒントを得ました。ありがとうございます。


グローバル変数
bool flag[10] = {0};

―を作成したファイルのヘッダーに

#define FLAG_TITLE flag[0]
#def...
extern bool flag[10];

これをincludeしたら動いたので,これでいくらか問題は解決するでしょう。
もしかしてこれもあまりよくなかったりしますか?勝手に良いと思っただけですが


ソフト屋さん
すみません。構造体,というよりクラスは使っているんですが,一部抜粋にすると説明が必要になるのでxとyに書き換えました。
メンバ変数は全部private:に入れてあり,変数操作は実際は jiki::add_x(int num) {x += num;} みたいなことしてます。
制作中のコンテンツも期待して待っています。
構造体を使わなかった理由は特にありません。クラスを先に知ったのでクラスを使えばいいか,みたなものです。

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

Re: フラグを多用するとコードがぐちゃぐちゃ

#6

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

YM さんが書きました:制作中のコンテンツも期待して待っています。
あのコンテンツは、私じゃなくてDixq(管理人)さんですね。
私は掲示板の管理サポータですので。

それで、色々勘違いされていると思いますがフラグは色々名前を付けないために構造体やクラスで一纏めにするんです。
あと何でもTRUE/FALSEで管理されているのがややこしいで状態遷移はTRUE/FALSEで管理せずにみけCATさんの提案のようにenumで番号管理する方が手間が少なくなります。

YM さんの物を書き換えた参考記述例。

コード:

削除
[追記]
書いた後で、ここまでやったほうが良いと思ったので訂正。さらにバグ修正。

コード:

enum state_e {
    STATE_INTRO,
    STATE_GAME,
    STATE_ENDING,
    STATE_SCORE,
    STATE_END,
};

state_e state = STATE_INTRO;
 
while(state!=STATE_END){
	
	switch( state ) {
	case STATE_INTRO:
        if( intro() ) {// 終わるとTRUE
        	state = STATE_GAME;
        }
		break;
	case STATE_GAME:
        if( game() ) {// 終わるとTRUE
        	state = STATE_ENDING;
        }
        break;
	case STATE_ENDING:
        if( ending() ) {// 終わるとTRUE
        	state = STATE_SCORE;
        }
        break;
	case STATE_SCORE:
        if( score() ) {// 終わるとTRUE
        	state = STATE_END;
        }
        break;
    }
}
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

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

Re: フラグを多用するとコードがぐちゃぐちゃ

#7

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

あと一般的に分りやすいとされるのはflag[0]ではなく名前を付けることでサンプルはこちらです。

コード:

//	クラスに追加と想定
class Player
{
private:
	bool fKeyInvalidate;	//キー無効(true)			flag[3]
	bool fHitInvalidate;	//当たり判定無効(ture)		flag[10]
	bool fMoveLeft;			//左移動					flag[0] 
	bool fFlag1;			//機能不明で名前付けられず	flag[1]
}

if( fKeyInvalidate==false ) {
    if( key[KEY_INPUT_LEFT] == 1 && fFlag1==false ){
        // 自機が左レーンにいないなら左を移動するためのフラグを立てる
        if(x != xinit - 54){
			fMoveLeft = true;		// 左移動を有効化
			fKeyInvalidate = true;	// 移動終了までキー入力を無効化。
			fHitInvalidate = true;	// 移動終了まであたり判定を無効化。移動中に敵と当たると座標が狂う
            reset_count();  // count = 0; の処理
        }
    }
}

int t = count;
 
if(fMoveLeft){
    if(t <= 5){
        // 6フレーム目(最終)のみに行われる処理
        if(t == 5){
            fMoveLeft = false;		  // 左移動フラグを無効化
            fKeyInvalidate = false;	  // キー入力を有効化
            fHitInvalidate = false;	  // あたり判定を有効化
        }
        x+=5;
        y-=5;
        count++;
    }
}
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

YM

Re: フラグを多用するとコードがぐちゃぐちゃ

#8

投稿記事 by YM » 14年前

両方とも納得できる分かりやすさでした。前者のswitchはスマートですね。美しい。笑
後者のコードを校正していただいたのも自分がなにをやればいいのか分かりやすいです。
例示に入れておく必要のなかったフラグを消し忘れていました。お手数かけました。

その他いろいろと勉強になる書き方があったので参考にします。ありがとうございます。

とりあえず手始めにフラグを管理するクラスか構造体かを用意することにします。

アバター
Dixq (管理人)
管理人
記事: 1662
登録日時: 14年前
住所: 北海道札幌市
連絡を取る:

Re: フラグを多用するとコードがぐちゃぐちゃ

#9

投稿記事 by Dixq (管理人) » 14年前

> 制作中のコンテンツも期待して待っています。

オンラインゲームの奴ですかね?
ありがとうございます。

ソースコードはコメント無しで誰が見ても分かるように書くのがベストだと思いますので、flag と言う変数名は嫌われがちですね。
私のプログラムの師からは「フラグは無くても設計は出来る。フラグは使うな」と言われたほどです。
そうは言ってもフラグが必要な場面はあるので、今回のようになるべく分かり易く変数の意味を表す工夫をされると良いと思います。

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

Re: フラグを多用するとコードがぐちゃぐちゃ

#10

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

Dixq (管理人) さんが書きました:オンラインゲームの奴ですかね?
ありがとうございます。
話の流れから、「新・C言語 ~ゲームプログラミングの館~」の事かと。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: フラグを多用するとコードがぐちゃぐちゃ

#11

投稿記事 by みけCAT » 14年前

YM さんが書きました:みけCATさん
enumは簡単な役割は知っていましたが,頂いた例の使い方がイマイチ分かりません。
enum {FLAG_TITLE = 0; ...} ならば,その先は {... FLAG_OPENING = 1;} となるのでしょうが・・・。SO WHAT状態。
それとも単に管理方法の一種ならば良いんですが。
ちょっと気になるので一言良ければお願いしますmm
enumを使うと自動的に連番の定数が生成されます。
例えば、

コード:

enum {
    FLAG_TITLE=0,
    FLAG_OPENING,
    FLAG_MAIN,
    FLAG_ENDING,
    FLAG_SCORE
}
とすると、FLAG_TITLEが0、FLAG_OPENINGが1、FLAG_MAINが2、FLAG_ENDINGが3、FLAG_SCOREが4になります。
これを使うと、例えばflag[0]をflag[FLAG_TITLE]、flag[1]をflag[FLAG_OPENING]などと書けます。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
Dixq (管理人)
管理人
記事: 1662
登録日時: 14年前
住所: 北海道札幌市
連絡を取る:

Re: フラグを多用するとコードがぐちゃぐちゃ

#12

投稿記事 by Dixq (管理人) » 14年前

あぁ制作中のコンテンツってそちらの方でしたか。
すみません、作成中のままで・・。早いところ作ってしまおうと思います。

閉鎖

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