1. ## Returning a char?

Hello All!
I was trying to create a random card, like from a deck of cards, and I've been having some trouble. If there was a way to return a char, I feel the problem would be much easier. (I realize I could do the same thing assigning a global variable)

I'm VERY new to coding, so take it easy on me!

Code:
```int card (void) {
//Draws a random card
srand(time(NULL));

int cardNum = rand()%13;
int tag = rand()%4;

//Assigns rank of card, and returns it
if (cardNum >= 10) {
if (cardNum == 10)
char rank = 'J';
else if (cardNum == 11)
char rank = 'Q';
else if (cardNum == 12)
char rank = 'K';
else if (cardNum == 13)
char rank = 'A';
}
else int rank = cardNum +2;

//Assigns suit of card, and modifies a global character
if (tag == 0)
suit = 'D';
else if (tag == 1)
suit = 'C';
else if (tag == 2)
suit = 'H';
else suit = 'C';

return rank;
}```
I want to return the rank variable, which is either an int or a char, depending on it's original value.

2. You should either return a struct object representing a card with both rank and suit, or return a single number that uniquely identifies rank and suit.

By the way, move this:
Code:
`srand(time(NULL));`
to near the start of your main function. srand should only be called once in your program to seed the pseudorandom number generator, whereas rand would be called whenever you want to generate a pseudorandom number.

3. srand() should only be called once in your program. Put it early in main.

cardNum is rand() % 13, so it will be 0 to 12, inclusive. So cardNum == 13 will never be true. Your numbers in this section should go from 9 to 12 (Jack is 9).

"rank variable, which is either an int or a char"
Not in C. You need to pick one or the other. Make it a char and set it like so:
Code:
`char rank = "23456789TJQKA"[cardNum];`
I'm not sure what you mean by "a way to return a char".
If you want to return a char, return a char. Or have you made a double typo and meant "return a card"? I.e., you'd like to return both the rank and suit.
Code:
```typedef struct Card {
char rank;
char suit;
} Card;

Card rnd_card(void) {
Card c;
c.rank = 'T';
c.suit = 'H';
return c;
}```
Alternatively, you can represent a card as a random int from 0 to 51, inclusive. When you need the suit, just use (ncard / 13), when you want the value use (ncard % 13) (possibly + 2, depending on your purpose).
Code:
```#include <stdio.h>

#define CARD_STRING "23456789TJQKA"
#define SUIT_STRING "CDHS"

int print_card(int card) {
printf("%c%c ", CARD_STRING[card % 13], SUIT_STRING[card / 13]);
}
int main(void) {
for (int i = 0; i < 52; i++)
print_card(i);
putchar('\n');
return 0;
}```

4. Hey guys, thanks for the help. I managed to get it working by just creating global variables and modifying them.

As for the srand(), I used to think that it needed to be put in each one of the functions it's used in, so thanks for the update! Clearly I have much to learn...

5. Originally Posted by Ascend
I managed to get it working by just creating global variables and modifying them.
Global variables should be avoided. You should become familiar with passing values to (and returning values from) functions.

6. Return a unsigned char
the lower 4bits is: 1(ace) to 13 (king) value
the next 2 bits is family: (0-3)

char getcard(void){
return ((rand()%13 +1) | ((rand()%4) <<4));
}

7. Return a unsigned char
the lower 4bits is: 1(ace) to 13 (king) value
the next 2 bits is family: (0-3)
Code:
```char getcard(void){
return ((rand()%13 +1) | ((rand()%4) <<4));
}```
Not that different from using base-10 numbers in a similar fashion (ie suit and rank are incorporated into a unique ID number). I have a strong dislike for solutions that use bitwise operations for no apparent reason than "just because." Hardware prefers to work in larger segments of memory.

Also, you're not special, post with code tags.

8. Could always spilt it up on byte boundry
Code:
```typedef union cardTag{
unsigned int card;
struct{
char value;
char family;
};
}cardunion;

int getcard(void){
return ((rand()%13 +1) | ((rand()%4) <<8)); // little endian int
}```

9. Originally Posted by Matticus
Global variables should be avoided. You should become familiar with passing values to (and returning values from) functions.
Why should global variables be avoided? Is it just bad practice or do they make for a more intensive program?

10. Originally Posted by Ascend
Why should global variables be avoided? Is it just bad practice or do they make for a more intensive program?
Global variables are generally considered bad practice, especially during the learning phase.

As programs become larger, it becomes more difficult to keep track of where global variables are updated, as their value can be changed by any functions in the same scope. This also makes reading the code more difficult, since it's not immediately obvious who might be changing their value. Additionally, this makes troubleshooting a lot more difficult for the same reason.

Global variables also threaten modularity, which is a goal for writing clean, maintainable, and testable code. Functions should receive the data they need to work with, and return a value if necessary. Once functions start reaching outside themselves to interact with data, it becomes easier for the code to become tangled. Functions should be used to reduce coupling between pieces of code - otherwise, changing one function might accidentally break something else that relies on the same global data. This makes the program a lot more fragile, which may come back to bite you when you have to make changes later on. Functions utilizing global data also inhibit their reuse, since they become tied to that specific task.

There are other potential problems, as well, such as conflicts if the same variable name is accidentally used elsewhere in the program, which could lead to confusing bugs.

Most of these problems will not be encountered when you're still writing small "practice" programs, but it's still good to avoid globals. If you use them too much as a "quick fix" in the early stages, then you might come to rely on them as the size of your programs start to grow, which will eventually lead to the problems above. Also, by properly passing information to/from functions, you will develop good coding habits and cleaner logic as your experience develops over time.

11. Yea, that makes sense.

Thanks Matticus!

12. Originally Posted by whiteflags
Hardware prefers to work in larger segments
Care to explain?

13. Some MCU/CPU don't have good bit access or they have limited like ARM's bitfield shadow memory trick that it's only good for one bit at a time.
TI's MSP430 have BitTest,BitClear and BitSet instructions so it handles bits pretty good.
But copy bit-pair's from one bitfield to another bitfield you need 4-6 instructions, so that should be avoided.

14. I see. Thanks