2011-11-07 57 views
2

我使用無符號整數表示遊戲中的一堆飛機。每架飛機有兩個狀態,飛行和接地。我想將這個狀態與飛機編號一起存儲。什麼是實現這一目標的「最佳」方式?我可以使用std :: maps與飛機和它們的狀態,但似乎過度和緩慢。它可以使用位標誌完成嗎? 測試的分配和測試應該很快。如何在unsigned int上使用位標記以存儲其中的一個bool值

僞代碼:

unsigned int Boing = 777; 

if(Boing is flying) 
set some bit; 

is Boing flying? (how to check for the current state) 

任何暗示一個簡單而快速技術是讚賞!

回答

2

最快,最徹底的方法可能是避免位域,並簡單地定義一個結構:

struct Plane 
{ 
    bool isFlying; 
    unsigned int number; 
} 

... 


std::vector<Plane> planes; 
Plane p; 
p.isFlying = true; 
p.number = 777; 
planes.push_back(p); 

此方法將使用更多的內存比試圖國旗塞進同一個詞,但需要較少的工作獲取/設置字段。除非你受到內存限制,否則我強烈建議避免試圖緊密包裝所有東西。

你甚至可以考慮使用enum而不是bool作爲狀態。

+0

我承認,一個結構是好辦了。你知道的速度差什麼?我的意思是直接轉變一點聽起來要比涉及一個結構所帶來的所有代碼更快 – Lumpi

+3

@Lumpi:一個結構根本不需要任何代碼通過一個結構訪問一個字段只是一個內存訪問位字段需要一個內存訪問+位操作(實際上兩次寫入存儲器訪問)。 –

+0

@Lumpi:說實話,這將成爲你的瓶頸的可能性很小。但是,位填充意味着你在進行微型優化,並且結構不太可能變慢(除非你正在做大量的內存拷貝)。它也更清潔。 –

0

使用結構或類來組合信息「數字」和「狀態」,以及任何其他你想要的飛機。如果你在int上使用位操作(這是可能的,只是不可取的),改變狀態會改變你的飛機的實際數量。

2

一個簡單的方法就是如果不飛行就讓數字爲負值。

+0

不錯,簡單。 :) – Rontologist

+0

這很好,很簡單,但它也是不必要的醜陋(想想設置和獲取單個字段所需的代碼)和CPU密集型。 –

0

比方說,你的unsigned int類型有32位:

#define SET_FLYING(x)  (x) |= (1<<31) 
#define SET_GROUNDED(x) (x) &= ~(1<<31) 
#define IS_FLYING(x)  ((x) & (1<<31)) 
#define ID(x)    ((x) & ~(1<<31)) 

如果你想更C++時尚,你可以寫那些爲內聯函數。無論如何,我更多地寫了它來向您展示如何完成位操作,而不是將其實現爲宏還是函數。

,使其與不同尺寸爲int的工作,你可以改變31:

instead of 31: ((sizeof(x)<<3)-1) 

這基本上是sizeof(x)*8-1

附:如果有人想告訴我「不,不要使用宏,這是C++,使用我寫的這個過於複雜的東西」,保存你的呼吸。只需給-1,繼續前進。

編輯:我上面寫的是你的問題的答案:「如何使用標誌位作爲標誌」。如果你想這樣做,以更好的方式,但不擴大你的內存使用情況(通過增加bool),你可以寫這樣的事:

struct airplane 
{ 
    unsigned int id: 31; 
    unsigned int is_flying: 1; 
}; 

airplane Boing = {777, false}; 

然後分配給從id讀取或is_flying執行位操作,但它們由編譯器處理。

+0

使用宏,一切手段!但將它們括在括號內,否則它們將無法按預期工作。特別是,將'IS_FLYING(x)'定義爲'((x)&(1 << 31))'是一個非常好的主意。 – TonyK

+0

考慮'IS_FLYING(x)== IS_FLYING(y)'。用你的「不太看中」的宏,它不會起作用 - 或者說,給出錯誤的結果,但是該錯誤仍然隱藏。有了那些「過於複雜」的內聯函數,一切都會按預期工作,並且不會花費任何人的任何東西。附:只有一種方法可以完全避免對本網站的批評... –

+0

P.P.S.如果你的意思是'sizeof x * 8 - 1',爲什麼你不這樣寫呢? sizeof表達式返回的值是(在這種情況下是)編譯時常量,沒有什麼可以進行微優化的。似乎沒有理解什麼可以和什麼不能被微觀優化,從簡單的尖叫聲「壞C」開始,就像沒有用括號括起宏一樣。 –

1

假設您從未使用無符號整數範圍內的可用值(合理的可能性,但遠非絕對確定),您可以將範圍限制爲比包含無符號的位少一位,然後使用最重要的一點是存儲「飛行」狀態。在這種情況下,你可以這樣做:

// This theoretically isn't required to work, but will for most reasonable machines. 
unsigned flying_bit = 1 << (CHAR_BITS * sizeof(unsigned)); 

void take_off(unsigned &plane) { 
    plane |= flying_bit; 
} 

void land(unsigned &plane) { 
    plane &= flying_bit; 
} 

bool is_flying(unsigned const &plane) { 
    return plane & flying_bit != 0; 
} 

另一種可能性是使用實際的位字段:

struct plane { 
    uint32_t model: 31; 
    uint32_t flying: 1; 
}; 

在這種情況下,您只需直接賦值,如:

plane myplane = {777, 0}; 

myplane.flying = 1; // take off 

myplane.flying = 0; // land 
0

您可以將狀態和飛機編號打包在unsigned int中。假設無符號整型是您的平臺

unsigned int myplane; 
int planenumber = (myplane & 0xffff) //can be the plane number 
int booleanstate = ((myplane >> 16) & 0xffff) //can be the boolean state 
2
struct Stuff 
{ 
    unsigned int Boing: 31; 
    unsigned int isFlying: 1; 
}; 

. 
. 
. 

Stuff myStuff; 
myStuff.Boing = 777; 
myStuff.isFlying = false; 

More on bitfields

1

在32位爲什麼不簽上您的整數?正值是飛行的,負值不是,零值是無效的。

0

如何將bitset用作平面編號的bitset索引?如果你不需要更多的狀態,那麼你就完成了。如果你需要的話,你也可以使用每個狀態(例如墜毀,修復需要一個單獨的位矢量,所以你只需要使用一個位,你實際需要的每個平面狀態)

但是我懷疑速度是否是你最關心的問題對付遊戲的圖形和物理會吃掉大部分的CPU時間相比,你的飛機狀態操作。

#include <iostream> 
#include <boost/dynamic_bitset.hpp> 

using namespace boost; 

class State 
{ 
public: 
    State(int nPlanes):_States(dynamic_bitset<>(nPlanes)) 
    { 
    } 

    void SetState(int nPlane, bool bFly) 
    { 
     _States[nPlane] = bFly; 
    } 

    void Dump() 
    { 
     for (boost::dynamic_bitset<>::size_type i = 0; i < _States.size(); ++i) 
      std::cout << _States[i]; 
    } 

private: 
    dynamic_bitset<> _States; 
}; 


int _tmain(int argc, _TCHAR* argv[]) 
{ 
    State planes(500); 
    planes.SetState(0, true); 
    planes.SetState(5,true); 
    planes.Dump(); 

    return 0; 
} 
相關問題