洗牌流星集合

Posted

技术标签:

【中文标题】洗牌流星集合【英文标题】:Shuffling a meteor collection 【发布时间】:2013-11-30 23:40:01 【问题描述】:

我正在构建一个纸牌游戏,需要在游戏开始前洗牌玩家的牌组。通过在将数组插入数据库之前对其进行改组,可以毫无问题地完成此操作。然而,在游戏开始后,有些情况下玩家需要洗牌。我想到的唯一方法是在再次洗牌后重新插入甲板,但这肯定是无效的。 这是插入前洗牌的代码。

deck = _.shuffle (Card_Reference.find deck_id: hoster.deck).fetch()


    _.each deck, (card) ->
        Deck.insert
            userId: opponent._id
            game_id: id
            card: card.card

插入后

deck = Deck.find().fetch()
ids = _.pluck deck, "_id"
shuffled = _.shuffle deck
Deck.remove _id: $in: ids

_.each shuffled, (card) ->
    Deck.insert
       userId: opponent._id
       game_id: id
       card: card.card

这当然是无效和不必要的。 那么,如何洗牌一个集合呢? 谢谢。

【问题讨论】:

您是想为所有玩家设置相同的随机播放,还是为每个播放器设置不同的随机播放? @AndrewMao 我想要的是当玩家点击洗牌按钮时,玩家的牌组再次洗牌。 【参考方案1】:

是的,移除和重新插入是一种低效的洗牌方式,尤其是在渲染卡片是一项耗时的操作时。我建议使用以下方法,如果Deck#each 中呈现,则仅生成moved 操作,例如:

无论您在何处使用需要洗牌的牌组,请使用按洗牌顺序排序的光标:

deck = Deck.find(, sort: order: 1).fetch()

现在,在需要洗牌时更改顺序:

newOrder = _.shuffle [1..52] # or whatever Deck.find().count() is
Deck.find().forEach (card, idx) -> 
  Deck.update(card._id, $set: order: newOrder[idx])

这种洗牌方法不会导致任何内容被删除并重新出现在集合中。只要您为玩家和游戏正确地确定查找操作的范围,以便其他牌组在不知不觉中被洗牌,您就应该开始做生意了。

【讨论】:

所以,按照这种方式,如果我想在卡组底部插入一张卡片,我只需给它一个卡组大小+1的顺序,负值添加一张卡片甲板顶部,对吧? 是的,但在这种情况下,您可能需要做一些更聪明的事情来跟踪正在使用的索引,因为它们不会是连续的。

以上是关于洗牌流星集合的主要内容,如果未能解决你的问题,请参考以下文章

集合综合练习(斗地主随机洗牌)

java斗地主扑克 扑克牌 洗牌 发牌 Collection 集合练习

斗地主之洗牌发牌----Java篇

洗牌算法

Java学习笔记34(集合框架八:综合案例:模拟斗地主的洗牌发牌)

Map集合HashMap集合LinkedHashMap集合Hashtable集合Collections工具类和模拟斗地主洗牌和发牌