3

CS 教育の一環として、Ruby/EventMachine に基づく TCP サーバーによってリンクされたクライアントを使用して、ゲーム イベントを表す JSON メッセージがやり取りされるマルチプレイヤー Android yatzy ゲームを構築中です。

しかし、ゲーム ターン管理をどのように最適に処理するかについて、私は確信が持てません。

典型的なヤッツィー ゲームは 15 ラウンドで構成されます。私の実装では、最大 4 人のプレーヤーを処理します。サイコロのロール、サイコロのホールド、スコアの選択などのイベントは、Ruby サーバーに送信され、他のプレイヤーにブロードキャストされます。

現在、私のサーバーはゲーム ターンを処理しています。クライアントから新しいスコアの選択肢を受け取るたびに、スコアを他のクライアントにブロードキャストします。続いて、次にサイコロを振るプレイヤーのユーザー ID を含むメッセージをブロードキャストします。

私はシステムが脱落したプレイヤーを処理できるようにしたいと考えています。解決策を思いつきましたが、それが理想的であるとは確信が持てません。

@turnfiber = Fiber.new do
  15.times do
    @players.each do |key, value|
      Fiber.yield value
    end
  end
end

@turnfiber実行中のゲームを表すゲームオブジェクトに属するインスタンス変数です。@playersプレーヤーの一意の ID をキーとして使用し、対応するプレーヤー オブジェクトを値として使用するハッシュです。

@turnfiber.resumeターンが終了するたびに (スコアの選択の提出を通じて) 呼び出され、サイコロを転がす次のプレーヤーを取得し、サイコロを振る許可をブロードキャストします。プレイヤーがターン 4 でゲームを離れた場合、クライアントは終了メッセージを送信して、去るプレイヤーを@playersハッシュから削除し、彼の離脱をブロードキャストし、プレイヤーがハッシュに存在しなくなったため、@players後続の反復を防止するという考え方です。サイコロのコントロールを「死んだ」プレーヤーに渡すことから、デッドロックを回避します。これまでのところ、私の Android クライアントは不完全なので、この理論が実際に実際に機能するかどうかはまだテストしていません。

私がファイバー クラスを選択したのは、 を 15 回繰り返し@playersてサイコロを 1 つずつ振らせたいという欲求に基づいています。ファイバーは、呼び出されるたびにループを一時停止しyieldてプレーヤーを返すため、これを可能にします。

このアプローチについて、特にどのような弱点があるか、ターン管理の問題を解決するために検討すべき代替手段について、ご意見をお聞かせください。

4

1 に答える 1

1

Ruby にはEnumeratorsがあり、これは限定された形式のコルーチンです。それらは次のように機能します。

infinite_set = Enumerator.new do |yielder|
  i = 0
  loop do
    yielder.yield(i += 1)
  end
end

puts infinite_set.next
puts infinite_set.next
puts infinite_set.next

# Output:
# 1
# 2
# 3

列挙子を使用すると、外部反復、リストの遅延評価、および関数の複数のエントリ/終了ポイントが可能になります。内部を見ると、Ruby がファイバーを使用してそれらを実装していることがわかります。

元のコードに対する私の見解は、次のようなものが必要だということです。

(1..15).each do |round|
  # round code
  players.each do |player|
    next unless player.active?
    # do network IO with the player object
    # if the player times out or drops, change the player active state
  end
end

これに別のファイバーを追加すると、サーバーが複数のゲームを同時に実行している場合や、何らかのインプロセス バックグラウンド キューイングが必要でない限り、不要な複雑さが増すと思います。その場合、ファイバーと Eventmachine が最適です。

于 2012-10-19T12:49:24.030 に答える