0

マッチしたカードのペアにポイントが与えられる 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 の 1 つ (1 ペア) と 6 の 4 つ (2 ペア) を除いてすべて削除したいと思います。user_hand を 4 5 1 2 のままにします。しかし、私の人生では、これを行う方法が思いつきません。どんな助けでも大歓迎です!

4

4 に答える 4

0

配列をループすることから始めて、user_countremove_card を の 2 倍長く呼び出し続け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++ を使用しているかに応じて、構造体またはクラスを使用してユーザーの手を握ることを検討する必要があります。

于 2013-10-29T20:49:34.320 に答える
0

通常、カードに 1 つの配列を使用し、カードの数を保持するために 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;
    }
  }
}
于 2013-10-29T20:41:42.440 に答える
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 )以下になるとは思いません

于 2013-10-29T20:42:11.620 に答える
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
        }
    }
}
于 2013-10-29T21:03:45.357 に答える