Thread: looping issue

  1. #1
    Registered User PunchOut's Avatar
    Join Date
    Jun 2008
    Location
    norfolk, va
    Posts
    16

    looping issue

    Hello everyone, I am having trouble with a program and the loop in the main function highlighted in red. I need the program to deal 10 times and determine hands etc. Not sure what I am missing here.

    Code:
    /* Fig. 7.24: fig07_ 24. c 
    Card shuffling dealing program */ 
    # include <stdio.h> 
    # include <stdlib.h> 
    # include <time.h> 
    # include <string.h>
    
    
    /* prototypes */ 
    void shuffle( int wDeck[][ 13 ] ); 
    void deal( const int wDeck[][ 13 ], const char * wFace[], const char * wSuit[], int userSuit[], int userFace[], int compSuit[], int compFace[] ); 
    void user( int userSuit[], int userFace[], int userHand );
    void comp( int compSuit[], int compFace[], int compHand );
    void compare( int userHand, int compHand, int userTotal, int compTotal  );
    
    /* needed for qsort used in hands function */
    
    /********************************** MAIN **********************************/
    int main( void ) 
    { 
    	int x = 0;
    	/* initialize arrays for each hand's suit and face*/
    	int user_hand = 0;
    	int user_total = 0;
    	int user_suit[4] = {0};
    	int user_face[13] = {0};
    	
    	int comp_hand = 0;
    	int comp_total = 0;
    	int comp_suit[4] = {0};
    	int comp_face[13] = {0};
    
    	/* initialize suit array */
    	const char *suit[4] = { "Hearts", "Diamonds", "Clubs", "Spades" };
    	/* initialize face array */
    	const char *face[13] = { "Ace", "Deuce", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King" };
    	/* initialize deck array */ 
    	int deck[ 4 ][ 13 ] = { 0 }; 
    
    	for(x = 1; x <= 10; x++) {
    		shuffle( deck ); /* shuffle the deck */ 
    		deal( deck, face, suit, user_suit, user_face, comp_suit, comp_face); /* deal the deck */ 
    		user(user_suit, user_face, user_hand); /* determine the user's hand */
    		comp(comp_suit, comp_face, comp_hand); /* determine the computer's hand */
    		compare(user_hand, comp_hand, user_total, comp_total); /* compares the hands and keeps track if the winners */
    	} 
    
    	system("pause");
    
    	return 0; /* indicates successful termination */ 
    } /* end main */ 
    
    
    /********************************** shuffle cards in deck **********************************/ 
    void shuffle( int wDeck[][ 13 ] ) 
    { 
    	int row; /* row number */ 
    	int column; /* column number */ 
    	int card; /* counter */ 
    
    	  /* for each of the cards, choose slot of deck randomly */
    	for ( card = 1; card <= 52; card++ ) {
    		/* choose new random location until unoccupied slot found */
    		do {
    			row = rand() % 4;
    			column = rand() % 13;
    		} while( wDeck[ row ][ column ] != 0); /*end do...while */
     
    		/* place card number in chosen slot of deck */ 
    		wDeck[ row ][ column ] = card; 
    	} /* end for */ 
    } /* end function shuffle */ 
    
    
     
    /********************************** deal cards in deck **********************************/ 
    void deal( const int wDeck[][ 13 ], const char *wFace[], char *wSuit[], int userSuit[], int userFace[], int compSuit[], int compFace[] ) 
    { 
    	int card; /* card counter */ 
    	int row; /* row counter */ 
    	int column; /* column counter */ 
    	printf("*****Your hand*****\n");
    	/* deal 5 cards */ 
    	for ( card = 1; card <= 10; card++ ) {
    		if(card == 6) {
    		printf("\n\n*****Computer's Hand*****\n");
    		}
    	/* loop through rows of wDeck */  
    	for ( row = 0; row <= 3; row++ ) { 
    	  /* loop through columns of wDeck for current row */ 
          for ( column = 0; column <= 12; column++ ) { \
    	    /* if slot contains current card, display card */ 
    		if ( wDeck[ row ][ column ] == card ) {
    		  printf("%5s of %8s\n", wFace[ column ], wSuit[ row ]);
    		  /* store user info */
    		  if(card < 6) {
    			 userSuit[row]++;
    			 userFace[column]++;
    		  } 
    		  if(card > 5) {
    			 compSuit[row]++;
    			 compFace[column]++;
    		  }
    		} /* end if contains current card */ 
          } /* end for columns */ 
        } /* end for rows */ 
    
      } /* end for dealing */
      	  
    
    } /* end function deal */
    
    void user( int userSuit[], int userFace[], int userHand )
    {
    	int i;
    	int trips = 0, pair = 0, straight = 0;
    
    	for(i=0; i<13; i++){ /****** determine 4 of a kind *******/
    		if(userFace[i] == 4) {
    			userHand = 6;
    			printf("\nYou has 4 of a kind\n");
    			break;
    		}/* if statement */
    	}/* 4 of a kind loop */
    
    	for(i=0; i<4; i++){ /******* determine flush *******/
    		if(userSuit[i] == 5) {
    			userHand = 5;
    			printf("\nYou has a Flush\n");
    			break;
    		} 
    	}/* flush loop */
    	
    	for(i=0; i<13; i++) { /******* determine straight *******/
    		if(userFace[i] == 1){
    			straight++;
    			if(straight == 5) {
    				userHand = 4;
    				printf("\nYou has a Straight \n");
    				break;
    			}
    		}
    		else
    			straight = 0;
    	}
    	
    	for(i=0; i<13; i++){ /******* determine 3 of a kind *******/
    		if(userFace[i] == 3) {
    			userHand = 3;
    			printf("\nYou has 3 of a kind \n");
    			break;
    		}
    	}/* 3 of a kind loop */
    
    	for(i=0; i<13; i++){ /* pair loop */
    		if(userFace[i] == 2) {
    			pair++;
    		}
    	}/* end of pair loop */
    	if(pair == 2) { /******* determine 2 pair *******/
    		userHand = 2;
    		printf("\nYou has two pair!\n\n");
    	}
    	if(pair == 1) { /******* determine pair *******/
    		userHand = 1;
    		printf("\nYou has one pair!\n\n");
    	}
    	if(pair == 0) {
    		userHand = 0;
    		printf("\nYou have high card!\n\n");
    	}
    }
    
    void comp( int compSuit[], int compFace[], int compHand )
    {
    	int i;
    	int trips = 0, pair = 0, straight = 0;
    
    	for(i=0; i<13; i++){ /****** determine 4 of a kind *******/
    		if(compFace[i] == 4) {
    			compHand = 6;
    			printf("\nYou has 4 of a kind\n");
    			break;
    		}/* if statement */
    	}/* 4 of a kind loop */
    
    	for(i=0; i<4; i++){ /******* determine flush *******/
    		if(compSuit[i] == 5) {
    			compHand = 5;
    			printf("\nYou has a Flush\n");
    			break;
    		} 
    	}/* flush loop */
    	
    	for(i=0; i<13; i++) { /******* determine straight *******/
    		if(compFace[i] == 1){
    			straight++;
    			if(straight == 5) {
    				compHand = 4;
    				printf("\nYou has a Straight \n");
    				break;
    			}
    		}
    		else
    			straight = 0;
    	}
    	
    	for(i=0; i<13; i++){ /******* determine 3 of a kind *******/
    		if(compFace[i] == 3) {
    			compHand = 3;
    			printf("\nYou has 3 of a kind \n");
    			break;
    		}
    	}/* 3 of a kind loop */
    
    	for(i=0; i<13; i++){ /* pair loop */
    		if(compFace[i] == 2) {
    			pair++;
    		}
    	}/* end of pair loop */
    	if(pair == 2) { /******* determine 2 pair *******/
    		compHand = 2;
    		printf("\nYou has two pair!\n\n");
    	}
    	if(pair == 1) { /******* determine pair *******/
    		compHand = 1;
    		printf("\nYou has one pair!\n\n");
    	}
    	if(pair == 0) {
    		compHand = 0;
    		printf("\nYou have high card!\n\n");
    	}
    }
    
    void compare( int userHand, int compHand, int userTotal, int compTotal )
    {
    	if(userHand > compHand) {
    		userTotal++;
    		return;
    	}
    	if(compHand > userHand) {
    		compTotal++;
    		return;
    	}
    	
    }

  2. #2
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Because you initialize the whole deck to 0 and use that as the condition to end the shuffle,
    Code:
    	for ( card = 1; card <= 52; card++ ) {
    		/* choose new random location until unoccupied slot found */
    		do {
    			row = rand() % 4;
    			column = rand() % 13;
    		} while( wDeck[ row ][ column ] != 0); /*end do...while */
     
    		/* place card number in chosen slot of deck */ 
    		wDeck[ row ][ column ] = card; 
    	} /* end for */
    The second time thru there are no zeros in the deck, so this never ends. BTW, this is a very crazy way to do a shuffle -- potentially, if the system keeps throwing the same sequence of random numbers, it will never end the first time either.

    To simulate a shuffle, you should mimic reality: place all fifty-two cards in the deck, then randomly swap one card with another a fixed number of times. The "Fisher-Yates" shuffle is kind of the definitive algorithm for this and it is very simple:

    Fisher

    Right now, you are selecting a deck position at random and assigning it a progressive value a fixed number of times, and checking for collisions. This collision check makes the shuffle very inefficient. I placed a counter inside the do while loop and it happened over 120 times on the first shuffle,* because there are fewer and fewer zero values left each time. This is also unrealistic: by rejecting collisions, you are producing an even distribution. A real shuffle is more random than that.

    Also: you should call srand() once at the beginning of the program, or it will always play out the same way. And finally, your prototype for deal() does not match the definition -- there is a variable that is const in one but not in the other. Use compiler warnings!

    * note that the F-Y shuffle happens in a fixed number of iterations. You could use 52 or 20 or 100, it will always be the same, rather than somewhere between 52 and infinity as it is now.
    Last edited by MK27; 10-02-2011 at 10:13 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  3. #3
    Registered User PunchOut's Avatar
    Join Date
    Jun 2008
    Location
    norfolk, va
    Posts
    16
    I am having a very hard time understanding how to implement the Fisher-Yates algorithm. Is there by chance a simpler way to make this work?

    This program originally dealt 52 cards and we were told to make it deal 10 times and match up hands between the computer and user etc. The shuffle function was given to us by my teacher, is there any way to just tweak that function to make the loop run correctly?

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by PunchOut
    I am having a very hard time understanding how to implement the Fisher-Yates algorithm.
    Do you understand the idea behind the algorithm?
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    Registered User PunchOut's Avatar
    Join Date
    Jun 2008
    Location
    norfolk, va
    Posts
    16
    I think so, the Fisher-Yates cancels out possibilities instead of error checking.

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by PunchOut
    I think so, the Fisher-Yates cancels out possibilities instead of error checking.
    Maybe it will be easier to understand in this way: the algorithm shuffles the list by selecting elements at random from the list, without replacement, until every element from the list has been selected.

    We can do this in-place by looping over each position in the list. On each iteration, we select one element from among the elements at that position and the positions that come after it. Whatever is selected at random is swapped with the element at the current position. We then move on to the next position. We ignore the elements that come before the current position because we are selecting without replacement.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by PunchOut View Post
    The shuffle function was given to us by my teacher,
    Ain't that a card, lol. Are you sure that is exactly it?

    is there any way to just tweak that function to make the loop run correctly?
    You could use memset() to zero the array out before each shuffle. It is still inefficient and has an open-ended, potentially infinite runtime (altho the infinite one is very unlikely).

    Here's a working example of the fisher-yates shuffle:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    void FYshuffle (int *ray, int len) {
    	int i, tmp, x;
    	for (i=len-1; i>1; i--) {
    		x = rand()%i;
    		if (x==i) continue;
    	// now swap
    		tmp = ray[i];
    		ray[i] = ray[x];
    		ray[x] = tmp;
    	}
    }
    
    int main(void) {
    	int ray[10] = {0,1,2,3,4,5,6,7,8,9}, i;
    
    	srand(time(0));
    	FYshuffle(ray,10);
    	for (i=0; i<10; i++) printf("%d\n",ray[i]);
    
    	return 0;
    }
    Make sense? This one is tweaked slightly so that the loop works from the end of the array (len-1) backward and swaps with a randomly selected slot lower than the current one (rand()%i).

    You just have to do some arithmetic to get that to work on a 2D array.
    Last edited by MK27; 10-02-2011 at 12:09 PM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. looping issue
    By aadil7 in forum C Programming
    Replies: 9
    Last Post: 01-13-2011, 10:20 PM
  2. Do-While looping issue
    By atom.sk in forum C Programming
    Replies: 7
    Last Post: 12-19-2010, 02:02 PM
  3. bandwidth issue / network issue with wireless device communication
    By vlrk in forum Networking/Device Communication
    Replies: 0
    Last Post: 07-05-2010, 11:52 PM
  4. Looping Issue
    By stormy in forum C Programming
    Replies: 5
    Last Post: 01-24-2006, 02:35 AM
  5. Looping.
    By Unregistered in forum C++ Programming
    Replies: 17
    Last Post: 08-02-2002, 09:58 PM