【问题标题】:Deck shuffling in C will compile but Segmentation FaultsC 中的 Deck shuffle 会编译,但会出现 Segmentation Faults
【发布时间】:2015-02-18 21:12:47
【问题描述】:
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;
   }
}

所以我尝试了许多不同的方法来让我的牌组洗牌,但不幸的是我没有运气,我想做的就是很好地洗牌它编译的牌组,但是当它洗牌时,它会出现分段错误。关于如何解决它的任何想法?一切正常,但洗牌功能。

【问题讨论】:

  • 你做过堆栈跟踪吗?此外,在发布问题时,请尝试仅发布相关代码。 shuffle_deck 在这种情况下。它使人们更容易看到他们何时不必查看您的所有其他代码。
  • 在随机播放中,您正在为堆栈分配一个随机整数*stack = rand() %stack-&gt;size;——我认为这不是您想要的。
  • @dubstylee 谢谢我真的不知道我需要包括什么
  • @user590028 你说得对,但是我分配的 int 该怎么办?
  • 您的代码对stack 执行了各种操作,但看起来您想要操作的是stack-&gt;deck 的元素。

标签: c arrays pointers enums segmentation-fault


【解决方案1】:

这一行:

*cardptr = *stack;

发生在变量cardptr 指向任何东西之前,因此它指向随机内存,你会覆盖它。

洗牌是一个众所周知的已解决问题。谷歌“Fisher-Yates”。

【讨论】:

    【解决方案2】:

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

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

    在 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
       }
    }
    

    【讨论】:

    • 请注意,假设stack-&gt;deck 的有效元素是从索引0 到索引stack-&gt;size - 1 的元素。
    • 这让我知道我需要做什么谢谢。
    【解决方案3】:

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

    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;
    }
    

    这可能不是一个公正的洗牌。请参阅 Wikipedia 上的 Fisher-Yates 和 Coding Horror 上的 The Danger of Naïveté

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-26
      • 2010-10-12
      • 2018-11-29
      • 2012-02-04
      • 2021-10-05
      • 2014-08-06
      • 2021-08-06
      • 2017-10-19
      相关资源
      最近更新 更多