(upbeat music)
- [Instructor] In the last movie we looked at
deal_cards.CPP from chapter 10 of the exercise files
to see how the deck class was used.
And in this movie we're going to actually look at
the code for the deck class.
I want to start with the BWexception.h.
We've seen this before.
The only difference here is
I've put it in its own header file.
But also you'll notice these if define,
and define, and end if,
and this is called an include guard,
and we'll cover this in a little more detail
in the advanced topics companion course,
but this simply prevents a header from being
included more than once.
And other than that, this is in the namespace BW.
It inherits from the exception classes.
This is really exactly the same
as we've seen elsewhere in this course.
Let's take a look at the deck.h file.
This is the header file for the deck class.
And again, it's an include guard.
And that ends down here at the bottom,
as does the namespace.
We're in this namespace here,
and I've included a number of libraries
from the C++ standard library,
and also the memory, which is specific to C++,
which supports the new and delete operators.
A lot of this will be used in the implementation file,
but they're included here
cause the implementation file includes this,
and so it ends up in both places.
and here's our namespace.
And you'll notice I have some type defs.
For a lot of reasons I like to use integers
of a specific size.
Rather than just saying int or long int,
I like to know that I'm getting a 32 bit int or 64 bit int,
especially when I'm writing code for mobile,
where the size of the code might actually
really, really matter.
And so I try to use the smallest size ints can
for a particular purpose.
And we'll see that as we go through here.
We have some constants for a C string
with each of the suits,
a C string with each of the letter ranks,
ace, 10, Jack, queen, king.
And then the default deck size is 52,
and that's an eight bit integer.
These are all eight bit integers
because they don't ever need to be large values.
So again, I'm trying to save space here.
In fact, here's the struck for an individual card,
and it has two four bit integers by using bit fields here.
And so the suit and the rank should both fit
in the space of an eight bit integer on most systems.
That's not guaranteed to be true,
but on most systems and certainly on mobile
that's going to be observed.
And then we have the class for the deck itself.
So I have some data members here.
I like to use an underscore at the beginning of the name
for a data member.
I only do that when I'm in my namespace.
If you do that in the general namespace,
you risk colliding with other system identifiers,
and that's a bad thing.
And so, because I'm using my own namespace, namespace BW,
I can get away with this.
And I like to do this.
It's a quick indicator to me when I'm reading the code,
that these are private data members,
and likewise, these are private function members.
These are members that are not part of
the public interface to the class,
but they're used just internally.
So I have init deck, delete deck, create deck,
and an overall init.
And we'll see the code for that in the CPP file.
I'm disallowing a copy constructor,
and I'm disallowing the assignment operator
cause I don't really want to be able to do that
to my deck of cards.
Once I have a deck of cards,
I don't want to be able to copy it.
Just sort of an integrity thing with cards.
And so here I have a constructor for single deck,
and I have a constructor for multiple decks,
and a move constructor.
And we'll talk more about move semantics
in the advanced topics course and a destructor.
And then I have utilities for creating a new deck,
or for creating a new deck with more than 52 cards in it,
for shuffling the deck,
and for getting a specific individual card
from a specific place in the deck.
There may be times when I would want to do that,
or for just dealing a card,
which takes the deck off the top and decrements the count.
And then we have our info functions,
remaining, deck size, and a pointer to the array of cards.
And so, there we have it.
We have a non-member function for displaying a string
of a particular card,
that five of hearts or Jack of clubs, those two characters.
And this is a non-member function
because the card structure is outside of the class.
And so it should be a non-member function.
Let's take a look at the CPP file.
Look at the implementation.
We're not going to go through this all in detail,
but there's a few things that we're going to want to see here.
Our constructors.
Well, here's the destructor, which calls delete deck.
And you notice the delete deck has that underscore
because it's a private function.
And when we look here at delete deck,
oh, it looks like it's right there.
It checks to see if we have a pointer.
If we do, we call delete to deallocate
the memory for the deck.
We set the pointer to null,
and we set the remaining count to zero.
So that's really all there is in delete deck.
Init, initializes all the stuff,
and this is called by our constructors.
And so it sets up the seed for the random number generator.
We run it once for those systems
that don't seem to work properly the first time out.
We call create deck,
which is another private function,
and we call shuffled deck,
and we'll take a look at those in a minute.
And the move constructor, again,
we'll talk about move semantics
in the advanced topics course,
but this allows us to move one deck
from one place to another without leaving it behind.
So that's not really necessary for our purposes
for this exercise.
You probably don't have this in your solution.
It's just there for completeness.
And again, you can learn more about move semantics
in the advanced topics course.
And here we have our utilities.
We have init deck,
which calls delete deck, and it checks the number of decks,
and throws an exception if it's out of range,
and it just sets up the space,
and it calls new on our deck pointer for the array of cards,
and it allocates space for those cards.
And then create deck actually initializes.
It goes through these loops around suits and ranks,
and it initializes all of the cards in order,
and then we can call shuffle to shuffle them.
But when we create a new deck,
everything is in order just like when you unwrap
a new deck of cards from its packaging.
And down here is shuffle deck,
which simply goes through the deck
and calls the standard library function swap,
and it just swaps cards.
And it does that randomly using the random number generator.
And so that shuffles our deck, very simple.
We can get a specific card at a particular index,
and we can deal a card.
Here's deal a card,
which basically just returns a card off the top of the deck
and decrements the count.
Simple as that.
And here's our little info functions, the size of the deck,
the remaining cards, the pointer to the deck itself.
And then here's our non-member function
that prints out a card with its rank and its suit.
And again, you might've seen me use this trick before
where I'll take a reference to a particular element
in our array and give it a name.
And this just allows my code to be a little more readable.
It doesn't actually generate any code.
Doesn't take up any space.
The compiled code comes out the same,
but rather than calling it outstring sub one,
I can call it outstring suit, which is nice and useful.
And here, if the rank is zero, we know it's an ace.
If the rank is greater than eight, we know it's a face card,
10, Jack, queen, king.
And otherwise it's one of our numeric cards. Very simple.
So now we can come over here to deal cards.
We have all our code.
We've seen this before.
We simply compile and run.
And I see I left this at five cards from the last movie.
Normally, this would be just a single deck,
and there's that.
So this is my solution to the challenge.
Obviously your solution will be different.
You may or may not use the STL.
You may or may not use some of the features
that we haven't covered completely in this title,
but that's an idea of how this works.
Feel free to experiment with this code and learn from it,
and I hope this exercise and this course
has been valuable to you.