对条件语句执行逐位AND XOR

Bitwise AND XOR on conditional statement

本文关键字:AND XOR 执行 条件 语句      更新时间:2023-10-16

我正在努力理解这个片段

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(true)或0(false)吗?因为我所理解的&是逐位运算符,当turns & 1时,它总是返回0,因为turns是一个递增值,那么(game->turns & 1)在这个if语句中的函数是什么?有没有任何方法可以用java编写这个片段。提前感谢

game->turns遍历连续值时,其最后一位在每次迭代中在0和1之间切换。结果,game->turns & 1也在0和1之间。如果bool为false,则将结果与bool进行异或运算,如果bool是true,则将得到相反的值。

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_firsttrue时,序列如何进行1-0-1-0-1-0的。

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

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

game->回合数&对于每一个奇数的game->回合值,1将返回true。例如:

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

因为对于这两个值,最右边的位都是"1"。如果computer_first也是"1",例如true,则If语句将返回false,因为1^1=0。

如果你问我的话,这似乎是一种相当迂回的做事方式。if (game->turns % 2) != game->computer_first怎么了?

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

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();