[英]What are the rules for bitmasks? Like 0xFF vs. 0xFC
我正在制作一个创建程序生成的地牢的游戏,我找到了一个使用位掩码来检索房间号和门类型等内容的例子。
在该示例中,他使用位掩码从每个图块的整数中提取细节。 并且整数被这样分解
0xLLSDRRET
L - is the Level Number
S - Denotes a special tile(Like Stairs)
D - is if its a door, and what type(Door, Arch, Trapped)
R - Room number
E - Flags an entrance to a room
T - Names the type of tile(Floor, Cooridor, Blocked)
在这里,他使用一个位掩码来获取,例如,房间号码,如:
int[][] map = new int[40][40]
int $ROOM_ID = 0x0000FF00;
System.out.println(map[x][y] & $ROOM_ID);
现在有了这个,如果map [x] [y]是例如0x00001200,那么输出将是1200.我知道这部分面具。
但在源$ ROOM_ID是ACTUALLY 0x0000FFC0,我不明白C做什么,因为我尝试了不同的值,我似乎无法抓住C做的,例如
0x00001200 output-> 1200
0x00001210 output-> 1200
0x00001220 output-> 1200
0x00001230 output-> 1200
0x00001240 output-> 1240
0x00001250 output-> 1240
0x00001260 output-> 1240
0x00001270 output-> 1240
0x00001280 output-> 1280
0x00001290 output-> 1280
0x000012A0 output-> 1280
0x000012B0 output-> 1280
0x000012C0 output-> 12C0
0x000012D0 output-> 12C0
0x000012E0 output-> 12C0
0x000012F0 output-> 12C0
有更多位掩码知识的人可以解释为什么0x0000FFC0和0x000012F0 = 12C0?
你正在做的是按位算术。 暂时忽略高位(因为它们都是0)并且只考虑两个十六进制值0xFFC0
和0x12F0
。 然后bitwise and
基数10中的乘法完全相同。它在位级上看起来像这样:
0xFFC0 = 1111111111100000
&
0x12F0 = 0001001011110000
然后等于0001001011100000 = 0x12F0
转换为十六进制二进制的技巧就是这个。 每两个十六进制数字是一个字节(即8位)。 例如, 0xFF
是单个字节。 因此,您可以通过简单地为每个十六进制数字写入位值(即0xF (base-16) = 1111 (base-2) = 15 (base-10)
)将其转换为二进制表示。 由于我们知道每个字节总是精确为8位,因此每个十六进制数字都会转换为自己的4位二进制表示。 然后,您只需要记住十六进制值0000
(0)到1111
(F)的二进制表示,并适当地替换它们。 这个技巧在两个方向都有效。
就位掩码而言,这对于从位向量中提取值非常有用。 bitvector(通常)是一种简单的数据类型(即int
, char
等)。 然后,每个特定位表示要启用或禁用的值类型。 因此,如果我有一个位向量(char =单字节,所以请考虑这个数据类型为bitvector,例如) 0x01
而我的最低位表示门已启用,则此位向量有一个门。 如果我的bitvector的值是0x02
,那么没有门启用(但在0x03
有一扇门)。 为什么是这样? 您需要始终查看基础二进制表示以完全理解位向量/位掩码。
0x01 = 00000001
0x02 = 00000010
0x03 = 00000011
如您所见,在第一个和第三个值中,设置了最低位。 但是,在第二个值中,设置第二个最低位,但不是最低位。 但是,您可以使用此第二个值来表示另一个属性(尽管出于示例的目的,第二个值中没有门)。
然后注意,从上面格式化的位向量中检索门的相应位掩码(巧合)将是0x01
因为0x01 & 0x01 = 1
1,0x02 0x02 & 0x01 = 0
,以及0x03 & 0x01 = 1
(再次,返回二进制表示和乘)
注意二进制,而不仅仅是十六进制。 十六进制中的C
是十进制的12是二进制的1100
; F是二进制的1111
。 所以
F&1 == 1,F&2 == 2,C&F == C,0&0 == 0。
0xF
是1
位: 1111
。 任何值的按位AND和0xF
是相同的值。 换句话说,给定位置的带有0xF
的AND 保留来自另一个操作数的位。
所以在0x0000FFC0 & 0x000012F0
, F
数字保留相应的数字:
0xF & 0x1 = 0x1
0xF & 0x2 = 0x2
0xC & 0xF = 0xC
同理:
0xFFC0 & 0x12F0 = 0x12C0
您可能知道,任何值的按位AND和0
都是0
。 因此,像0x0000FF00
这样的结构仅用于保留第二个最低有效字节。
0xFFC0
的使用实际上取决于其余代码如何使用该最低有效字节。 在标志的解释中,最低有效字节的上半部分记录为: 房间的入口 。 不知何故,这在System.out.println(map[x][y] & $ROOM_ID);
。
0xC
是二进制的1100
,因此通过在0xFFC0
掩码中包含0xC0
,代码也试图保留该最低有效位的两个最高有效位 - 最右边 - 字节。 请注意,在这两个位上,您可以精确编码4个值。 如果游戏是2D并且每个房间都是Zork风格的正方形,那么这就与4个罗盘点上的入口相匹配。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.