0

我还没有完全验证正确性和缺少一个错误的错误,但请耐心等待。

这里的目标是将一副纸牌(定义为 {Card*})处理/拆分为多个 Decks(可选地将 {Card*} 作为构造函数参数)。我想以循环方式拆分牌,就像实际上会发牌一样。这是我到目前为止的代码:

{Deck*} split(Integer ways) {
    assert(theCards.size % ways == 0);
    {Card*} empty = {};
    value decks = LinkedList { for (i in 0:ways) empty };
    for(i -> card in entries(theCards)) {
        value deckIndex = i % ways;
        assert (exists current = decks[deckIndex]);
        decks.set(deckIndex, {card, *current});
    }
    return { for(cards in decks) Deck(cards) };
}
  1. 这是将列表拆分为多个列表的正确/惯用方式吗?
  2. 如果我不想反转所有卡片(即附加到列表而不是前置,或反转可迭代),我该怎么做?
  3. 我将如何decks在循环中懒惰地初始化变量的值?
  4. 有什么办法可以摆脱需要empty我拥有的变量吗?
  5. 我有没有机会在不需要可变数据结构的情况下编写这个?

谢谢,对于多问题感到抱歉(我已经在 codereview.stackexchange.com 上创建了这个,但我没有代表在ceylon那里创建标签)。

4

2 回答 2

4

不颠倒、懒惰、不可变的数据结构:

alias Card => String;

{{Card*}*} deal({Card*} cards, Integer players)
        => {for (i in 0:players) cards.skipping(i).by(players)};

void run() {
    value suits = {"♦", "♣", "♥", "♠"};
    value ranks = {for (i in 2..10) i.string}.chain{"J", "Q", "K", "A"};
    value deck = {for (suit in suits) for (rank in ranks) rank + suit};
    print(deal(deck.taking(10), 2)); // { { 2♦, 4♦, 6♦, 8♦, 10♦ }, { 3♦, 5♦, 7♦, 9♦, J♦ } }
}

懒惰和不可变的风格是以每手牌遍历所有牌为代价的。我更喜欢这个急切的解决方案:

{Card[]*} deal({Card*} cards, Integer players) {
    value hands = [for (i in 0:players) SequenceBuilder<Card>()];
    for (card->hand in zipEntries(cards, hands.cycled)) {
        hand.append(card);
    }
    return {for (hand in hands) hand.sequence};
}

这样,您只需迭代一次套牌。


请注意,Ceylon 的枚举类型提供了一种很好的方式来以类型安全和面向对象的方式表示西装和等级等事物,类似于 Java 的枚举:

abstract class Suit(shared actual String string)
        of diamonds | clubs | hearts | spades {}

object diamonds extends Suit("♦") {}
object clubs extends Suit("♣") {}
object hearts extends Suit("♥") {}
object spades extends Suit("♠") {}
于 2013-12-10T04:07:16.177 回答
1

怎么样:

alias Deck => {Card*};

{Deck*} split(Deck cards, Integer ways) {
    assert(ways.divides(cards.size));
    return { for i in (0:ways) { for (j->card in entries(cards)) if (j%ways==i) card } };
}

如果Deck实际上是一个类,从你的描述中不是很清楚,那么这个:

class Deck(shared {Card*} cards) { ... }

{Deck*} split(Deck deck, Integer ways) {
    assert(ways.divides(deck.cards.size));
    return { for i in (0:ways) Deck { for (j->card in entries(deck.cards)) if (j%ways==i) card } };
}

注意:我没有测试过这个。

于 2013-12-09T20:43:25.057 回答