My assignment is to make a program that can perform a card trick. You may be familiar with the concept of the trick, but here is a video link from my instructor.

It is a fairly long program, but everything works as planned EXCEPT for my "PickUp" function, which is supposed to pickup the cards column by column. The user selected column must ALWAYS be picked up second and the order of the other two doesn't matter.

The program works at this point, but my issue is that for some reason if you select column 1 or column 2 the "King of Clubs" (which has a int value of 0) will always be the first card picked up... even if it is not one of the 21 cards in play. Maybe one of you will have some insight?

I have attached my source code as a link since it is almost 400 lines long. I figured this was a better way to post it instead of just wrapping code tags around it. Please don't flame me if this is bad manors :P

CardTrick.c

I know its a lot of code, but the PickUp function is my only issue. It stars at line 251.

/* File: cardtrick.c
 * Programmer: Matt Sanchez
 * Date: 10-15-10
 * Course: COP 3515
 *
 * Purpose:
 * Write a program that performs a cardtrick. The program will create a
 * random deck of cards, deal them out, pick them up, and determine the
 * secret card.
 *
*/

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define SIZE 52

/* Function Prototypes */
void BuildDeck( int deck[], int size );
void PrintDeck( int deck[], int size );
void PrintCard( int card );
void Deal( int deck[], int play[][3] );
void PickUp( int deck[], int play[][3], int column );
void SecretCard( int deck[] );

int main() 
{

/* declare and initialize variables */
char SeeDeck = 'n';
char PlayAgain = 'y';
char name[30] = "";
int column = 0;
int i = 0;

/* Declare a 52 element array of integers to be used as the deck of cards */
int deck[52] = { 0 };

/* Declare a 7 by 3 array to receive the cards dealt to play the trick */
int play[7][3] = { 0 };

/* Generate a random seed for the rand() function. */
srand ( time(0) );


/* Openning message.  Ask the player for his/her name */
printf("\nHello, I am a computer program that is so smart\n");
printf("I can even perform a card trick.  Here's how.\n\n");
printf("To begin the card trick type in your name: ");
scanf("%s", name);

/* Capitalize the first letter of the person's name. */
name[0] = toupper(name[0]);

printf("\nThank you %s.\n\n", name);

do
	{
    /* Build the deck */
    BuildDeck(deck, SIZE);

	

    /* Ask if the player wants to see the entire deck. If so, print it out. */
    printf("Ok %s, first things first.  Do you want to see what \n", name);
    printf("the deck of cards looks like (y/n)? \n");
    scanf(" %c", &SeeDeck);
    SeeDeck = tolower(SeeDeck);

	/*if yes print entire deck using PrintDeck function*/
	if( SeeDeck == 'y' ) {
		PrintDeck( deck, SIZE);
		
	}

	
	
    printf("\n%s, pick a card and remember it...\n", name);

    /* Begin the card trick loop */
    for(i = 0; i < 3; i++)
    {
		
		/* Begin the trick by calling the function to deal out the first 21 cards */
		Deal( deck, play );
		

		/* Include error checking for entering which column */
        do
		{
			/* Ask the player to pick a card and identify the column where the card is */
			printf("\nWhich column is your card in (0, 1, or 2)?: ");
		} while(scanf("%d", &column)==0 || column < 0 || column > 2);
	  
		/* Pick up the cards, by column, with the selected column second */
		PickUp( deck, play, column );
			
    } //end 3 count for loop

    /* Display the top ten cards, then reveal the secret card */
	SecretCard( deck );
	
	

    /* if the player wants to play again */
    printf("%s, would you like to play again (y/n)? ", name);
    scanf(" %c", &PlayAgain);
    PlayAgain = tolower(PlayAgain); 
}  while(PlayAgain == 'y'); //edit out } preceding while

/* Exiting message */
printf("\n\nThank you for playing the card trick!\n\n");
return;

} //End MAIN

/*BuildDeck function*/
void BuildDeck( int deck[], int size )
{
  int used[52] = {0};
  int card = 0, i = 0;

  /* Generate cards until the deck is full of integers */
  while(i < size)
    {
		/* generate a random number between 0 and 51 */
		card = rand() % 52;
		
		/* Check the used array at the position of the card.  
		   If 0, add the card and set the used location to 1.  If 1, generate another number */
		if(used[card] == 0)
		{
			used[card] = 1;
			deck[i] = card;
			i++;
		
		}

		if(used[card] == 1) {
			card = rand() % 52;
		}

    } //end while loop
	return;
}

/*PrintDeck function*/
void PrintDeck( int deck[], int size )
{
	int i = 0;

	/* Print out each card in the deck */
	while( i < 52 ) {
		
		PrintCard(deck[i]);
		printf( "\n" );
		i++;
	
	} //end while loop
	
	
}

/*Deal function*/
void Deal( int deck[], int play[][3] )
{
	int row = 0, col = 0, card = 0;

	/* deal cards by passing addresses of cardvalues from
	   the deck array to the play array                   */
	printf("\n\n");
	printf("   Column 0           Column 1           Column 2\n");
	printf("=======================================================\n\n");

	for( row = 0; row < 7; row++ ) {

		play[row][col] = deck[card];
		PrintCard( play[row][col]);
		card++;

		for( col = 0; col < 2; col++ ) {

			play[row][col] = deck[card];
			PrintCard( play[row][col] );
			card++;

		} //end ROW

		printf( "\n" ); //start new row

	} //end COL
	
	return;
}

/*PrintCard function*/
void PrintCard( int card )
{
	int rank = 0;
	int suit = 0;

	rank = card % 13; /*use remainder to determine rank*/
	suit = card / 13; /*use int division to determine suit
					  only values 0, 1, 2, 3 are possible*/

	if( rank == 0 ) {
		printf( " King" );
	}

	if( rank == 1 ) {
		printf( "  Ace" );
	}

	if( rank == 11 ) {
		printf( " Jack" );
	}

	if( rank == 12 ) {
		printf( "Queen" );
	}
	
	if( rank > 1 && rank < 11 ) {
		printf( "%5d", rank );
	}
	
	/*print "of" by itself*/
	printf( " of " );

	if( suit == 0 ) {
		printf( "Clubs     " );
	}

	if( suit == 1 ) {
		printf( "Diamonds  " );
	}

	if( suit == 2 ) {
		printf( "Hearts    " );
	}

	if( suit == 3 ) {
		printf( "Spades    " );
	}
	
	  return;
}

/*PickUp function*/
void PickUp( int deck[], int play[][3], int column )
{
  int card = 0, row = 0;

  if( column == 2 ) { //start IF column == 2

	printf( "New 2 Rules\n" );

	for( row = 0; row < 7; row++ ) {
		printf( "Col 2" );
		deck[card] = play[row][2];
		printf( "Pickup " );
		PrintCard( play[row][2] );
		printf( "Card number: %d", card );
		printf( "\n" );
		card++;
	}

	for( row = 0; row < 7; row++ ) {
		printf( "Col 1" );
		deck[card] = play[row][1];
		printf( "Pickup " );
		PrintCard( play[row][1] );
		printf( "Card number: %d", card );
		printf( "\n" );
		card++;
	}

	for( row = 0; row < 7; row++ ) {
		printf( "Col 0" );
		deck[card] = play[row][0];
		printf( "Pickup " );
		PrintCard( play[row][0] );
		printf( "Card number: %d", card );
		printf( "\n" );
		card++;
	}

  } //end IF column == 2
  
  
  else if( column == 1 ) { //start IF column == 1

	printf( "New 1 Rules\n" );

	for( row = 0; row < 7; row++ ) {
		printf( "Col 2" );
		deck[card] = play[row][2];
		printf( "Pickup " );
		PrintCard( play[row][2] );
		printf( "Card number: %d", card );
		printf( "\n" );
		card++;
	}

	for( row = 0; row < 7; row++ ) {
		printf( "Col 0" );
		deck[card] = play[row][0];
		printf( "Pickup " );
		PrintCard( play[row][0] );
		printf( "Card number: %d", card );
		printf( "\n" );
		card++;
	}

	for( row = 0; row < 7; row++ ) {
		printf( "Col 1" );
		deck[card] = play[row][1];
		printf( "Pickup " );
		PrintCard( play[row][1] );
		printf( "Card number: %d", card );
		printf( "\n" );
		card++;
	}

  } //end IF column == 1


    else if( column == 0 ) { //start IF column == 0

	printf( "New 0 Rules\n" );

	for( row = 0; row < 7; row++ ) {
		printf( "Col 1" );
		deck[card] = play[row][1];
		printf( "Pickup " );
		PrintCard( play[row][1] );
		printf( "Card number: %d", card );
		printf( "\n" );
		card++;
	}

	for( row = 0; row < 7; row++ ) {
		printf( "Col 2" );
		deck[card] = play[row][2];
		printf( "Pickup " );
		PrintCard( play[row][2] );
		printf( "Card number: %d", card );
		printf( "\n" );
		card++;
	}

	for( row = 0; row < 7; row++ ) {
		printf( "Col 0" );
		deck[card] = play[row][0];
		printf( "Pickup " );
		PrintCard( play[row][0] );
		printf( "Card number: %d", card );
		printf( "\n" );
		card++;
	}

  } //end IF column == 0
	
	return;
}

/*SecretCard function*/
void SecretCard( int deck[] )
{
	int card = 0;

	/*print 11th card in deck*/
	printf("\nFinding secret card...\n");
	for(card = 0; card < 10; card++) {
		PrintCard(deck[card]);
		printf( "\n" );
	}

	printf( "\nYour secret card is: " );
	PrintCard(deck[card]);
	printf( "\n" );
	return;
}

Edited 6 Years Ago by CleanSanchez: n/a

Your Deal function is very very wrong. It may cause all sorts of problems (including the one you observe).

so many if's... so little switches...

You should consolidate all your printf's wherever possible so that the logic can also be consolidated.

I also suggest that you convert all your hard coded numbers into enumerations so that its more legible.

This isn't a solution, just a coding suggestion.

Edited 6 Years Ago by N1GHTS: n/a

You've got:
If it's column 2 - 2, 1, 0
If it's column 1 - 2, 0, 1
If it's column 0 - 1, 2, 0
Shouldn't column 2 be 0, 1, 2?

Your Deal function is very very wrong. It may cause all sorts of problems (including the one you observe).

Care to elaborate?

so many if's... so little switches...

You should consolidate all your printf's wherever possible so that the logic can also be consolidated.

I also suggest that you convert all your hard coded numbers into enumerations so that its more legible.

Coding tips are always appreciated.. any examples?

You've got:
If it's column 2 - 2, 1, 0
If it's column 1 - 2, 0, 1
If it's column 0 - 1, 2, 0
Shouldn't column 2 be 0, 1, 2?

Technically speaking;
Col 0: 1-0-2 or 2-0-1
Col 1: 0-1-2 or 2-1-0
Col 2: 0-2-1 or 1-2-0

but for whatever reason the way I have it written makes it work... well, work-ish

A switch is easier to read than a bunch of if statements.

void PrintCard( int card ) {

	int rank = card % 13; /*use remainder to determine rank*/
	int suit = card / 13; /*use int division to determine suit
                                only values 0, 1, 2, 3 are possible*/
        switch (rank) {
            case 0:  printf( " King" ); break;
            case 1:  printf( "  Ace" ); break;
            case 11: printf( " Jack" ); break;
            case 12: printf( "Queen" ); break;
            default: printf( "%5d", rank ); break;
        }
        switch (suit) {
            case 0:  printf( " of Clubs     " ); break;
            case 1:  printf( " of Diamonds  " ); break;
            case 2:  printf( " of Hearts    " ); break;
            case 3:  printf( " of Spades    " ); break;
        }
}

A little tough going thru all that non-structured stuff with NotePad, However,
I do see a couple of interesting items:

(1)
By switching options 1 & 0 then (of course) option 1 works fine.
-Meaning: It's not in the pickup subrt'n ( I thought you said it might be there)

(2)
By looking at the Tuple of DECK, I see that K of C is 0,0,0.
I'm sure you saw/know this by viewing your watch list during a step-thru.
However, You'll quickly realize that this is an INIT'lation error.
At some-point (to be determined) you are re-init'ling your deck or your pointer to point to element 0,0,0.
(Thus causing KofC to appear each time.

more later.

Shift-Stop
ps, the other guys are entirely right- The code really needs to be re-structured.

Follow-up,
Since KofC is being ADDED into the 0th element (and the last card is being rotated (Pushed )out, then I would ask myself WHY is anything being added?
Secondly,
when I print the VARs in the PickUp subrt'n then I see that the 0th card is -Already- KofC -

When I review the code I see that there is nothing between my pressing "2"
and seeeing KofC in Pos 0.
Therefore,
I believe the error is Not in Print subrt'n
Not in the PickUp subrt'n
Not in the 'Your Choice Now" subrt'n
That only leaves two remaining subrt'ns.
The RND "Load the Deck" is beginning to look very bad at this point.

My guess is that during the DEALing process, KofC is being re-introduced
as a 22nd card at position CARD[0]

I'm not willing to finish the homework ass'ment 4 U
but I think you can get there from here.

Best of luck at USF !

Shift-Stop

Thank you guys soooo much for all of the input! I'm going to spend some time this week (was working all weekend) to try and iron out the kinks. Will probably talk to my prof as well. Thanks again for all the help.

This article has been dead for over six months. Start a new discussion instead.