混洗Meteor集合

3

我正在制作一款卡牌游戏,在游戏开始前需要洗牌玩家的牌库。将数组洗牌后插入数据库即可轻松完成此操作。然而,在游戏开始后,有些情况下需要玩家重新洗牌。我想到的唯一方法是再次洗牌后重新插入牌库,但这显然是低效的。以下是插入前洗牌的代码:

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

当然,这是无效和不必要的。那么,如何打乱集合呢?谢谢。

你是想让所有玩家使用相同的洗牌顺序还是每个玩家都有不同的洗牌顺序? - Andrew Mao
@AndrewMao 我想要的是,当玩家点击洗牌按钮时,玩家的牌组再次洗牌。 - doctor penguin
1个回答

2

是的,删除和重新插入是一种低效的洗牌方式,特别是如果渲染卡片需要耗费时间。我建议采用以下方法,仅在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的顺序,而给负值则会将牌放在牌堆顶部,对吗? - doctor penguin
是的,但在这种情况下,您可能希望做一些更智能的事情来跟踪使用的索引,因为它们不会是连续的。 - Andrew Mao

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接