gpt4 book ai didi

ruby - 使用纤维进行事件迭代?

转载 作者:数据小太阳 更新时间:2023-10-29 08:09:50 25 4
gpt4 key购买 nike

作为我 CS 教育的一部分,我正在构建一个多人 Android yatzy 游戏,客户端通过基于 Ruby/EventMachine 的 TCP 服务器链接在一起,JSON 消息代表游戏事件来回传递。

但是,我不确定如何以最佳方式处理游戏回合管理。

典型的 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 客户端还不完整,所以我还没有测试这个理论在实践中是否真的有效。

我选择 Fiber 类是基于希望能够在 @players 上迭代 15 次并让他们一次掷一个骰子。纤维使这成为可能,因为每次调用 yield 并返回播放器时它们都会暂停循环。

我想知道您对这种方法的看法,特别是它有哪些弱点以及您认为我应该考虑哪些替代方案来解决这个转弯管理问题。

最佳答案

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 会很棒。

关于ruby - 使用纤维进行事件迭代?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12965534/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com