2013-08-02 38 views
2

我编写的C + +的任天堂DS,但这应该是所有的C++通用。更高效的方式来编码,如果然后在C语言else语句

我已经知道switch语句,但我需要做一套的,如果,那么,和else有多个参数:

void doSomething(int number) 
{ 
... 
} 

bool left = true; 
bool right = false; 
bool top = false; 
bool bottom = false; 

if (left && top && right) 
    doSomething(1); 
else if (top && right && bottom) 
    doSomething(2); 
else if (left && right && bottom) 
    doSomething(3); 
else if (left && top && bottom) 
    doSomething(4); 

任何帮助表示赞赏。

+0

如果只有那些布尔之一将是真实的,你可以连续做四个if语句,而且不需要嵌套。例如,'if(left)doSomething(1);如果(右)doSomething(2);'等等 – Xynariz

+2

什么决定了你的bool的价值?你的测试看起来不寻常左右两边怎么都是真的?对这些变量实际意义的解释可能会有所帮助。 –

+0

我发现想法右边界由左,上和下表示,都是非常直观的。 –

回答

10

可以四个布尔值转换成二进制数0..15,并使用数组来查找参数,就像这样:

int location = (left ? 1<<0 : 0) 
      | (right ? 1<<1 : 0) 
      | (top ? 1<<2 : 0) 
      | (bottom ? 1<<3 : 0); 

现在location有一个从0到15,所以你可以这样做:

int lookup[] = {-1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 3, -1, 4, 2, -1}; 
int arg = lookup[location]; 
if (arg != -1) { 
    doSomething(arg); 
} 
+1

你可以查找一个const数组。 –

+1

假设我六个月后回来,试着理解这段代码在做什么,用原始版本的代码不会更好吗?我真的不明白这个答案如何改善任何事情。请解释一下,也许我错过了一些东西...... – Tarik

+0

这真的很糟吗?看起来相当简单...三元运营商可能有点多,但是meh。尽管现在'doSomething()'需要在不同参数值之间的switch语句。 – Suedocode

0

封装这一成getSide()返回一个枚举。我假设布尔变量是从类实现或调用DoSomething的

... 
    bool left = true; 
    bool right = false; 
    bool top = false; 
    bool bottom = false; 
    ... 
    doSomething(getSide()); 
    ... 

    enum Side { 
    Top, Bottom, Left, Right 
    } 

    void doSomething(Side side) 
    { 
    ... 
    } 

    Side getSide() { 
    if (left && top && right) //Bottom Border 
     return Side.Bottom; 
    else if (top && right && bottom) //Left Border 
     return Side.Left; 
    else if (left && right && bottom) //Top Border 
     return Side.Top; 
    else if (left && top && bottom) //Right Border 
     return Side.Right; 
    } 
+0

尽管这会起作用,但如果...其他如果 –

+0

不会避免使用。实际上,它不会。我不认为避免如果其他方面有任何益处,除非在其他地方重复该代码;此时最好将其封装在方法中,并通过避免发送代表边的数字来澄清其余代码。 – Tarik

1

访问如果你是一个真正的心理(或混淆),你可以使用类似位掩码:

unsigned char direction = 8; // 1 0 0 0 for l r t b 

或留与公约相一致,你在你的问题中:

unsigned char direction = left + (right << 1) + (top << 2) + (bottom << 3); 

,然后你将有(*)

switch(direction) { 
    case 14: // 1 1 1 0 
     doSomething(1); 
     break; 
    case 7: // 0 1 1 1 
     doSomething(2); 
     break; 
    case 13: // 1 1 0 1 
     doSomething(3); 
     break; 
    case 11: // 1 0 1 1 
     doSomething(4); 
     break; 
} 

如果你需要方便地访问个人价值:

inline bool left() {return (direction & 8) == 8;} 
inline bool right() {return (direction & 4) == 4;} 
inline bool top() {return (direction & 2) == 2;} 
inline bool bottom() {return (direction & 1) == 1;} 

其实,这应该是非常快...


(*)作为替代,你也可以这样写:

const unsigned char left_c = 8; 
const unsigned char right_c = 4; 
const unsigned char top_c = 2; 
const unsigned char bottom_c = 1; 

并测试这样的组合(常数表达式在交换机接受):

switch(direction) { 
    case (left_c + right_c + top_c): 
     doSomething(1); 
     break; 
    ... 
} 
0

我加入该响应只是为了显示如何能够在std::bitset可以用于此目的。我知道,也许你的目标平台不支持C++ 11标准,但希望这可以帮助别人。

g++ locations.cpp -std=c++11 

输出是:

#include<iostream> 
#include<bitset> 
#include<vector> 
#include<map> 

// The location is represented as a set of four bits; we also need a 
// comparator so that we can later store them in a map. 
using Location = std::bitset<4>; 
struct LocationComparator { 
    bool operator()(const Location& loc1, const Location& loc2) const { 
    return loc1.to_ulong() < loc2.to_ulong(); 
    } 
}; 

// the callback (handler) has a signature "void callback()" 
using Callback = void (*)(); 

// the mapping between location and callback is stored in a simple 
// std::map 
using CallbackMap = std::map<Location, Callback, LocationComparator>; 

// we define the fundamental locations 
const Location Top ("1000"); 
const Location Bottom("0100"); 
const Location Right ("0010"); 
const Location Left ("0001"); 

// ... and define some actions (notice the signature corresponds to 
// Callback) 
void action_1() { std::cout<<"action 1"<<std::endl;} 
void action_2() { std::cout<<"action 2"<<std::endl;} 
void action_3() { std::cout<<"action 3"<<std::endl;} 
void action_4() { std::cout<<"action 4"<<std::endl;} 

// ... now create the map between specific locations and actions 
// (notice that bitset can perform logical operations) 
CallbackMap callbacks = { 
    { Top | Right , action_1 }, 
    { Top | Left , action_2 }, 
    { Bottom | Right , action_3 }, 
    { Bottom | Left , action_4 }, 
}; 

// an abstract game element has a location, the interaction will 
// depend on the defined callbacks 
class GameElement { 
public: 
    GameElement(const Location& location) 
     : m_location(location) { } 

    void interact() const { 
    callbacks[m_location](); 
    } 

    virtual ~GameElement() { } // so that others can inherit 
private: 
    Location m_location; 
}; 

int main() { 
    // create a vector of game elements and make them interact according 
    // to their positions 

    std::vector<GameElement> elements; 

    elements.emplace_back(Top | Right); 
    elements.emplace_back(Top | Left); 
    elements.emplace_back(Bottom | Right); 
    elements.emplace_back(Bottom | Left); 

    for(auto & e : elements) { 
    e.interact(); 
    } 

} 

我使用GCC 4.7.2使用以下命令编译它在OS X

action 1 
action 2 
action 3 
action 4