【问题标题】:Deck (Linked List) of Cards (Nodes) Riffle Shuffle卡片组(链接列表)(节点)Riffle Shuffle
【发布时间】:2014-05-07 10:53:35
【问题描述】:

我又回来了。所以我使用卡片作为节点以链表方式创建了一个卡片组。但是,我的 riffle shuffle 功能有问题。该函数应该创建两个 Deck 对象,每个对象存储我的 Deck drawPile 的一半。然后,这两个半堆应该一次取出一张牌并将其添加回drawPile。我没有收到错误,但它根本没有洗牌。我这样调用函数:drawPile.shuffle(drawPile);

Deck::Deck()
{
    top = NULL;
    SIZE = 0;
}

Deck::Deck(Card *n)
{
    top = n;
}
void Deck::shuffle(Deck &d)
{
    srand((unsigned)time(0));

    for (int i = 0; i < 7; i++){
        //split deck in half -- leftHalf and rightHalf
        Deck leftHalf, rightHalf;

        int j = SIZE/2;
        for (int k = SIZE; k > j; k--){
            drawCard(leftHalf);  //drawCard off Deck and addCard to leftHalf
        }
        for (j; j > 0; j--){
            drawCard(rightHalf);  //drawCard off Deck and addCard to rightHalf
        }
        while (leftHalf.getSIZE() > 0 && rightHalf.getSIZE() > 0){
            int probPile = leftHalf.getSIZE()/(leftHalf.getSIZE() + rightHalf.getSIZE())*100;
            int randomNum = rand() % 100 + 1;
            if (randomNum <= probPile){
                leftHalf.drawCard(d);   //drawCard off leftHalf and addCard to Deck
            }
            else{
                rightHalf.drawCard(d);  //drawCard off rightHalf and addCard to Deck
            }
        }
        while (leftHalf.getSIZE() > 0){
    leftHalf.drawCard(d);
        }
    while (rightHalf.getSIZE() > 0){
    rightHalf.drawCard(d);
    }
    }
}

void Deck::drawCard(Deck &d)    
{
    Card *draw = top;
    if (draw != NULL){
        top = top->getNext();
        SIZE--;
            d.addCard(draw->getVALUE(), draw->getSUIT());
    }
}//end drawCard

void Deck::addCard(int val, string s)
{
    top = new Card(val, s, top);
    SIZE++;
}//end addCard

【问题讨论】:

  • 与其制作自己的容器,不如考虑使用(或至少包装)standard container,例如std::vector
  • 至于您的问题,您是否尝试过在调试器中逐行执行代码?只用一个小“牌组”(比如十张“牌”)就可以更容易。
  • 这是一个类,我不允许使用链表以外的任何结构。 ://
  • 忽略你试图创造的任何人为的概率,最终这是分裂牌组,然后随机抽取一堆或另一堆,直到一侧用尽,最后附加剩余的无论哪一边有最后一张牌,你就完成了。这对吗?如果是这样,这方式比它需要的更复杂。 (看起来你忘记附加至少剩下一张牌的“一半”作为最后一招)。
  • 是的,这就是目标。但是,我不确定如何附加您提到的“一半”。

标签: c++ linked-list shuffle dynamic-allocation


【解决方案1】:

你的问题在这里:

while (leftHalf.getSIZE() > 0 && rightHalf.getSIZE() > 0){

如果你已经从leftHalf 抽取了所有的牌,但rightHalf 仍然包含一些牌,那么你的循环就结束了。在这种情况下,您的洗牌 Deck 不包含所有卡片。
在该循环之后,您需要例如实现两个这样的循环:

while (leftHalf.getSIZE() > 0)
    // Draw all remaining cards from leftHalf
while (rightHalf.getSIZE() > 0)
    // Draw all remaining cards from rightHalf

==============================================
你也可以在这里得到一个“空指针访问”错误:

d.addCard(draw->getVALUE(), draw->getSUIT());

因为draw 可以为空。

==============================================
也在这里:

for (int l = SIZE; l > 0; l--){

你试图抓太多牌。您可以从j 而不是SIZE 开始循环。

=============================================== 另一个问题在这里:

int probPile = leftHalf.getSIZE()/(leftHalf.getSIZE() + rightHalf.getSIZE())*100;

probPile 始终为 0,因为您使用整数除法(例如,如果我们使用整数除法,5/100 为 0)。使用的解决方案之一 浮点除法。您可以在除法之前以某种方式将int 值转换为double,例如通过乘以1.0,然后将结果转换回int

int probPile = static_cast<int>(leftHalf.getSIZE() * 1.0 /(leftHalf.getSIZE() + rightHalf.getSIZE())*100);

或者你可以在除法之前乘以100:

int probPile = leftHalf.getSIZE() * 100/(leftHalf.getSIZE() + rightHalf.getSIZE());

【讨论】:

  • 非常感谢!我最终把 d.addCard(draw->getVALUE(), draw->getSUIT());在 if 语句中,这消除了我遇到的错误。我即将测试剩余卡片的新 while 循环
  • 好的,所以当我合并两个额外的 while 循环时,我根本没有收到任何错误......但是“洗牌”之后的卡片仍然是有序的。
  • @Shannon 关于您的编辑。看起来shuffle 同时被调用了两次。也许当出现错误窗口(“空指针”)时,您以某种方式第二次调用了shuffle
  • 我的编辑是我自己的错误,我不小心用断点强制它再次循环。
  • @Shannon 我为 Deck 保持有序的问题添加了解决方案。
猜你喜欢
  • 2020-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-05
  • 1970-01-01
相关资源
最近更新 更多