# Thread: Simple problem, I hope...

1. ## Simple problem, I hope...

Hi, I'm new to programming in general and I'm attempting to write a text based game of black jack for a bit of practice. I've just started the project and run into something weird that I really can't explain. So far all I'm doing is defining a function that creates a data structure database for each individual card and having the main function print the suit and a number value corresponding to how many "cards" are in the deck. I can't figure out why it spits back junk for cards 2 - 7 and then proceeds to print correctly. Any ideas? When it prints, it looks like this:

Code:
```h deckValue = 1
deckValue = 1
\304 deckValue = -1809827132
\206 deckValue = -1605732986
\206 deckValue = -1605732986
deckValue = 2139062143
h deckValue = 32639
h deckValue = 8
h deckValue = 9
h deckValue = 10
h deckValue = 11
h deckValue = 12
h deckValue = 13
d deckValue = 14
d deckValue = 15
d deckValue = 16
d deckValue = 17
d deckValue = 18
d deckValue = 19
d deckValue = 20
d deckValue = 21
d deckValue = 22
d deckValue = 23
d deckValue = 24
d deckValue = 25
d deckValue = 26
c deckValue = 27
c deckValue = 28
c deckValue = 29
c deckValue = 30
c deckValue = 31
c deckValue = 32
c deckValue = 33
c deckValue = 34
c deckValue = 35
c deckValue = 36
c deckValue = 37
c deckValue = 38
c deckValue = 39
s deckValue = 40
s deckValue = 41
s deckValue = 42
s deckValue = 43
s deckValue = 44
s deckValue = 45
s deckValue = 46
s deckValue = 47
s deckValue = 48
s deckValue = 49
s deckValue = 50
s deckValue = 51
s deckValue = 52```

2. How about putting some code in those code tags?

3. Originally Posted by anduril462
How about putting some code in those code tags?
You're hopeless, Anduril!

You STILL want to see ACTUAL CODE, to debug a C program?

Must be a slow learner!!

4. He's new here, and telepathic abilities take time to develop.

5. Originally Posted by Polaris84
Hi, I'm new to programming in general
While the others are having their little joke the fact is there's nothing in what you posted that even remotely resembles C programming code.

If you haven't already, you need to grab a good book on the topic or at least read some of the many tutorials on the web.

There's also a list of book recommendations here...
http://cboard.cprogramming.com/c-pro...endations.html

You're hopeless, Anduril!

You STILL want to see ACTUAL CODE, to debug a C program?

Must be a slow learner!!
I'd prefer it if they mailed me their punch cards, but I'm trying real hard to adapt to this new-fangled interweb thing.

@Polaris84
Do post your code for this so we can help you. My first two guesses would be uninitialized variables or buffer overflow somewhere, but it's really hard to say without seeing your code.

7. Haha, right, code might help you. So I have made a temporary fix that keeps everything printing right, but it seems unnecessary. Here is the code for creating the deck of cards.

Code:
```#include "deck.h"
#include "main.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

void	intializeDeck()
{
struct	Card*	newCard = NULL;
int		deckOf52 = 1;	// keeps track of how mand cards are in the deck and gives deckValue its value.
int		x = 0;		// gCard array value.
int		y = 2;		// used to give numCard face value.
int		z = 1;		// used to give card numarical value.

while (deckOf52 < 53)
{
if(deckOf52 < 14)
{
gCard[ x ].suit = 'h';
}
if(deckOf52 > 13 && deckOf52 < 27)
{
gCard[ x ].suit = 'd';
}
if(deckOf52 > 26 && deckOf52 < 40)
{
gCard[ x ].suit = 'c';
}
if(deckOf52 > 39)
{
gCard[ x ].suit = 's';
}
if( z == 1 )
{
gCard[ x ].nonNumCard = 'A';
}
else
{
if( z == 11 )

{
gCard[ x ].nonNumCard = 'J';
}
else
{
if( z == 12 )
{
gCard[ x ].nonNumCard = 'Q';
}
else
{
if( z == 13 )
{
gCard[ x ].nonNumCard = 'K';
}
else
{
gCard[ x ].numCard = y;
}
}
}
}

gCard[ x].cardValue = z;

z += 1;
if( z == 14 )
z = 1;

gCard[ x ].deckValue = deckOf52;

y += 1;

if(gCard[ x ].nonNumCard == 'A' || gCard[ x ].nonNumCard == 'J' || gCard[ x ].nonNumCard == 'Q' || gCard[ x ].nonNumCard == 'K')
{
y = 2;
}
if( y == 11 )
{
y = 2;
}

deckOf52 += 1;
x += 1;

newCard = realloc(gCard , 1 + sizeof(struct Card));
gCard = newCard;
}

}```
and how I'm printing them now with the fix I mentioned

Code:
```#include "deck.h"
#include "main.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

struct	Card*	gCard = NULL;

int main ()
{
int		x = 0;

gCard = malloc(sizeof(struct Card));

printf("Black Jack!\n\n");

while(x < 52)
{
intializeDeck();	// function used to be called before this loop when I was having the problem

if(gCard[ x ].nonNumCard == 'A' || gCard[ x ].nonNumCard == 'J' || gCard[ x ].nonNumCard == 'Q' || gCard[ x ].nonNumCard == 'K')
printf("%c of %c   deckValue = %d   cardValue = %d\n\n" , gCard[ x ].nonNumCard ,  gCard[ x ].suit , gCard[ x ].deckValue , gCard[ x ].cardValue);
else
printf("%d of %c   deckValue = %d   cardValue = %d\n\n" , gCard[ x ].numCard ,  gCard[ x ].suit , gCard[ x ].deckValue , gCard[ x ].cardValue);

x += 1;
}

return 0;
}```
OH, and here is the data struct declaration.

Code:
```struct	Card
{
int		cardValue;			// Numerical value of card, such as Jack = 11, A = 1 or 11, Queen = 12, etc.
int		deckValue;			// deckValue = the numerical value of the card in the deck of 1 - 52, starting from "Ah" being "1", "2h" being "2", etc.
char	suit;
char	nonNumCard;
int		numCard;
};

struct	Card*	gCard;```

8. So the big problem seems to be that you call realloc with 1+sizeof(struct Card) bytes. That doesn't grow it by 1 each time, that simply takes gCard, and makes sure it's reallocated to only one more byte than a single card needs. This will mean gCard[x] is out of bounds for any x other than 0. You actually don't need to dynamically allocate space for your deck at all. There will always be 52 cards. Make a constant (something like CARDS_IN_DECK) and an array, like Card deck[CARDS_IN_DECK].

You really only need to keep track of the suit and face value. You can create an enum for suit and just use 0-12 for the face. Use a functions to get the cards playing value, suit and face. It will mean only one type of printf for displaying a card (instead of the two you have in main). For example:
Code:
```enum {
HEARTS,  // this defaults to 0
DIAMONDS
...
};
char getSuit(Card *c)
{
switch (c->suit) {
case HEARTS:
return 'h';
break;
...
}
}```
You can use / and % instead of your if (deckOf52 > 26 && deckOf52 < 40) to make assigning suit and face easier:
Code:
```for (card_num = 0; card_num < CARDS_IN_DECK; card_num++) {
deck[card_num].suit = card_num / CARDS_IN_SUIT;  // this would be a constant defined as 13
deck[card_num].face = card_num % CARDS_IN_SUIT;```
I don't really understand what you're using x, y and z for, but I'm pretty sure they're not really necessary (besides, you're assigning y to numCard without actually setting it).

Some general notes that might clean up your code a bit:
• Global variables are evil. Declare them in the appropriate function and pass them around.
• x += 1; can be turned into the more common x++;
• Replace your while loops with for loops (they're easier to read for array and counting loops). E.g.

Code:
```x = 0;
while (x < 42) {
x++;
}
// same as the cleaner, more common:
for (x = 0; x < 42; x++) {
}```
That's all I have for now, but it should keep you busy for a while.

9. Macros are fun.

#define SUIT(card) ("CDHS"[((card)/13)%4])
#define FACE(card) ("A23456789TJQK"[(card)%13])

Quzah.

10. Okay, thanks for the tips, this is all stuff I haven't considered. The tutorial I read seemed to discourage the use of switch() statements since there is no real disadvantage to using if() statements and they are "more versatile", but lots of people seem to use switch() over if(). I have been meaning to incorporate the for() loop more often, but I got all nice and cozy with the while() loop that I just don't like to touch them. I can see what you mean about making it easier to read, but only in some cases when the meat of the loop can all be stated in one set of parameters, i.e. when x is the only variable being altered in the loop. x y & z are all just expendable int's that I can use to do calculations when I need to. They're values and purpose can be changed but generally I use them for similar purposes throughout code. In intializeDeck() function, y tracks number cards by resetting back to '2' once it reads z = the value of a char card(1,11,12,&13). z tracks the play value of the card(1 -13).

Also, how can globals be all that bad? It seems like they can prevent you from doing a lot of work. It seems like you should have all of your most important variables and data that your whole program will be using in one place, that is if it needs to be consistent data passed around in multiple functions in multiple libraries. If something goes wrong, you don't have to potentially sift through several files of code because your only tossing variables into functions and returning them. In this case, the ONLY global I'm truly using is a struct pointer because that struct and its contents will need to be called within other functions in order to obtain info on one card, i.e. in a shuffleDeck() function, or dealDeck() function. Seems way easier to see and know its all in one place.

11. In C, global variables are more of a headache, since C programs tend to use pointers a lot.

When the structs are prototyped globally, but the variable or struct array itself is local and passed around to other functions as needed, it gives you the best encapsulation of the variables and makes bug hunting, a LOT easier.

The classic one is where you have a global variable, and accidentally name a local variable with that same name. The local "covers up" the global and although you know everything checks out in the local function, it somehow "dies" when the program returns from that function. WTF??

In a blackjack program, having the deck of cards global seems intuitively right. It's such a small program, and there is just one deck in play at a time, etc. With larger programs, I'd make everything local if you can.

I used to use globals heavily, coming from QBASIC. Now it's rare that I use one global variable in a program.

12. Globals generally hurt more than they help, and it's a practice I think should be discouraged when learning C. There are times when globals are appropriate, but IMO, this is not one of them. To be fair, this is not a horrible use of them, but there's no really good case for this either, other than "I don't want to pass it around".

Your arguments for globals are common fallacies. The small effort of passing them around greatly outweighs the headaches that come with debugging code that uses globals. You actually have to sift through more code with globals, because anything could have changed the global variable, instead of just a handful of functions. Think of it this way: if you have a tool that others want to use, you can either leave it on your front porch and let whoever use it when they want (globals), or you can only loan it out to individuals who come and ask for it in person (locals). If your tool comes back broken or doesn't come back at all, which scenario makes it easier to determine who's responsible for the loss/damage (bug)?

The link in my previous post gives a good discussion on the topic, so here it is again: Global Variables Are Bad.

13. Originally Posted by Polaris84
Also, how can globals be all that bad?
Code:
```#include <stdio.h>

int a = 0;

int multiply(int q)
{ int x = 1 ;
for (a = 2; a < 6; a ++)
x *= q;
return x; }

int main (void)
{ int z;
printf("Enter a 3 digit number : ");
scanf("%d",&a);
z = multiply( a );

printf (Input = %d  Result = %d\n\n",a,z);
return 0;
}```
Now... imagine multiply() is half way down a 10,000 line program... have fun finding it!

14. Originally Posted by CommonTater
Now... imagine multiply() is half way down a 10,000 line program... have fun finding it!
CTRL+F

Quzah.

15. Originally Posted by quzah
CTRL+F
Quzah.
I meant finding "the bug"... You can search for every instance of a, but that's a lot of searching... and it might not easily lead you to what is changing the value of a.