1

編集: attack.condition には複数の値が含まれることがあるため、switch ステートメントは機能しません。

だから私は成長しようとしているこの列挙型を持っています:

enum Condition {    Null            =   0x0001,
            SelfIsUnderground   =   0x0002,
            SelfIsGround        =   0x0004,
            SelfIsAir       =   0x0008,
            SelfIsWater     =   0x0010,
            OtherIsUnderground  =   0x0020,
            OtherIsGround       =   0x0040,
            OtherIsAir      =   0x0080,
            OtherIsWater        =   0x0100,
            Tile            =   0x0200,
            CONDITION_COUNTX    =   0x03FF};

そして、この関数も成長します:

bool Attack::CanBeDone(Spirit* pSelf, Spirit* pTarget,Map* pMap)
{
    if(this->condition!=Null)
    {
        if(this->condition & SelfIsUnderground)
            if(pSelf->GetcurrentLayer()!=Underground)
                return false;

        if(this->condition & SelfIsGround)
            if(pSelf->GetcurrentLayer()!=Ground)
                return false;

        if(this->condition & SelfIsAir)
            if(pSelf->GetcurrentLayer()!=Air)
                return false;

        if(this->condition & SelfIsWater)
            if(pSelf->GetcurrentLayer()!=Water)
                return false;

        if(this->condition & OtherIsUnderground)
            if(pTarget->GetcurrentLayer()!=Underground)
                return false;

        if(this->condition & OtherIsGround)
            if(pTarget->GetcurrentLayer()!=Ground)
                return false;

        ...

何度も何度も書くことに代わるものはありますか:

    if(this->condition & arg)
        if(pSelf->GetcurrentLayer()!=value)
            return false;

?

おまけ: Condition::Null に値 0x0000、SelfIsUnderground 0x0001、SelfIsGround 0x0002 を与えて、再び 2 の累乗にするとうまくいくでしょうか? 最終的に、Tile の値は 0x0100 になります。

4

4 に答える 4

2

まず、次のように書きます。

enum Condition {    Null            =   0x0001,
            SelfBase        =   0x0002,
            SelfIsUnderground   =   SelfBase * (1 << Underground),
            SelfIsGround        =   SelfBase * (1 << Ground),
            SelfIsAir       =   SelfBase * (1 << Air),
            SelfIsWater     =   SelfBase * (1 << Water),
            SelfMask        =   SelfBase * ((1 << Max) - 1),
            OtherBase       =   0x0020,
            OtherIsUnderground  =   OtherBase * (1 << Underground),
            OtherIsGround       =   OtherBase * (1 << Ground),
            OtherIsAir      =   OtherBase * (1 << Air),
            OtherIsWater        =   OtherBase * (1 << Water),
            OtherMask       =   OtherBase * ((1 << Max) - 1),
            Tile            =   0x0200,
            CONDITION_COUNTX    =   0x03FF};

(それと仮定Underground == 0Max == Water + 1。次に、長いリストは 2 つのかなり鮮明な式に縮小されます。

if ( (SelfMask & this->condition & (SelfBase * (1 << pSelf->GetcurrentLayer()))) )
    return false;

if ( (OtherMask & this->condition & (OtherBase * (1 << pTarget->GetcurrentLayer()))) )
    return false;

return true;

列挙型を展開しても、これは正しいままです。ただし、まだいくらかの冗長性があることに注意してください (たとえば、OtherBaseTileがどのように定義されているかなど)、これも減らすことができます。Condition静的アサートは、列挙型が適切に定義されていることを確認するのに役立ちます。

于 2013-04-03T01:57:50.743 に答える
0

Condition列挙を完全に放棄し、代わりに構造体を使用すると思います。自身と対象の条件は別物であり、そのように扱われるべきである

enum Layer : char //only takes 1 byte
{
    Ground      = 1<<0,
    Underground = 1<<1,
    Air         = 1<<2,
    Water       = 1<<3
};
struct Condition {
    Layer Self;
    Layer Target;
};
bool Attack::CanBeDone(Spirit* pSelf, Spirit* pTarget,Map* pMap) {
    return this->Condition.Self & pSelf->GetcurrentLayer() 
        && this->Condition.Target & pTarget->GetcurrentLayer();
}
于 2013-04-03T03:33:16.417 に答える
0

これは、ビットマスクとビットごとの操作を使用して、時期尚早に最適化することで得られるものです。簡単な代替手段はありません。

なぜstd::vector<Layer> selfLayers, otherLayersですか?(または、複数のレイヤーを持つことはできません-コードは、できることを意味します。)
または、レイヤーからrequiredConditionBitsへのマップを使用できますか?

Attackまた、クラスが 2 つの s の条件を格納している理由がわかりませんSpirit。誰Attack::conditionが最初に設定しますか?

ビットではないものにはビットマップを使用せず、列挙型ではないものには列挙を使用しないことから始めます。Layer単純なクラス ( 、などCondition) とヘルパー関数 (Attack::getSourceLayer多分? 混乱しすぎて確信が持てません)の作成に時間を費やすことを検討します。また、クラスの関係を見直して、Attack本当にconditionフラグなどが必要であることを確認します。

于 2013-04-03T02:46:39.770 に答える
0

Layerと列挙型を結び付けるとCondition、次の行に何かを書くことができます。

enum Condition {    Null            =   0x0001,
    SelfIsUnderground   =   0x0002,
    SelfIsGround        =   0x0004,
    SelfIsAir       =   0x0008,
    SelfIsWater     =   0x0010,
    OtherIsUnderground  =   0x0020,
    OtherIsGround       =   0x0040,
    OtherIsAir      =   0x0080,
    OtherIsWater        =   0x0100,
    Tile            =   0x0200,
    CONDITION_COUNTX    =   0x03FF};

enum Layer
{
    Ground = SelfIsGround,
    Underground = SelfIsUnderground,
    Air = SelfIsAir,
    Water =  SelfIsWater
};

struct Spirit
{
    Layer GetcurrentLayer() const;

};

struct Map;

struct Attack
{
    Condition condition;
    bool CanBeDone(Spirit* pSelf, Spirit* pTarget,Map* pMap)
    {
        return (condition & pSelf->GetcurrentLayer() )&&
             ( (condition / 0x10) & pTarget->GetcurrentLayer());
    }

};

Conditionおそらく、の観点から定義することを期待していますLayerが、それは単なる詳細です。

于 2013-04-03T02:10:21.410 に答える