ページ 11

似たような処理をまとめたい

Posted: 2013年6月25日(火) 01:11
by kees
はじめまして。初投稿となります。

現在配列内を調べる関数として以下があります。(メンバ関数の一部です)
現在地点から上下左右に調べる関数なのですが、似たような処理なのにまとめられなくてモヤモヤしています。
ただfor文の条件と、getTypeの引数が違うくらいでほぼ同じです。
何かいいまとめ方はないでしょうか?

よろしくお願い致します。

コード:

bool checkUp( int x, int y, int type )
{
	for( int i = y - 1; i >= 0; --i ) {	
		if( getType(x,i) == type) ) {
			return true;
		}
	}
	return false;
}
bool checkDown( int x, int y, int type )
{
	for( int i = y + 1; i < MAX_Y; ++i ) {	
		if( getType(x,i) == type) ) {
			return true;
		}
	}
	return false;
}
bool checkLeft( int x, int y, int type )
{
	for( int i = x - 1; i >= 0; --i ) {	
		if( getType(i,y) == type) ) {
			return true;
		}
	}
	return false;
}
bool checkRight( int x, int y, int type )
{
	for( int i = x + 1; i < MAX_X; ++i ) {	
		if( getType(i,y) == type) ) {
			return true;
		}
	}
	return false;
}

Re: 似たような処理をまとめたい

Posted: 2013年6月25日(火) 01:46
by YuO
kees さんが書きました:現在配列内を調べる関数として以下があります。(メンバ関数の一部です)
現在地点から上下左右に調べる関数なのですが、似たような処理なのにまとめられなくてモヤモヤしています。
ただfor文の条件と、getTypeの引数が違うくらいでほぼ同じです。
何かいいまとめ方はないでしょうか?
わたしだったら,若干効率を犠牲にしまいますが,xとyのインクリメント値を引数に渡すことで処理します。

コード:

namespace
{
    bool checkType (int x0, int y0, int cx, int cy, int type) // cx, cyはインクリメント値。
    {
        for (int x = x0 + cx, y = y0 + cy;
             0 <= x && x < MAX_X && 0 <= y && y < MAX_Y; // xとyが範囲内であることを調べる
             x += cx, y += cy)
        {
            if (getType(x, y) == type) {
                return true;
            }
        }
        return false;
    }
}

bool checkUp (int x, int y, int type)
{
    return checkType(x, y, 0, -1, type);
}

bool checkDown (int x, int y, int type)
{
    return checkType(x, y, 0, +1, type);
}

bool checkLeft (int x, int y, int type)
{
    return checkType(x, y, -1, 0, type);
}

bool checkRight (int x, int y, int type)
{
    return checkType(x, y, +1, 0, type);
}

Re: 似たような処理をまとめたい

Posted: 2013年6月25日(火) 02:04
by kees
YuOさん返信ありがとうございます。

インクリメントを引数に取る方法は思いつきませんでした。
確かに、これなら主要な部分はひとまとめにできますね。
しかし、欲を言えば関数の使い勝手を重視したいです。
一つの関数で完結させたいって感じです。
無理に一つの関数にしようとすると、ゴチャゴチャになりそうでよろしくはないと思っているのですが・・・
一応以下のような関数も考えてみたのですが、ただ呼び出すものを切り替えているだけでスッキリしなかったんです。

コード:

bool checkType( int x, int y, int type, int dir )
{
	switch( dir )
	{
	case 0:	return checkUp( x, y, type );		break;
	case 1:	return checkDown( x, y, type );		break;
	case 2:	return checkLeft( x, y, type );		break;
	case 3:	return checkRight( x, y, type );	break;
	}
}

Re: 似たような処理をまとめたい

Posted: 2013年6月25日(火) 04:20
by sprbo
関数を1つにするのであれば引数のdirでxとyの値を進めてはみてはいかがでしょう。

コード:

bool CheckType( int x, int y, int type, int dir )
{
    switch( dir )
    {
    case 0:
        y--;
        break;
    case 1:
        y++;
        break;
    case 2:
        x--;
        break;
    case 3:
        x++;
        break;
    default:
        return false;
    }

    //xとyの範囲内かをチェック
    if( y < 0 || y >= MAX_Y || x < 0 || x >= MAX_X )
        return false;
    
    //現要素をチェック
    if( GetType( x, y ) == type )
        return true;

    //次の要素のチェックへ
    return CheckType( x, y, type, dir ); 
}

Re: 似たような処理をまとめたい

Posted: 2013年6月25日(火) 05:13
by sprbo
ああ・・・よく見てませんでした。
YuOさんのCheckType関数を直接呼んだ方が早いですね

Re: 似たような処理をまとめたい

Posted: 2013年6月25日(火) 16:38
by ISLe
kees さんが書きました:しかし、欲を言えば関数の使い勝手を重視したいです。
一つの関数で完結させたいって感じです。

コード:

bool checkType(int x, int y, int type, int dir)
{
	if (dir < 0 || dir >= 4) return false;
	static const struct { int x; int y; } vec[4] = {
		{  0, -1 }, // 上方向
		{  0,  1 }, // 下方向
		{ -1,  0 }, // 左方向
		{  1,  0 }, // 右方向
	};
	// YuOさんのcheckType関数 なんならここに中身を展開してしまっても
	return checkType(x, y, vec[dir].x, vec[dir].y, type);
}

Re: 似たような処理をまとめたい

Posted: 2013年6月27日(木) 01:55
by kees
みなさん返信有り難うございます。
返事が遅くなってしまい、申し訳ありません。

ISLeさんとYuO合わせた関数はとても使いやすそうです。
呼び出し元も引数で切り替えがきくし、内部処理もまとまっていて共通処理を入れやすいそうです。

この形を雛形とし、組み込もうと思います。
みさなんありがとうございました!とても助かりました。

また悩みが出た時は質問させてもらいます!
それでは失礼します。