条件语句上的按位和异或

时间:2012-08-27 13:35:04

标签: c++ if-statement bit-manipulation

我正在尝试理解这个片段

for (; game->boxes_left > 0; game->turns++)
      {
      if ( (game->turns & 1) ^ game->computer_first )
         game->human_move();
      else
         game->computer_move();
      }

因为inf game->turns是一个整数,它的值越来越大,而game->comp_first是一个布尔值,有人请告诉我if ( (game->turns & 1) ^ game->computer_first )如何将它返回1(真)或0(假的)? 因为我理解&是按位运算符,而当turns & 1它总是返回0,因为turns是一个递增的值,{if {1}}在这个if语句中的作用是什么?有没有办法在java中编写这个片段。提前致谢

3 个答案:

答案 0 :(得分:3)

game->turns经历连续值时,其最后一位在每次迭代时在0和1之间切换。结果,game->turns & 1也介于0和1之间。如果bool为假,则使用bool对结果进行异或,给出相同的值,如果bool为真,则为反转值。

game->turns   Last bit   XOR 0    XOR 1
-----------   --------   -----    -----
          0          0       0        1
          1          1       1        0
          2          0       0        1
          3          1       1        0
          4          0       0        1
          5          1       1        0

注意game->computer_firstfalse时序列为0-1-0-1-0-1,game->computer_first为1-0-1-0-1-0是true

要将此代码段转换为Java,请将game.turns & 1的结果与)进行比较:

if (((game.turns & 1) != 0) ^ game->computer_first) ...

答案 1 :(得分:2)

game-> turn& 1对于游戏的每个值都将返回true - >转为奇数。 E.g:

turns= 0x00001111
one=   0x00000001
result=0x00000001

因为两个值的最右边的位都是“1”。如果computer_first也是“1”,例如true,if语句将返回false,因为1 ^ 1 = 0。

如果你问我,看起来像是一种相当迂回的做事方式。问题与if (game->turns % 2) != game->computer_first有什么关系?

答案 2 :(得分:0)

正如其他人已经指出的那样,这段代码是基于这样一个事实:当你递增一个数字时,它的二进制表示的最低有效位在on和off之间交替。

IMO,缺乏可读性主要是一个更大问题的症状:代码的逻辑并不是最好的。我想我的做法有点不同。这是一个极少数情况,其中一些指向成员函数的指针真正有意义并且简化了代码。

由于我不知道实际的类型,我将假设game是指向Game类型的对象的指针。从那里开始,定义指向第一个和第二个玩家的成员函数的指针,然后编写一个由一对移动而不是单个移动组成的循环(或者,根据您的观点,更像是一个每次迭代完成移动。)

typedef void (Game::*pmf)();

pmf first_player = &Game::human_move;
pmf second_player = &Game::computer_move;

if (game->comp_first)
    std::swap(first_player, second_player);

for ( ; game->boxes_left > 0; game->turns+=2) {
    game->*first_player();
    game->*second_player();
}

不幸的是,虽然这使得代码更简洁,更简单,但它也使得转换为Java变得更加困难 - Java没有直接模拟C ++指向成员函数的指针。通常的替代方法是定义一个接口,然后是一个实现该接口的匿名类。在你完成所有这些之前,从一些代码重复的东西开始可能更简单:

if (game->comp_first)
    for (; game->boxes_left > 0; game->turns+=2) {
        game->computer_move();
        game->player_move();
    }
else
    for (; game->boxes_left > 0; game->turns+=2) {
        game->player_move();
        game->computer_move();
    }

...由于此代码不使用任何高级功能,因此将其转换为Java等低级语言应该相当简单。对我来说,使用指向成员函数的指针给我看起来很明显,它提供了最干净的结果,我仍然认为最后一个版本比你开始时更清晰。

我想我应该再添加一个细节。根据具体情况,您可能必须在只有一名玩家移动后退出循环。如果这对你正在实施的任何游戏都有可能,你可以改变这两行:

game->*first_player();
game->*second_player();

而是让每个move函数返回一个布尔值,指示在该移动之后是否仍然可以进一步播放,并且你的循环体将变成类似:

if (game->*first_player())
    game->*second_player();