2012-02-05 72 views
3

我的问题似乎有点业余,但我无法在任何地方找到答案。一段时间以前,“Minecraft”的一位开发人员谈到了门在游戏中的存储方式(link)。他说他们使用4位存储。 2表示定位,1表示如果它是上部或下部,一个表示打开或关闭。这让我想到你是如何做到的。您看到存储一个字节,因为一个ASCII字符是一个字节。但是,您不能只将一些字符写入仅有一点的文件中,因为字符不能只存储一位,而是作为一个字节存储。我知道有一点表示为1或0.然而,将1或0写入文件将会给你4个字节,而不是一个位。那么这是如何完成的?存储单个位

谢谢。

+1

它是通过bitpacking完成的,将各种信息放入单个字节的数据中。 – Alastair 2012-02-05 02:02:19

+0

http://en.wikipedia.org/wiki/Bitwise_operation – 2012-02-05 02:06:04

回答

2

这很可能是通过组合不同的二进制标志来完成。为了能够给你一个清晰的解释,你必须了解数字如何按位表示。基本上,它就像十进制数字一样,只有两个数字可用。下面是一个例子(二进制表示中的十进制数字0-16)。

Decimal  Binary 

0   0 
1   1 
2   10 
3   11 
4   100 
5   101 
6   110 
7   111 
8   1000 
9   1001 
10   1010 
11   1011 
12   1100 
13   1101 
14   1110 
15   1111 
16   10000 

这正是您的电脑如何存储数字。 你还必须得到一个关于按位运算符的基本认识。 假设你有8位的两行看起来是这样的:

10101010 
01011111 

如果您在使用逐位或操作结合这两个行 - “|” - 输出的比特x是1,如果其中第1行的位x是1或第2排的位x为1。因此,在我们的情况下,结果是这样的:

11111111 

按位与运算符( &)检查两排1的比特x是1,行2的比特x是1。 在我们的这种情况下是输出:

00001010 

的逐位XOR(异或)运算符(^)检查是否我们的输出如下:

11110101 

基本上Minecraft的开发者所做的是他们定义了几个标志。

// this is just an example, not Minecraft's actual code 

public static final byte ORIENTATION_SOUTH = 0; // 00000000 
public static final byte ORIENTATION_NORTH = 1; // 00000001 
public static final byte ORIENTATION_WEST = 2; // 00000010 
public static final byte ORIENTATION_EAST = 3; // 00000011 

public static final byte PART_UPPER = 4;  // 00000100 - third bit is 1 
public static final byte PART_LOWER = 0;  // 00000000 - third bit is 0 

public static final byte STATE_OPEN = 8;  // 00001000 - fourth bit is 1 
public static fianl byte STATE_CLOSED = 0;  // 00000000 - fourth bit is 0 

所以,如果他们想在门的上部朝西,是一个车门开着状态,他们会写这样的:

byte state = ORIENTATION_WEST | PART_UPPER | STATE_OPEN; 

位明智的,它应该是这样的:

00000010 | (orientation) 
00000100 | (part) 
00001000 (open or closed) 

,然后这些最终成为:

00001110 (west, upper part, open) 

虽然只有字节的前4位被使用,正如你所说的,你不能只保存位。最有可能的是整个字节被保存。

1

定义:

DOOR_UP = 0x01 
DOOR_LEFT = 0x02 
DOOR_BIG = 0x04 
DOOR_SMALL = 0x08 
DOOR_RED = 0x10 
DOOR_BLUE = 0x20 
DOOR_GREEN = 0x40 

如果你需要离开,小,绿色的门写

def door := DOOR_LEFT or DOOR_SMALL or DOOR_GREEN (Z** or some generic language) 
byte door = DOOR_LEFT | DOOR_SMALL | DOOR_GREEN; (C++) 

是检查门绿色 “问”:

door & DOOR_GREEN 

零表示不绿色。非零(实际上,DOOR_GREEN)是指绿色的门

增加:

你甚至可以包0-7两个数字中的一个字节。同样的想法是在ZX频谱(1982)用来定义字符的颜色:

Xbbbfff (bbb - background color, fff - foreground color, X - for blink) 

要设置BKG色5和FGD 4使用:

color = 5 << 3 | 4 

要获得背景色用途:

(color >> 3) & mask(0x7) -> 5 

如果你每制作一个游戏都很重要。尽量避免使用位操作,只要你可以:)

1

你是对的,当你需要的只是存储一个位时,你不能这样做:你必须至少保存一个字节。

但是,如果您有多个项目,每个项目占用少于一个字节,您可以将多个项目组合在一个字节中。

以4位门为例,假设您要存储两扇门的信息。你需要8位,这是一个字节。您可以将第一个门保存在较低的四位中,第二个门保存在较高的四位中。当您需要获得第一个门的状态时,通过应用twoDoorsInOneByte & 0x0F操作屏蔽掉第二个门:它删除字节的较高部分。当你需要第二扇门时,使用左移位移位:(twoDoorsInOneByte >> 4) & 0x0F:它将高四位移动到高四位,并且清除字节上半部分的位,以防你的值感叹 - 延长。

最后,在C中你有另一种选择:你可以使用bit fields。如果您想将任意长度的元素打包成几个字以节省空间,这可能很有用。请注意,当节省相对较高或存储器太细时(例如,您正在为8位微控制器编写嵌入式代码)时,应谨慎应用此技术。

0

尽管他们说他们使用4位,但我知道他们实际上是将信息存储在一个字节中(这很容易创建,因为字节是一种基本数据类型)。

我不认为有可能直接存储一个位,但我想你想知道,尽管他们声称他们使用4位,但这些位存储在一个字节中。

0

几乎所有的现代计算机都是字节可寻址的,这意味着您只能寻址(指向)一个字节的内存并且不会更小。所以在这种情况下,他们正在存储一个字节。为了让在钻头他们关心他们使用位操作来操纵字节:

const int OPEN_CLOSE_BIT = 1 << 0; 
const int UPPER_LOWER_BIT = 1 << 1; 

byte doorByte = getByteFromSomewhere(); 

if (doorByte & UPPER_LOWER_BIT) { 
    // the door is in some state 
}