6

手続き型生成のダンジョンを作成するゲームに取り組んでいるときに、ビットマスキングを使用して部屋番号やドアのタイプなどを取得する例を見つけました。

この例では、彼はビットマスクを使用して、各タイルの整数から詳細を取得します。整数はこのように分解されます

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は実際には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の理由を説明できますか?

4

3 に答える 3

10

あなたがしているのはビット単位の算術です。今のところ上位ビットは無視し(すべて0であるため)、2つの16進値0xFFC0とを単純に考慮します0x12F0。次に、はbitwise and10進数の乗算とまったく同じように機能します。ビットレベルでは次のようになります。

0xFFC0 = 1111111111100000

0x12F0 = 0001001011110000

これは次のようになります0001001011100000 = 0x12F0

16進バイナリとの間で変換するための秘訣はこれです。2桁ごとに1バイト(つまり8ビット)です。たとえば、0xFFは1バイトです。したがって、各16進数(つまり0xF (base-16) = 1111 (base-2) = 15 (base-10))のビット値を書き込むだけで、これを2進表現に変換できます。各バイトは常に正確に8ビットであることがわかっているため、各16進数は独自の4ビットの2進表現に変換されます。次に、16進値0000(0)から1111(F)のバイナリ表現を記憶し、それらを適切に置き換えるだけです。トリックは両方向で機能します。

ビットマスクに関する限り、これはビットベクトルから値を抽出するのに単純に役立ちます。ビットベクトルは(通常)単純なデータ型(つまりintcharなど)です。次に、特定の各ビットは、有効または無効にする値のタイプを示します。したがって、のビットベクトル(char = 1バイト、たとえばビットベクトルのこのデータ型を検討してください)が0x01あり、最下位ビットがドアが有効になっていることを示している場合、このビットベクトルにはドアがあります。私のビットベクトルの値が0x02である場合、ドアは有効になっていません(ただし、0x03ドアはあります)。どうしてこれなの?ビットベクトル/ビットマスクを完全に理解するには、基礎となるバイナリ表現を常に確認する必要があります。

0x01 = 00000001、、0x02 = 00000010_0x03 = 00000011

ご覧のとおり、1番目と3番目の値には、最下位ビットが設定されています。ただし、2番目の値では、2番目の最下位ビットが設定されますが、最下位ビットは設定されません。ただし、この2番目の値を使用して、別のプロパティを示すことができます(ただし、例として、2番目の値にはドアがありません)。

次に、上記のようにフォーマットされたビットベクトルからドアを取得するための対応するビットマスク(偶然に)は、、、および(再び、バイナリ表現に戻って乗算する)からであることに注意してください0x010x01 & 0x01 = 10x02 & 0x01 = 00x03 & 0x01 = 1

于 2012-08-18T19:12:35.993 に答える
5

16進数だけでなく、2進数にも注意してください。 C16進数は12、10進数は11002進数です。Fは1111バイナリです。それで

F&1 == 1、F&2 == 2、C&F == C、0&0==0。

于 2012-08-18T19:02:52.053 に答える
1

0xFすべての1ビットです:1111任意の値のビットごとのANDであり、同じ値です。つまり、特定の位置にあるANDは、他のオペランドのビットを保持します。0xF0xF

したがって、0x0000FFC0 & 0x000012F0では、F数字は対応する数字を保持しています。

0xF & 0x1 = 0x1
0xF & 0x2 = 0x2
0xC & 0xF = 0xC

同様に:

0xFFC0 & 0x12F0 = 0x12C0

ご存知かもしれませんが、任意の値のビットごとのAND0はです0。したがって、のような構文は、最下位2番目のバイトのみ0x0000FF00を保持するために使用されます。

の使用法は、0xFFC0実際には、コードの残りの部分がその最下位バイトをどのように使用しているかによって異なります。フラグの説明では、最下位バイトの上半分は次のように文書化されています。部屋への入り口。どういうわけかそれはで重要ですSystem.out.println(map[x][y] & $ROOM_ID);

0xC1100バイナリであるため0xC00xFFC0マスクに含めることにより、コードはその最下位(右端)バイトの最上位2ビットも保持しようとします。これらの2ビットでは、正確に4つの値をエンコードできることに注意してください。これは、ゲームが2Dで、各部屋が正方形のZorkスタイルである場合、4つのコンパスポイントで可能な入り口を備えたゲームデザインと一致します。

ビットマスクのルールについてはウィキの記事から始めるよりも悪いことをする可能性があります。それは基本をかなりうまくカバーしています。最終的に、これはすべてブール代数です。

于 2012-08-18T19:10:38.983 に答える