2

我在游戏中使用代表一堆飞机的无符号整数。每架飞机都有两种状态,飞行和停飞。我想将此状态与飞机编号一起存储。实现这一目标的“最佳”方法是什么?我可以将 std::maps 与飞机及其状态一起使用,但这似乎有点矫枉过正而且速度很慢。可以使用位标志来完成吗?测试的分配和测试应该很快。

伪代码:

unsigned int Boing = 777;

if( Boing is flying)
 set some bit;

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

任何关于简单快速技术的提示都值得赞赏!

4

9 回答 9

2

The fastest and cleanest way is probably to avoid bitfields, and simply define a struct:

struct Plane
{
    bool isFlying;
    unsigned int number;
}

...


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

This method will use more memory than trying to cram the flag into the same word, but will take less work to get/set the fields. Unless you're memory-constrained, I would strongly recommend avoiding trying to pack everything tightly.

You could even consider using an enum rather than a bool for the state.

于 2011-11-07T19:39:58.697 回答
2

One simple way would be to just make the number negative if not flying.

于 2011-11-07T19:42:20.170 回答
2
struct Stuff
{
  unsigned int Boing: 31;
  unsigned int isFlying: 1;
};

.
.
.

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

更多关于位域

于 2011-11-07T19:48:11.860 回答
1

假设您从不使用 unsigned int 中可用的全部值(合理的可能性,但远非绝对确定),您可以将范围限制为比 unsigned in 包含少一位,然后使用最高有效位存储“飞行”状态。在这种情况下,您可以执行以下操作:

// 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
于 2011-11-07T19:45:48.960 回答
1

为什么不只是签署你的整数?正值飞行,负值不飞行,零无效。

于 2011-11-07T19:58:09.133 回答
0

Use a struct or a class to combine the information "number" and "state", and whatever else you want a plane to be. If you use bit operations on the int (which is possible, just not advisable), changing the state would change the actual number of your plane.

于 2011-11-07T19:41:33.440 回答
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

PS如果有人想告诉我“不不!不要使用宏,这是C++,使用我写的这个过于复杂的东西”,省着气。只需给出 -1 并继续。

编辑:我上面写的是你的问题的答案:“如何使用符号位作为标志”。如果您想以更好的方式执行此操作,但不扩展内存使用量(通过添加 a bool),您可以随时编写如下内容:

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

airplane Boing = {777, false};

然后,分配和读取idis_flying执行位操作,但它们由编译器处理。

于 2011-11-07T19:43:57.033 回答
0

您可以将州和飞机号打包在unsigned int中。假设 unsigned int 在您的平台上是 32 位的

unsigned int myplane;
int planenumber = (myplane & 0xffff ) //can be the plane number
int booleanstate = ((myplane >> 16) & 0xffff) //can be the boolean state
于 2011-11-07T19:46:16.920 回答
0

使用位集索引作为平面编号的位集怎么样?如果您不需要更多状态,那么您就完成了。如果您需要,您还可以为每个状态使用(例如,崩溃、修复需要一个单独的位向量,因此您对实际需要的每个平面状态只使用一个位。

但我怀疑,如果您处理游戏图形和物理将占用您的大部分 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;
}
于 2011-11-07T20:14:11.310 回答