1

私はビット単位の操作をいじっていて、キツネ (オオカミ)、ニワトリ (ガチョウ)、穀物 (トウモロコシ)、そして川を渡ろうとしている人がいる単純なロジック パズルを実装したいと考えていました。それぞれの最初の 4 ビットを使用して、川のどちら側にいるかを表しています。

ロジックを実装するのに少し苦労しています。

2 つのビットが 1 または 0 であり、1 と 0 ではないことを確認するにはどうすればよいですか?

int game()
{
    int state = 0;
    int done = 0;
    while (!done)
    {
        int input = 0;
        input = move();

        /*
           0000 0000
                |||\_grain
                ||\__chicken
                |\___fox
                \____person
           0 = left side of the river
           1 = right side
        */
        if (input == 3)// Moves person and grain
        {
            // Move the grain if the person is on the same side.
            if (!(state & 1 << 3 ^ state & 1<< 0))
            {
                state ^= 1 << 3;
                state ^= 1 << 0;
            }
            else
            {
                // Always switch the person no matter what
                state ^= 1 << 3;
            }
        }
        else if (input == 2) // Moves person and chicken
        {
            // Move Chicken only if person is on the same side
            if (!(state & 1 << 3 ^ state & 1<< 1))
            {
                state ^= 1 << 3;
                state ^= 1 << 1;
            }
            else
            {
                // Always switch the person no matter what
                state ^= 1 << 3;
            }
        }
        else if (input == 1)// Moves person and fox
        {
            // Move the fox if the person is on the same side.
            if (!(state & 1 << 3 ^ state & 1<< 2))
            {
                state ^= 1 << 3;
                state ^= 1 << 2;
            }
            else
            {
                // Always switch the person no matter what
                state ^= 1 << 3;
            }
        }

        // Fox and Chicken on one side and person on the other = lost
        if ((state & 1 << 2 && state & 1 << 1) && ~(state & 1 << 3))
        {
            printf("Failed\n");
        }
    }
    return 1;
}

ビットごとのチェックはよりエレガントなコードになると思いますが、それはもっと面倒なようです。ビットごとのロジックで頭を壁にぶつけてうんざりすると、いつもこれをやってしまいます。

int game()
{
    int state = 0;
    int done = 0;
    while (!done)
    {
        int input = 0;
        input = move();

        /*
           0000 0000
                   | | | \_grain
                   | | \__chicken
                   | \___fox
                   \____person
           0 = left side of the river
           1 = right side
        */
        if (input == 3)// Moves person and grain
        {
            // Are they on the same side?
            if (state == 9 || state == 11 || state == 13 || state == 15 ||
                state == 0 || state == 2 || state == 4 || state == 6)
            {
                // Move the person and grain
                state ^= 1 << 3;
                state ^= 1 << 0;
            }
            else
            {
                state ^= 1 << 3;
            }
        }
        else if (input == 2) // Moves person and chicken
        {
            // Are they on the same side?
            if (state == 10 || state == 11 || state == 14 || state == 15 ||
                state == 0 || state == 1 || state == 4 || state == 5)
            {
                // Move the person and chicken
                state ^= 1 << 3;
                state ^= 1 << 1;
            }
            else
            {
                state ^= 1 << 3;
            }
        }
        else if (input == 1)// Moves person and fox
        {
            // Are they on the same side?
            if (state == 12 || state == 13 || state == 14 || state == 15 ||
                state == 0 || state == 1 || state == 2 || state == 3)
            {
                // Move the person and fox
                state ^= 1 << 3;
                state ^= 1 << 2;
            }
            else
            {
                state ^= 1 << 3;
            }
        }
        else
        {
            // Always switch the person no matter what
            state ^= 1 << 3;
        }

        //Check if you won or lost
        if (state == 3 || state == 6 || state == 8 || state == 9 || state == 12) // Lost
        {
            return 0;
        }
        if (state == 15) // Won
        {
            return 1;
        }
    }
    return 1;
}
4

3 に答える 3

2

Cは、ゼロ以外である限り、ifステートメントの条件をtrueと評価します。

XOR演算子(^)は、ビットが設定されているかどうかをテストするために使用するものではない可能性があります。たとえば、次のようになります。

// Move the grain if the person is on the same side.
if (state ^ 1 << 3 && state ^ 1 << 0)

この場合の状態変数は、intのサイズを無視し、のビットマスクを使用して失敗するはずだと仮定しましょう1110 0001。これにより、人は川の高次側に配置され、穀物は低次側に配置されます。

ifステートメントの最初の条件であるstate ^ 1 << 3、は、の一時マスクを作成します1110 1001。2番目の状態^1<< 0は、のビットマスクを作成します1110 0000。これはナンセンスであり、あなたが望むものではありません。

したがって、失敗したい入力(1110 0001)が与えられた場合、このifステートメントは次のようになります。

if ( 0b11101001 && 0b11100000 )

どちらが成功するか(これは悪いことです)。

おそらくやりたいことは、穀物と人の両方が「川」の右側、それぞれの場所(1<<3と1<<0)にあることを確認することです。自由に使える最良のビット演算子はAND演算子です。

これは宿題の問題のようなにおいがするので、あなたの質問に完全に答えるには至りません。しかし、ここでは、正しい方向を示すのに十分なコンテキストを持っている必要があります。

于 2012-09-18T02:09:23.657 に答える
2

2 つのビットが 1 または 0 であり、1 と 0 ではないことを確認するにはどうすればよいですか?

それらを同等に比較してみてはどうでしょうか。

#define MAN_MASK   (1<<3)
#define GRAIN_MASK (1<<0)

if(  
     ((state & MAN_MASK) == 0)
            == 
     ((state & GRAIN_MASK) == 0)
  );
于 2012-09-18T01:54:10.443 に答える
1

2つのビットが同じ状態にあるかどうかを確認するには、一方のビットをもう一方のビットの位置にシフトし、ビットが位置をXOR示しANDていることを確認して、結果がゼロであることを確認します。たとえば、ビット1がビット3と同じであることを確認するには、次のようにします。

// Shift bit 3 to position 1, XOR, mask with 2, and check for zero
if ((2 & ((state >> 2) ^ state)) == 0) {
    ...
}
于 2012-09-18T02:03:51.697 に答える