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)。然后,长列表简化为两个相当清晰的表达式:

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

如果将LayerCondition枚举绑定在一起,则可以在以下行中编写一些内容:

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());
    }

};

更有可能的是,我希望您根据 来定义ConditionLayer但这只是细节。

于 2013-04-03T02:10:21.410 回答
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该类存储两个Spirits 的条件。谁先设置Attack::condition

我会首先不对不是位的事物使用位图,也对不是枚举的事物使用枚举。我会考虑花一些时间创建简单的类(例如Layer, Condition)和辅助函数(Attack::getSourceLayer也许?我太困惑了,无法确定。)我还会检查我的类关系以确保Attack确实需要condition标志等。

于 2013-04-03T02:46:39.770 回答