3

このスニペットを理解しようとしています

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

infgame->turnsは整数であり、値が増加し、ブール値であるため、 1 (true) または 0 (false) を返すgame->comp_first方法を教えてください。if ( (game->turns & 1) ^ game->computer_first )私が理解している&のはビット単位の演算子であり、増加する値のようturns & 1に常に 0 を返す場合、この if ステートメントの機能は何ですか? このスニペットを Java で記述する方法はありますか。前もって感謝しますturns(game->turns & 1)

4

3 に答える 3

3

game->turns連続する値を通過するとき、その最後のビットは各反復で 0 と 1 の間で切り替わります。その結果、game->turns & 10 と 1 の間も移動します。結果を bool で XOR すると、bool が false の場合は同じ値が得られ、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

が の場合はシーケンスが 0-1-0-1-0-1 になり、 が の場合は 1-0-1-0-1-0 になることに注意してgame->computer_firstください。falsegame->computer_firsttrue

このスニペットを Java に変換するには、次の結果と比較しgame.turns & 1ます)

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 の場合、1 ^ 1 = 0 であるため、if ステートメントは false を返します。

あなたが私に尋ねると、かなり回り道のように思えます。何が問題なのif (game->turns % 2) != game->computer_firstですか?

于 2012-08-27T13:41:02.597 に答える
0

他の人がすでに指摘しているように、このコードは、数値をインクリメントすると、そのバイナリ表現の最下位ビットがオンとオフを交互に繰り返すという事実に基づいています。

IMO、読みやすさの欠如は、主に大きな問題の兆候です。コードのロジックは実際には最高ではありません。私は少し違うことをするだろうと思います。これは、メンバー関数へのいくつかのポインターが実際に意味をなし、コードをかなり単純化するまれなケースの1つです。

実際の型がわからないので、それgameが型のオブジェクトへのポインタであると仮定しますGame。そこから、1番目と2番目のプレーヤーのメンバー関数へのポインターを定義し、1つの動きではなく、1つの動きのペアで構成されるループを作成するという非常に簡単な問題です(または、視点によっては、実際には1つの動きのようになります)反復ごとの完全な移動)。

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などの低レベル言語に変換するのは簡単です。メンバー関数へのポインターを使用すると最もクリーンな結果が得られることは私には明らかなようですが、それでもこの最後のバージョンは、最初に使用したものよりもかなりクリーンだと思います。

もう1つ詳細を追加する必要があると思います。状況によっては、1人のプレイヤーだけが移動した後にループを終了しなければならない場合があります。実装しているゲームでそれが可能な場合は、次のように2行を変更します。

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

代わりに、各移動関数がブール値を返すようにして、その移動後にさらに再生が可能かどうかを示します。ループ本体は次のようになります。

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