1

我在搞乱按位运算,想实现一个简单的逻辑难题,你有一只狐狸(狼)、鸡(鹅)、谷物(玉米)和一个试图过河的人。我使用每个位的前 4 位来表示它们在河的哪一侧。

我在尝试实现逻辑时遇到了一些麻烦。

如何检查这两位是 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

如何检查这两位是 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 回答
2

只要 if 语句的条件不为零,C 就会将 if 语句的条件评估为真。

XOR运算符( ^) 可能不是您想要用来测试是否设置了位的对象,例如这里:

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

让我们假设在这种情况下状态变量应该失败,忽略 int 的 sizeof,并使用1110 0001. 这将人放在河流的高阶一侧,谷物位于低阶一侧。

if 语句的第一个条件state ^ 1 << 3, 将创建一个临时掩码1110 1001. 第二个,state ^ 1 << 0,将创建一个位掩码1110 0000。这是胡说八道,不是你想要的。

因此,给定您希望失败的输入 ( 1110 0001),此 if 语句类似于:

if ( 0b11101001 && 0b11100000 )

哪个成功(这很糟糕。)

您可能想要做的是确保谷物和人都在“河”的右侧,在各自的位置( 1 << 3 和 1 << 0 )。最好的按位运算符是AND运算符。

这闻起来有点像家庭作业问题,所以我不会完全回答你的问题;但是你应该有足够的上下文来让自己指向正确的方向。

于 2012-09-18T02:09:23.657 回答
1

要检查两个位是否处于相同状态,请将其中一个位移动到另一个位的位置,将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 回答