删除数组中的匹配对

时间:2013-10-29 20:21:03

标签: c arrays

我正在尝试编写Go Fish游戏,其中为匹配的卡片组提供积分。但是,我似乎找不到从手中移除匹配对的方法。

我已经实现了一个小循环来移除游戏其他方面使用的单张卡片,如下所示:

for ( i = position - 1 ; i < user_size - 1 ; i++)
    {
        user_hand[i] = user_hand[i+1];
        user_count[i]--;
        user_size--;
    }

其中user_size是用户手中的牌数,user_count是用户持有的13张牌值中的每一张牌中的多少。然而,我无法找到一种方法来删除相同价值的卡片。

例如,如果user_hand是:2 2 4 5 6 6 6 6 1 2

我想删除2个中的一个(一对)和6个中的所有四个(两对)。将user_hand留作:4 5 1 2.但是对于我的生活,我想不出办法做到这一点。任何帮助将不胜感激!

4 个答案:

答案 0 :(得分:0)

通常你会使用1个数组作为卡片,使用一个变量来保存卡片数量。 然后你可以使用这样的嵌套循环进行迭代:

for (int i = 0; i < user_size; i++){
  for (int j = i+1; j < user_size; j++){
    if(user_hand[i] == user_hand[j]){
      /* remove card at index i */
      for(int z = i; z < user_size - 1; z++) user_hand[z] = user_hand[z + 1];
      user_size--;
      /* remove card at index j */
      for(int z = j; z < user_size - 1; z++) user_hand[z] = user_hand[z + 1];
      user_size--;
    }
  }
}

但在您的示例中,您还获得了user_count[]。如果我理解正确(否则请纠正我)user_count []保存用户手上具有的特定值的卡数。 所以在你的例子中:2 2 4 5 6 6 6 6 1 2

user_count[0] = 0
user_count[1] = 1
user_count[2] = 3
user_count[3] = 0
user_count[4] = 1
user_count[5] = 1
user_count[6] = 4

如果这是user_count[]的用途,那么您可以这样做:

for (int i = 0; i < user_size; i++){
  for (int j = i+1; j < user_size; j++){
    if(user_hand[i] == user_hand[j]){
      int cardNumber = user_hand[i];
      /* remove card at index i */
      for(int z = i; z < user_size - 1; z++) user_hand[z] = user_hand[z + 1];
      user_size--;
      /* remove card at index j */
      for(int z = j; z < user_size - 1; z++) user_hand[z] = user_hand[z + 1];
      user_size--;
      /* decrement user_count by 2 */
      user_count[cardNumber] = user_count[cardNumber] - 2;
    }
  }
}

答案 1 :(得分:0)

如果用户手中的重新排序卡不是问题,您可以:

int *hand;
int handSize;
...
sort(hand, handSize);                   // 1. sort

int *newHand = malloc(sizeof(int) * handSize);
int i, newHandSize = 0;
for (i = 1; i < handSize; ++i) {
    if (hand[i - 1] == hand[i]) {
        hand[i] = -1;                   // 2. "flag" last value of a pair
        continue;
    }
    newHand[newHandSize] = hand[i - 1]; // 3. copy last examined card to new hand
    newHandSize++;
}
if (hand[handSize - 1] != -1) {         // 4. copy last element if needed
    newHand[newHandSize] = hand[handSize - 1];
    newHandSize++;
}
int* handToFree = hand;
hand = newHand;                         // 5. replace users hand with new hand
free(handToFree);                       // 6. clean up

但我认为它不能归 O(n * log(n)+ n)

答案 2 :(得分:0)

首先循环浏览user_count数组,并继续调用remove_card两倍user_count[rank] >= 2

for(int rank = 1; rank <= 13; rank++)
    while(user_count[rank] >= 2) {
        remove_card(user_hand, user_count, &user_size, rank);
        remove_card(user_hand, user_count, &user_size, rank);
    }

对于remove_card,只需找到第一张匹配的卡片,然后调用现有的例程:

void remove_card(int *user_hand, int *user_count, int *user_size, int rank) {
    for(int pos = 0; pos < *user_size; pos++)
         if(user_hand[pos] == rank)
            remove_card_at(user_hand, user_count, user_size, pos+1);
}

remove_card_at是您在原始帖子中提供的例程,用于删除特定位置的卡片。请注意,您必须将user_size转换为指针并取消引用它才能修改调用函数中的变量。

此外,您应该真正考虑使用结构或类来保持用户的手,这取决于您使用的是C还是C ++。

答案 3 :(得分:0)

void removePairs(int * hand, int size)
{       
    for(int i = 0; i < size; i++)
    {
        for(int j = i+1; j < size; j++)
        {
            if((hand[i] == hand[j]) && hand[i] != -1)
            { 
                hand[i] = -1; // set card "ready to remove"
                hand[j] = -1;
                break;
            }
        }
    }
    for(int k = 0; k < size; k++)
    {
        if(hand[k] != -1)
        {
            printf("%d ", hand[k]); // you can store remaining cards here
        }
    }
}