Playing Cards In C

0
294
C and Cards

Over my career as a software developer, I ran into a lot of code that I considered sh*t. I say this because it was clear to me that the developers who were writing the code, did so, without caring about other people who had to read it and maintain it.

Write Clean Understandable Code. Not Obfuscated Shit.

Some of these software developers were very good at what they did and had brilliant minds. But for aesthetic styling and architectural reasons, having to wade through it was more than worth the BS.

I want to give an example of what I consider “clean, well structured code” that is easy to read and understand. The kind of code that doesn’t need comments because the code reads well enough all on its own. I want you to put yourself in the frame of mind of your boss telling you that you are now the owner of this code and you have to maintain it.

The Code

Go through this and see how fast you can digest it.

  1. #include "stdafx.h"
  2. #include <stdlib.h>
  3. #include <time.h>
  4.  
  5. enum suit { Clubs, Diamonds, Hearts, Spades };
  6. enum face { Ace, Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King };
  7.  
  8. char *suitStrings[] = { "Clubs", "Diamonds", "Hearts", "Spades" };
  9. char *faceStrings[] = { "Ace", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King" };
  10.  
  11. typedef suit SUIT;
  12. typedef face FACE;
  13.  
  14. typedef struct {
  15.   SUIT s;
  16.   FACE f;
  17. } Card;
  18.  
  19. typedef struct {
  20.   int numCards;
  21.   Card *cards;
  22. } Deck;
  23.  
  24. char *SuitEnumToString(enum suit s) {
  25.   return(suitStrings[s]);
  26. }
  27.  
  28. char *FaceEnumToString(enum face f) {
  29.   return(faceStrings[f]);
  30. }
  31.  
  32. Deck* CreateDeck() {
  33.   int numCards = 0;
  34.   for (SUIT s = Clubs; s <= Spades; s = SUIT(s+1)) {
  35.     for (FACE f = Ace; f <= King; f = FACE(f+1)) {
  36.       ++numCards;
  37.     }
  38.   }
  39.  
  40.   Deck *deck = new Deck;
  41.   deck->cards = new Card[numCards];
  42.   deck->numCards = numCards;
  43.  
  44.   int i = 0;
  45.   for (SUIT s = Clubs; s <= Spades; s = SUIT(s + 1)) {
  46.     for (FACE f = Ace; f <= King; f = FACE(f + 1)) {
  47.       deck->cards[i].s = s;
  48.       deck->cards[i].f = f;
  49.       ++i;
  50.     }
  51.   }
  52.  
  53.   return(deck);
  54. }
  55.  
  56. void ShuffleDeck(Deck *deck) {
  57.   srand(time(NULL));
  58.   for (int i = 0; i < deck->numCards; ++i) {
  59.     int randomIdx;
  60.     Card tempCard;
  61.  
  62.     randomIdx = rand() % deck->numCards;
  63.     tempCard = deck->cards[i];
  64.     deck->cards[i] = deck->cards[randomIdx];
  65.     deck->cards[randomIdx] = tempCard;
  66.   }
  67. }
  68.  
  69. void ShowDeck(Deck *deck) {
  70.   for (int i = 0; i < deck->numCards; ++i) {
  71.     printf("%s of %s\n", FaceEnumToString(deck->cards[i].f), SuitEnumToString(deck->cards[i].s));
  72.   }
  73. }
  74.  
  75. void CleanupDeck(Deck *deck) {
  76.   delete [] deck->cards;
  77.   delete deck;
  78. }
  79.  
  80. int _tmain(int argc, _TCHAR* argv[])
  81. {
  82.   Deck *deck = CreateDeck();
  83.   ShuffleDeck(deck);
  84.   ShowDeck(deck);
  85.   CleanupDeck(deck);
  86.   return 0;
  87. }

Was it that bad? Did you have to struggle trying to understand what was going on? Getting caught up with language syntax? Poor indentation and styling? You should have been able to get through this in less than 5 minutes. Regardless if you know the C language syntax and got hung up on all the little things shouldn’t have been your frame of mind. Instead, you should have been focusing on the overall structure of the program. Was it easy to find things? Did you get a good feel for the algorithms and rules?

When you use enumerations and typedefs, it makes for an easier code read. Functions are appropriately named. Conversions from enumerations to character strings are trivial. Iterations through a deck of cards is intuitive.

Be A Professional. Be A Software Architect.

I grew up with a father who was an architect. He was damn good at what he did. He had to pay attention to detail while being creative at the same time. Dad designed the old Apple Computer headquarters for then CEO John Scully. The building stands as a testament to Silicon Valley. I saw things differently in an aesthetic and structurally sound perspective. I saw balance, cohesiveness, and appreciation in what it took to make things simple, not complex.

Apple Headquarters Cupertino

Write code like this. Refer to it often. Be a professional software architect and showcase your talent. Not write shit that is hard to read and understand. A skilled software developer is someone who can take the complicated and turn it into something simple. Not create obfuscated shit meant only for his eyes but for others.

Write software not for your eyes and mind, but for others.

The Shuffling Algorithm

One of the most important things in playing card simulations is the shuffling algorithm. In this example, I use a randomized swap algorithm. The key piece is the random number generator. If you want something more faster and sophisticated consider replacing the C rand() and seed function with a Mersenne Twister. I’ll leave that exercise for you to implement.

Of Interest