【C++】ビット演算とは?|フラグ管理をゲームで活用する方法

C++

今回は、C++でよく出てくる「ビット演算とは何か」について解説していきます。

「ビット演算って何?」
&|<< の意味がわからない…」
「ゲームのフラグ管理に使うって聞くけど、どう書くの?」

こんな疑問はありませんか?

ビット演算は少し難しく見えますが、「毒・麻痺・炎上」のような複数の状態を1つの整数でまとめて管理できる、ゲームと相性抜群のテクニックです。省メモリで高速なのもうれしいポイントです。

この記事を読み終えると、あなたはビット演算の意味・各演算子の使い方・ゲームのフラグ管理・初心者がハマりやすいミスをしっかり理解できると思いますので、ぜひ最後まで読んでいただけると嬉しいです。

ビット演算とは?

ビット演算とは、数値を2進数(0と1の並び)として見て、各ビットを直接操作する演算のことです。主な演算子は次の通りです。

  • &(AND)… 両方1なら1
  • |(OR)… どちらか1なら1
  • ^(XOR)… 違えば1
  • ~(NOT)… 0と1を反転
  • << / >>(シフト)… ビットを左右にずらす

なぜビット演算が必要?

理由は、複数のON/OFF状態を1つの整数にまとめられるからです。「毒か?」「麻痺か?」を bool 変数でいくつも持つ代わりに、1つの int にビットとして詰め込むことができます。省メモリで、判定も高速です。

実践例:ゲームの状態フラグ管理

状態を 1, 2, 4, 8…2のべき乗で定義するのがポイントです。こうするとビットが重ならず、ORで組み合わせられます。

#include <iostream>

// 2のべき乗で定義(ビットが重ならない)
const int POISON  = 1; // 0001
const int PARALYS = 2; // 0010
const int BURN    = 4; // 0100

int main() {
    int state = 0;

    state = state | POISON; // 毒を付与
    state = state | BURN;   // 炎上も付与

    // 毒かどうか判定
    if (state & POISON) {
        std::cout << "毒状態ですn";
    }
    // 麻痺かどうか判定
    if (state & PARALYS) {
        std::cout << "麻痺状態ですn";
    } else {
        std::cout << "麻痺ではありませんn";
    }
    return 0;
}
毒状態です
麻痺ではありません

| でフラグを立て、& で立っているか調べます。解除したいときは state = state & ~POISON; のように ~(反転)と & を組み合わせます。フラグ定数の作り方は#defineとconstexprの記事も参考になります。

シフト演算でビットを作る

フラグは 1 << n と書くと分かりやすく定義できます。1 << 0 は1、1 << 1 は2、1 << 2 は4です。

const int POISON  = 1 << 0; // 1
const int PARALYS = 1 << 1; // 2
const int BURN    = 1 << 2; // 4

この書き方なら、番号を増やすだけでフラグを追加できて管理がラクになります。

【重要】私が実際にビット演算で困った体験談

個人開発で状態フラグを作ったとき、判定を if (state & POISON) ではなく if (state == POISON) と書いてしまい、毒と炎上が同時に付いた瞬間に「毒じゃない」と誤判定されるバグに悩まされました。

原因は、== だと「毒だけの状態」としか一致しないこと。複数フラグが立っていると値が変わるので通りません。& で「そのビットが立っているか」を見る形に直したら、一発で正しく判定できました。「フラグ判定は &== ではない」と学んだ出来事です。

ビット演算使用時のよくある失敗例と対処法

①フラグ値を1,2,3,4…にする

31|2 と同じでビットが重なります。フラグは必ず 1, 2, 4, 8 の2のべき乗にしましょう。

②判定を == で書く

体験談のとおり、複数フラグ時に誤判定します。判定は if (state & FLAG) を使います。

③演算子の優先順位で括弧を忘れる

&== より優先順位が低いので、if (state & POISON == 0) は意図とズレます。迷ったら括弧で囲むのが安全です。

注意点

  • フラグは 2のべき乗(1 << nで定義する
  • 判定は &、付与は |、解除は & ~
  • 優先順位が不安なときは括弧で明示する

まとめ

  • ビット演算は数値を2進数として各ビットを操作する演算
  • & | ^ ~ << >> がある
  • 複数の状態を1つのintでフラグ管理できる
  • フラグは2のべき乗、判定は & が鉄則

ビット演算は、状態管理を省メモリ・高速に書ける便利な道具です。まずは毒・麻痺・炎上のような状態フラグから、|& を使ってみてください。

関連記事