3

我试图理解这个片段

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

因为 infgame->turns是一个整数,并且它具有递增的值,并且game->comp_first是一个布尔值,所以有人请告诉我如何if ( (game->turns & 1) ^ game->computer_first )返回它是 1 (true) 或 0 (false) 吗?因为我理解&的是按位运算符,当turns & 1它总是返回 0 时,作为turns一个递增的值,(game->turns & 1)这个 if 语句的功能是什么?有什么办法可以用java编写这个片段。提前致谢

4

3 回答 3

3

game->turns遍历连续值时,它的最后一位在每次迭代时在 0 和 1 之间切换。结果,game->turns & 1也介于 0 和 1 之间。如果 bool 为假,则用 bool 对结果进行 XOR 运算会得到相同的值,如果 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

请注意序列在 is 时如何变为 0-1-0-1-0-1 ,而在is时game->computer_firstfalse1-0-1-0-1-0 。game->computer_firsttrue

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

if (((game.turns & 1) != 0) ^ game->computer_first) ...
于 2012-08-27T13:38:35.347 回答
2

game->turns & 1 将为每个奇数的 game->turns 值返回 true。例如:

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

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

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

于 2012-08-27T13:41:02.597 回答
0

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

IMO,缺乏可读性很大程度上是一个更大问题的症状:代码的逻辑并不是最好的。我想我会做一些不同的事情。这是少数几个指向成员函数的指针真正有意义并大大简化代码的情况之一。

由于我不知道实际的类型,我将假设它game是一个指向 type 对象的指针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 之类的低级语言应该相当简单。在我看来,使用指向成员函数的指针可以得到最干净的结果,我仍然认为最后一个版本比你开始的版本要干净得多。

I suppose I should add one more detail. Depending on the situation, it's possible that you may have to exit the loop after only one player has made a move. If that's possible for whatever game you're implementing, you'd change the two lines like this:

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

and instead have each of the move functions return a boolean indicating whether further play remains possible following that move, and your loop body would become something like:

if (game->*first_player())
    game->*second_player();
于 2012-08-27T14:40:54.207 回答