始めまして。
例えばオミクジのプログラムを作ったとして
普通に書くと
if( kekka == 0 )
{
printf( "大吉" );
}
else if( kekka == 1 )
{
printf( "中吉" );
}
else if( kekka == 2 )
{
printf( "小吉" );
}
…
と単純なif文が多くなってしまうと思うんですが、それをなるべく短く、かつ見やすく解決する方法って無いでしょうか?
ちなみにこの例だと配列を使えば解決するんですが、それ以外の方法を教えてほしいです。
ifやswitchを使わない条件分岐について
Re:ifやswitchを使わない条件分岐について
お返事ありがとうございます。
確かに配列を使うと見やすく行くと思うのですが…。
srand( (unsigned int)time(NULL) );
char* s[5] = { "大吉" , "中吉" , "小吉" , "凶" , "大凶" };
printf( "%s\n" , s[ rand() % 5 ] );
この用に単純なプログラムだと良いのですが、C++での開発で
「もし、何々の時にオブジェクトを生成する」といった場合はどの様にしたら良いのでしょう?
製作しているゲームで、外部データを元にオブジェクトを生成させる処理があり、
// 登録されたデータ分生成
for( ; itr != DataContiner.end() ; ++itr )
{
int type = (*itr).ObjType;
if( (*itr).ObjType == WALL )
{
ObjectSPtr enemy( new Wall( 略 );
mObjectManager.add( enemy );
}
if( (*itr).ObjType == WOODWALL )
{
ObjectSPtr enemy( new WoodWall( 略 );
mObjectManager.add( enemy );
}
~略(この様な処理が30個程…。)~
}
この様な処理になってしまい、非常に醜い(見にくい)です。
ファクトリーなどの導入も考えましたが、結局の所コードが同じ様な処理になってしまいどうにも参っています。
こういった場合、どうすれば簡潔にかけるでしょうか?
確かに配列を使うと見やすく行くと思うのですが…。
srand( (unsigned int)time(NULL) );
char* s[5] = { "大吉" , "中吉" , "小吉" , "凶" , "大凶" };
printf( "%s\n" , s[ rand() % 5 ] );
この用に単純なプログラムだと良いのですが、C++での開発で
「もし、何々の時にオブジェクトを生成する」といった場合はどの様にしたら良いのでしょう?
製作しているゲームで、外部データを元にオブジェクトを生成させる処理があり、
// 登録されたデータ分生成
for( ; itr != DataContiner.end() ; ++itr )
{
int type = (*itr).ObjType;
if( (*itr).ObjType == WALL )
{
ObjectSPtr enemy( new Wall( 略 );
mObjectManager.add( enemy );
}
if( (*itr).ObjType == WOODWALL )
{
ObjectSPtr enemy( new WoodWall( 略 );
mObjectManager.add( enemy );
}
~略(この様な処理が30個程…。)~
}
この様な処理になってしまい、非常に醜い(見にくい)です。
ファクトリーなどの導入も考えましたが、結局の所コードが同じ様な処理になってしまいどうにも参っています。
こういった場合、どうすれば簡潔にかけるでしょうか?
Re:ifやswitchを使わない条件分岐について
素直に実装するなら,
どこか一箇所switch文かそれに相当するコードが必要になりますが,
それ以降は全部継承を使ってswitch文が不要になります。
class Object { public: virtual ObjectSPtr create_enemy() = 0; }; class WallObject : public Object { public: ObjectSPtr create_enemy() { return new Wall(); } }; class WoodWallObject : public Object { public: ObjectSPtr create_enemy() { return new WoodWall(); } };のような継承関係を作っておいて,
for( ; itr != DataContiner.end() ; ++itr ) { mObjectManager.add(itr->create_enemy()); }のように処理することでしょうか。
どこか一箇所switch文かそれに相当するコードが必要になりますが,
それ以降は全部継承を使ってswitch文が不要になります。
Re:ifやswitchを使わない条件分岐について
>YuOさん
Wallを生成するのにWallObjectと言うクラスに責任を預けると言う事でしょうか?
やはりクラス数が2倍になっても、ファクトリーの様なものを作ったほうがスマートに書けそうですね。
(というかそれ以外になさそう…w)
Wallを生成するのにWallObjectと言うクラスに責任を預けると言う事でしょうか?
やはりクラス数が2倍になっても、ファクトリーの様なものを作ったほうがスマートに書けそうですね。
(というかそれ以外になさそう…w)
Re:ifやswitchを使わない条件分岐について
>外部データを元にオブジェクトを生成させる処理があり、
ObjTypeが整数・列挙型とかで、0から始まっているとするなら
[color=#d0d0ff" face="monospace]
enum Type { WALL, WOODWALL };
ObjectSPtr *CreateWall() { return new Wall(); }
ObjectSPtr *CreateWoodWall() { return new WoodWall(); }
[/color]
という関数を作っておいて
[color=#d0d0ff" face="monospace]
const std::pair<Type, ObjectSPtr* (*)()> CreateSptrTbl[/url] =
{
std::make_pair(WALL, CreateWall),
std::make_pair(WOODWALL, CreateWoodWall),
};
[/color]というような(手抜きなので pairを使っていますが)テーブルを作ります。
で、何の型かは不明ですが DataContinerをループで回すときに
[color=#d0d0ff" face="monospace]
for( ; itr != DataContiner.end() ; ++itr )
{
const Type type = (*itr).ObjType;
if(type >= 0 && type <sizeof(CreateSptrTbl) / sizeof(CreateSptrTbl[0]))
mObjectManager.add((*CreateSptrTbl[type].second)());
}
[/color]
とすればそれなりにすっきりはしますね。
ObjTypeが整数・列挙型以外だったり、0から始まっているわけでないのなら
mapにでも入れて似たようなことができるかと思いますが、どうでしょう?
ObjTypeが整数・列挙型とかで、0から始まっているとするなら
[color=#d0d0ff" face="monospace]
enum Type { WALL, WOODWALL };
ObjectSPtr *CreateWall() { return new Wall(); }
ObjectSPtr *CreateWoodWall() { return new WoodWall(); }
[/color]
という関数を作っておいて
[color=#d0d0ff" face="monospace]
const std::pair<Type, ObjectSPtr* (*)()> CreateSptrTbl[/url] =
{
std::make_pair(WALL, CreateWall),
std::make_pair(WOODWALL, CreateWoodWall),
};
[/color]というような(手抜きなので pairを使っていますが)テーブルを作ります。
で、何の型かは不明ですが DataContinerをループで回すときに
[color=#d0d0ff" face="monospace]
for( ; itr != DataContiner.end() ; ++itr )
{
const Type type = (*itr).ObjType;
if(type >= 0 && type <sizeof(CreateSptrTbl) / sizeof(CreateSptrTbl[0]))
mObjectManager.add((*CreateSptrTbl[type].second)());
}
[/color]
とすればそれなりにすっきりはしますね。
ObjTypeが整数・列挙型以外だったり、0から始まっているわけでないのなら
mapにでも入れて似たようなことができるかと思いますが、どうでしょう?