Thread: copying array positions

  1. #1
    Registered User
    Join Date
    Apr 2019
    Posts
    662

    copying array positions

    for this example i have an array of 52 cards i take five cards off the top and mark the slots empty then ii want to move the 6th card into the position of the 1st card (array element 5 to array element 0) and mark element 0 as taken then take the 7th card and put it as the second and so on until i have run out of cards then mark the last 5 slots (elements 48 - 52) as empty.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>
    
    enum card_value {TWO = 2, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING, ACE};
    enum Suit {SPADES = 0, HEARTS, CLUBS, DIAMONDS};
    
    typedef struct
    {
        enum Suit suit;
        enum card_value value;
        bool empty_slot;
    } Card;
    
    void print_deck(Card deck[])
    {
        int i;
        for (i = 0; i < 52; i++)
        {
            if (deck[i].empty_slot)
            {
                printf("ee ");
            }
            else
            {
                printf("%d%d ", deck[i].suit, deck[i].value);
            }
        }
        printf("\n");
    }
    
    void move_deck(Card deck[])
    {
        int i, card_index = 0;
    
        for (i = 0; i < 52; i++)
        {
            if (deck[i].empty_slot)
            {
                card_index++;
            }
        }
    
        for (i = 0; i < 52; i++)
        {
            if (card_index < 52) //copy cards down the chain till moved last card
            {
                deck[i] = deck[i + card_index];
                deck[i + card_index].empty_slot = false;
                card_index++;
            }
            else
            {
                deck[i].empty_slot = true;
            }
        }
    
    }
    
    void get_hand(Card deck[], Card hand[])
    {
        int i;
    
        for (i = 0; i < 5; i++)
        {
            hand[i] = deck[i];
            deck[i].empty_slot = true;
        }
    }
    
    int main()
    {
        int i, j, card_count = 0;
        Card deck[52], hand[5];
    
        for (j = 0; j < 4; j++)
        {
            for (i = 2; i < 15; i++)
            {
                deck[card_count++] = (Card) {j, i, false};
            }
        }
    
        get_hand(deck, hand);
        print_deck(deck);
        move_deck(deck);
        print_deck(deck);
        return 0;
    }
    i get the following out after the first call to print_deck:
    ee ee ee ee ee 07 08 09 010 011 012 013 014 12 13 14 15 16 17 18 19 110 111 112 113 114 22 23 24 25 26 27 28 29 210 211 212 213 214 32 33 34 35 36 37 38 39 310 311 312 313 314

    all good i have my first 5 slots marked as empty (ee) However on the second call of print_deck i get this output:
    07 09 011 013 12 14 16 18 110 112 114 23 25 27 29 211 213 32 34 36 38 310 312 314 ee ee 218490 ee ee 327670 ee 00 ee 3276728 327670 ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee

    for some reason its printing out every other card or im moving every other card and then either filling the rest with junk or ee

    many thanks]
    coop

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    37,497
    I don't think you should be modifying card_index in the copy loop.

    Code:
    for ( i = 0, j = card_index ; j < 52 ; i++, j++ ) {
        deck[i] = deck[j];
    }
    for ( ; i < 52 ; i++ ) {
        deck[i].empty_slot = true;
    }
    Why store a flag in each card?

    Code:
    struct Deck {
        int numDealtCards;
        Card cards[52];
    };
    Dealing is then just
    Code:
    void deal(Deck *deck, Card hand[])
    {
        int i;
        for (i = 0; i < 5; i++)
        {
            // check numDealtCards
            hand[i] = deck->cards[deck->numDealtCards++];
        }
    }
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Apr 2019
    Posts
    662
    Quote Originally Posted by Salem View Post
    I don't think you should be modifying card_index in the copy loop.

    Code:
    for ( i = 0, j = card_index ; j < 52 ; i++, j++ ) {
        deck[i] = deck[j];
    }
    for ( ; i < 52 ; i++ ) {
        deck[i].empty_slot = true;
    }
    um isn't j now equivalently card_index??

    Quote Originally Posted by Salem View Post
    Why store a flag in each card?

    Code:
    struct Deck {
        int numDealtCards;
        Card cards[52];
    };
    Dealing is then just
    Code:
    void deal(Deck *deck, Card hand[])
    {
        int i;
        for (i = 0; i < 5; i++)
        {
            // check numDealtCards
            hand[i] = deck->cards[deck->numDealtCards++];
        }
    }
    then i guess i can set j to numDealtCards in the above example
    coop

  4. #4
    Registered User
    Join Date
    Feb 2019
    Posts
    533
    Essentialy what you want to do is to move all still valid cards in the deck to the begining of the array, marking the final cards as "empty", isn't it?

    Well... notice your card_value enumeration starts with 2. Add an EMPTY=0 at the beginning:
    Code:
    enum card_value {EMPTY = 0, TWO = 2, THREE, FOUR, 
      FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING, ACE};
    And use it as an EMPTY card (no need to use the empty_slot boolean - reducing the Card structure size). Here's an example code using integers:
    Code:
    #include <stdio.h>
    #include <string.h>
    
    int c[16] = { 1, 2, 0, 3, 4, 5, 0, 0, 0, 6, 7, 8, 0, 9, 10, 11 };
    
    void shrink ( int *p, unsigned int count )
    {
      unsigned int i, j;
    
      j = 0;
    
      for ( i = 0; i < count; i++ )
      {
        if ( !p[j] )
        {
          memmove ( p + j, p + j + 1, sizeof ( *p ) * ( count - j - 1 ) );
    
          // mark the last one as empty
          // need to do this only once, but it doesn't hurt to do it multiple times.
          p[count - 1] = 0;
        }
        else
          j++;  // advance only if no movement was made before.
      }
    }
    
    int main ( void )
    {
      unsigned int i;
    
      // print original array:
      for ( i = 0; i < sizeof c / sizeof c[0]; i++ )
        printf ( "%d ", c[i] );
    
      putchar ( '\n' );
    
      // rearrange...
      shrink ( c, sizeof c / sizeof c[0] );
    
      // print shrinked array
      for ( i = 0; i < sizeof c / sizeof c[0]; i++ )
        printf ( "%d ", c[i] );
    
      putchar ( '\n' );
    }
    Compiling and linking:
    Code:
    $ cc -o test test.c
    $ ./test
    1 2 0 3 4 5 0 0 0 6 7 8 0 9 10 11 
    1 2 3 4 5 6 7 8 9 10 11 0 0 0 0 0
    Last edited by flp1969; 05-14-2019 at 10:11 AM.

  5. #5
    Registered User
    Join Date
    Apr 2019
    Posts
    662
    ok let me change my first comment to salem to why is your approach different as it clearly is as yours works and mine doesnt
    coop

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    37,497
    OK, so you dealt 5 cards, so card_index = 5

    So you want to copy [5] to [0], [6] to [1], [7] to [2] all the way up to [51] to [46]

    The difference between the from and to indices is constant.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  7. #7
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    656
    Instead of dealing from the bottom of the deck, why not deal from the top? Then all you need to do is add 5 to numDealtCards.

    ETA: NVM. I like Salem's suggestion of dealing cards using numDealtCards as the index into the deck. It's simple and elegant. Why do you care what values the cards below numDealtCards have anyway?
    Last edited by christop; 05-14-2019 at 12:52 PM. Reason: change subtract to add

  8. #8
    Registered User
    Join Date
    Apr 2019
    Posts
    662
    i don't care i am only printing them all out to make sure my functions work

  9. #9
    Registered User
    Join Date
    Apr 2019
    Posts
    662
    Quote Originally Posted by Salem View Post
    OK, so you dealt 5 cards, so card_index = 5

    So you want to copy [5] to [0], [6] to [1], [7] to [2] all the way up to [51] to [46]

    The difference between the from and to indices is constant.
    im being thick i guess but i thought that's what i had written in my code.
    ie to index (i) is 0 and card_index is 5 next iteration of the for loop i is 1 and card_index is 6 then once card_index is greater than 51 i must of moved all the cards so mark the rest of the "slots empty"

    i must admit i think your idea of numCardsDealt is better as i could have another struct for discarded cards and all the indexes are already there
    coop

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 04-18-2013, 02:21 PM
  2. Replies: 3
    Last Post: 02-12-2013, 04:00 AM
  3. Replies: 2
    Last Post: 11-27-2012, 02:11 PM
  4. finding positions of characters in a 2d array
    By synhyborex in forum C Programming
    Replies: 2
    Last Post: 02-13-2011, 03:37 PM
  5. counting array positions
    By Cpro in forum C++ Programming
    Replies: 4
    Last Post: 02-04-2008, 11:25 PM

Tags for this Thread