2009-02-13 13 views
10

Zgodnie z witryną this, chcę reprezentować labirynt z dwuwymiarową tablicą 16-bitowych liczb całkowitych.Jak korzystać z flag bitowych w C++?

Każda 16-bitowa liczba całkowita musi posiadać następujące informacje:

Oto jeden ze sposobów, aby to zrobić (jest to bynajmniej jedyny sposób): siatka 12x16 labirynt może być reprezentowana jako tablica m [ 16] [12] z 16-bitowych liczb całkowitych. Każdy element tablicy będzie zawiera wszystkie informacje dla jednej odpowiedniej komórki w sieci, przy czym bity liczby całkowitej odwzorowanych tak:

alt text http://www.mazeworks.com/mazegen/mazetut/tut5.gif

strącić ścianie ustawienia granicy albo stanowi szczególne ścieżkę wszystko, co musimy zrobić, to odwrócić bity w jednym lub dwóch elementach tablicy.

Jak używać bitowych flag na 16-bitowych liczbach całkowitych, więc mogę ustawić każdy z tych bitów i sprawdzić, czy są ustawione.

Chciałbym zrobić to w łatwy do odczytania sposób (np. Border.W, Border.E, Walls.N, itp.).

Jak to zwykle robi się w C++? Czy używam szesnastkowych znaków do reprezentowania każdego z nich (np. Walls.N = 0x02, Walls.E = 0x04 itd.)? Czy powinienem używać enum?


Zobacz także How do you set, clear, and toggle a single bit?.

Odpowiedz

1

Można to zrobić za pomocą flag szesnastkowych lub wyliczeń, zgodnie z sugestiami, ale najbardziej czytelne/samodzielne dokumentowanie jest prawdopodobnie używać tak zwanych "bitfields" (szczegóły, Google dla C++ bitfields).

3

Używaj stałych heksadecymalnych/wyliczeń i operacji bitowych, jeśli zależy Ci na tym, które konkretne elementy oznaczają.

W przeciwnym razie użyj pól bitowych C++ (pamiętaj jednak, że porządkowanie bitów w liczbie całkowitej będzie zależne od kompilatora).

1

Tak, dobrym sposobem jest użycie szesnastkowego dziesiętnego do przedstawienia wzorów bitowych. Następnie operatory bitowe służą do manipulowania 16-bitowymi intami.

Na przykład:

if(x & 0x01){} // tests if bit 0 is set using bitwise AND 
x ^= 0x02;  // toggles bit 1 (0 based) using bitwise XOR 
x |= 0x10;  // sets bit 4 (0 based) using bitwise OR 
2

nauczyć się bitowe od podmiotów gospodarczych: &, |,^i!.

W górnej części wielu plików C/C++ widziałem flagi zdefiniowane w szesnastkowo, aby maskować każdy bit.

#define ONE 0x0001 

Aby sprawdzić, czy bit jest włączony, ty i to z 1. Aby go włączyć, ty albo ona z 1. Aby włączyć jak przełącznik, XOR go z 1.

9

Jeśli chcesz użyć bitfieldów, to jest prosta droga:

typedef struct MAZENODE 
{ 
    bool backtrack_north:1; 
    bool backtrack_south:1; 
    bool backtrack_east:1; 
    bool backtrack_west:1; 
    bool solution_north:1; 
    bool solution_south:1; 
    bool solution_east:1; 
    bool solution_west:1; 
    bool maze_north:1; 
    bool maze_south:1; 
    bool maze_east:1; 
    bool maze_west:1; 
    bool walls_north:1; 
    bool walls_south:1; 
    bool walls_east:1; 
    bool walls_west:1; 
}; 

Twój kod może przetestować każdy z nich pod kątem prawdziwości lub fałszu.

+0

Niestety nie jest to przenośne, ponieważ kolejność bitów jest specyficzna dla kompilatora. –

+0

Ponadto, nie jestem pewien, czy bool jest obsługiwanym typem dla bitfields, byłby bardziej przenośny, gdyby niepodpisany został użyty. –

+0

yes bool jest obsługiwany dla bitfieldów, ale masz rację, ich zamawianie jest całkowicie zależne od kompilatora i zwykle kojarzone z endianess – KPexEA

2

Aby manipulować zestawy bitów, można również użyć ....

std::bitset<N>

std::bitset<4*4> bits; 
bits[ 10 ] = false; 
bits.set(10); 
bits.flip(); 
assert(!bits.test(10)); 
0

Nie jestem wielkim fanem bitset. To jest po prostu więcej pisania w mojej opinii. I nie ukrywa to, co robisz. Nadal musisz & & & | bity. Chyba, że ​​wybierasz tylko 1 bit. To może działać dla małych grup flag. Nie musimy też ukrywać tego, co robimy. Jednak celem zajęć jest zazwyczaj ułatwienie użytkownikom. Nie sądzę, żeby ta klasa to osiągnęła.

Załóżmy na przykład, że masz system flag z flagami .64. Jeśli chcesz przetestować ... Nie wiem .. 39 z nich w 1, jeśli stwierdzenie, czy wszystkie są na ... przy użyciu bitfieldów to ogromny ból. Musisz wpisać je wszystkie .. Kurs. Zakładam, że używasz funkcji bitfields, a nie mieszania i dopasowywania. To samo z bitsetem. Chyba że brakuje mi czegoś z klasą ... co jest całkiem możliwe, ponieważ rzadko go używam .. Nie widzę sposobu, aby przetestować wszystkie 39 flag, chyba że wpiszesz dziurę lub uciekniesz się do "standardowych metod" (używając lista flag enum lub określona wartość dla 39 bitów i użycie operatora bitów & &). To może zacząć się brudzić w zależności od twojego podejścia. I wiem ... 64 flagi brzmią bardzo. I dobrze. To jest ... w zależności od tego, co robisz. Osobiście większość projektów, w które zaangażowałem się, zależy od systemów flag. Więc tak naprawdę ... 64 nie jest tak niespotykane. Chociaż 16 ~ 32 jest dużo bardziej powszechne w moim doświadczeniu. Naprawdę pomagam obecnie w projekcie, w którym jeden system flag ma 640 bitów. To w zasadzie system przywilejów. Więc ma sens uporządkowanie ich wszystkich razem ... Jednak .. co prawda .. Chciałbym to trochę przerwać ... ale ... eh ... Pomagam ... nie tworzyć.