C中的Deck shuffling将编译但是Segmentation Faults

时间:2015-02-18 21:12:47

标签: c arrays pointers enums segmentation-fault

typedef enum {Clubs = 1, Diamonds, Hearts, Spades} suit_t;
typedef enum {Ace = 1, Two = 2, Three = 3, Four = 4, Five = 5,
              Six = 6, Seven = 7, Eight = 8, Nine = 9, Ten = 10,
              Jack = 11, Queen = 12, King = 13} face_t;

typedef struct card_t
{
        suit_t suit;
        face_t face;
} card;

typedef struct stack_t
{
    struct card_t deck[53];
    int size;
} stack_h;

void shuffle_deck(stack_h *stack)
{
   stack_h temp, *cardptr;
   int i,num;

   for(i = 0; i < stack->size; i++)
   {
    i = rand() %stack->size;
    *cardptr = *stack;
    temp = *cardptr;
    *cardptr = *stack;
    *stack = temp;
   }
}

所以我尝试了许多不同的方法让我的牌组洗牌,但不幸的是我没有运气,我想要做的就是把它编制的牌组洗得很好但是当它改组牌时它会分段错误。关于如何修复它的任何想法?一切都有效,但改组功能。

3 个答案:

答案 0 :(得分:1)

这一行:

*cardptr = *stack;

在变量cardptr指向任何内容之前发生,因此它指向您覆盖的随机内存。

改组是一个众所周知的解决问题。 Google&#34; Fisher-Yates&#34;。

答案 1 :(得分:0)

您的交换代码充其量是可疑的。使用它可能更接近正确:

for (i = 0; i < stack->size; i++)
{
    int j = rand() % stack->size;
    card_t temp = stack->deck[i];
    stack->deck[i] = stack->deck[j];
    stack->deck[j] = temp;
}

这可能不是一个无偏见的随机播放。请参阅维基百科上的Fisher-Yates以及编码恐怖中的The Danger of Naïveté

答案 2 :(得分:0)

首先考虑算法。有多种方法可以执行随机播放,但常见的技术(Fisher-Yates)是:

  1. 如果剩余的元素少于两个,则停止。
  2. 从剩余要洗牌的池中选择一个随机元素,并将其与池的最后一个元素交换。
  3. 将池的大小减小一,然后返回步骤1.
  4. C中的实现可能如下所示:

    void shuffle_deck(stack_h *stack)
    {
       int last;
    
       for (last = stack->size - 1; last > 0; last -= 1)
       {
          int i = rand() % (last + 1);
    
          if (i < last) {
              card_t temp = stack->deck[i];
              stack->deck[i] = stack->deck[last];
              stack->deck[last] = temp;
          } // else the chosen element is already in the target position
       }
    }