Lab activity for Cards

You must have done the prelab first before attempting these problems.

Setup

Copy the files from the prelab activity (also new files hand.h/hand.cpp).

play.cpp, card.h, card.cpp, deck.cpp, deck.h, hand.h, hand.cpp, and a Makefile.

Problem 1: Debugging

Information below is particular the DDD debugger used with g++, you'll need to modify the instructions if you use a different environment

DDD is a visual debugger. It allows you to check the values of variables at any point in the program to see if they contain the value you think they should.

For this problem, you will be asked to write notes about what you do. You can put these in a README file in your directory, or write them on paper. Putting them in a README file gives you a more permanent record of what you're doing with the debugger.

Starting DDD

To run the program named play with the debugger, first compile the program ( make play ) and then to start the debugger, type: ddd play

Several windows will pop up. Wait patiently, it might take awhile. You can read and close the two grey Help and Tip of the Day windows. You should then see two windows, one large one that shows the code from play.cpp, which we will call the DDD window, and a small window of commands which we'll call the command window ( Run is the first command in this window).

Setting a BreakPoint

The first thing to do is to set a breakpoint. Then you will run the program and it will stop at this breakpoint, allowing you to check the values of variables.

In the DDD window, scroll down and find the line in the main function entitled

  player[k] = d.GetCard();

Set a breakpoint on this line by moving the cursor to the left end of the line, click the right mouse button and select Set Breakpoint. You will see a stop sign appear.

Set an additional break point on the line:

  Print(player);

Execute the program

To start execution of the program, you can either click on Run in the command window, or type run in the bottom half of the DDD window, beside the (gdb) prompt. Do this now.

The program runs until it encounters the first breakpoint. You'll see a lot of output scroll by (the output from printing the deck twice) at the bottom of the DDD window. Then you'll see an arrow beside the first stop sign, indicating execution paused on the line

  player[k] = d.GetCard();

Note this line has not been executed yet.

At the bottom of the DDD window, you will see the output so far followed by the message

  Breakpoint 1, main () at play.cpp:46

where 46 is the line number.

Stepping through the program one line at a time

From the breakpoint, you'll step through the program one line at a time to see how execution proceeds. For the line:

  player[k] = d.GetCard();

to execute, the GetCard function must first execute and return a value, and then the operator [] indexing function must execute.

In the command window, click on the Step button once. The GetCard function appears with the cursor set to the first line of this function:

    Card c;

In order for this line to execute, a card must be constructed, calling the constructor function for the Card class. Click on the Step button again.

The arrow is at the beginning of the default Card constructor. Click Step three more times (it has to execute each line in the initializer list) until it returns to the if statement in the GetCard function.

Let's check the value of myIndex. If you place the cursor over the variable myIndex, a little box will appear with the value 0. The value of myIndex also appears at the bottom of the window. Placing the cursor over Card c shows its value in a box (and also at the bottom of the window). Card c has the values given in the initializer list.

Since myIndex is 0, the condition on the if is true. Click on the Step button and the next line to execute is the first line in the body of the if. Click on the Step button to see this happen.

The arrow is now on the line:

   c = myCards[myIndex];

Click on the Step button several times until the arrow points to the line

   myIndex++;

Why did you have to click several times? The myCards[myIndex] line above uses the vector operator [] so it had to execute the lines in that function.

Check the value of myIndex, it should still be 0. Click on Step once to execute this line. Now check the value of myIndex, it should have changed to 1.

When debugging a program, you'll find DDD quite useful in checking the values of variables. When your program doesn't give the correct output, use DDD to check the values of variables. You'll think they are suppose to be one value and you might be surprised to see they contain a different value.

Using DDD is much faster than adding debugging output to your program. If you add cout statements to your program to debug, then you will have to recompile your program, and then later remove the statements and recompile again. With DDD, you just run the current executable and check the values.

Move to the next breakpoint

At this point, you'll stop the step by step execution and quickly move to the next breakpoint in the program by clicking the Cont (for continute) button in the command window. Do this now.

The arrow stops on the line.

  player[k] = d.GetCard();

Click Cont again, and the arrow is on the same line. That is because the execution is inside a loop.

Delete a breakpoint

Place the cursor over this stop sign, click the right mouse button, and select Delete Breakpoint. The stop sign will disappear.

Now click on Cont, and the arrow goes to the stop sign below on the line

  Print(player);

Click Cont one more time and you will see that the program completes execution.

Setting breakpoints in other files

When DDD first starts, it always brings up the file with the main function. Sometimes it is useful to set breakpoints in other files. You'll set additional breakpoints in the file deck.cpp and then execute the program again.

Click on File at the top left of the DDD window. Then select Open Source, scroll down to deck.cpp, and double right click on it. (or click on it once and then click on Open).

The file deck.cpp should appear.

In the Shuffle function, set a breakpoint on the line

  int k;

Also set a breakpoint on the last line of that function, the } that ends the function.

Displaying array values

Now you will execute the program again, this time displaying values of variables in arrays.

Click on the Run button. The program executes (displaying output at the bottom of the window) and stopping at the line right past the first breakpoint set in the Shuffle function.

Let's display the first three values in the array myCards. Put the cursor over the word myCards anywhere in the code, click on the right mouse button and select Display myCards. A Display window appears and a box with 1: this->myCards and shows that myCards has myCapacity 52 and mySize 52.

Put the cursor over the top of this box, right click and select New Display, then Other and a window appears. Change the words in the box to

   this->myCards[0]

and select Display.

A box displaying info about the 0th element in the array appears.

Right click on the box and select Show All and you will see the card in this position is the ace of spades (ace has rank 1).

Right click on the top of the box for element 0 and select New Display followed by Other, change the text in the box to:

   this->myCards[1]
and select Display.

The box containing the value in slot 1 appears (you may have to scroll to see it). Again, you will have to select Show All to show its contents, the ace of hearts.

Display the contents of myCards[2].

Now click on the Cont button, moving to the next breakpoint. The code for Shuffle has been executed, and the cards in the array have been shuffled. Look at the values in the display window for elements 0-2 and you will see that they have changed.

Write: In your README file, write down the new values of myCards[0], myCards[1] and myCards[2].

Click Cont to move to the next break point, the Print(player) at the bottom of the main function.

Note the values in the display window are gone, because they have gone out of scope.

Display the first three values in the player array.

To display the first value in player, put the cursor over the word player anywhere in the code, click on the right mouse button and select Display player. A Display window appears and a box with 1: player appears.

Write: In your README file, write down the capacity and size of player.

Put the cursor over the top of this box, right click and select New Display, then Other and a window appears. Change the words in the box to

   player[0]

and select Display.

Display the contents of player[1], and player[2]. Note that the three values displayed should be the three values you wrote down earlier.

Another way to show the value of an array element is to type the print command at the (gdb) prompt.

Print the contents of player[5] by typing:

   print player[5]

Note that this position was not assigned a value in the for loop above.

Write: In your README file, write down the value of player[5] and explain how it got its value.

Print the contents of player[20]. Note this position doesn't exist. You may have to scroll back to see the complete error message.

Write: In your README file, write down what happens when you print player[20].

To exit from DDD, select File, and then Exit.

Problem 2: The Hand class

This problem uses the Hand class in the files hand.h and hand.cpp.

Part 1:

Modify the main function in play.cpp to use the Hand class to create the hand (you won't need the tvector any more), to deal the hand, and to print the hand (you won't need the Print function in play.cpp anymore, instead use the Print function in the Hand class).

The class Hand encapsulates the tvector that was in main. You'll need to look at the hand.h file to see what you can do with a Hand object/variable, but the main ideas are to change main so that:

Part 2:

Currently a hand always consists of five cards, the 5 is a constant in the file hand.cpp. To be more general, you'll make it possible for hands to hold a varying number of cards.

First, create a new private instance variable int mySize in the class declaration in hand.h,

private: tvector<Card> myCards; int mySize; You'll need to initialize this in the constructor Hand::Hand, you should initialize it to have the value SIZE, which is 5. The best way to initialize mySize is in the initializer list: Hand::Hand() : myCards(), mySize(SIZE) { }

If you compile and run the program it should still works as it did before.

Now add a new function Hand::DealFrom that takes two parameters: the first is a Deck, the second is the number of cards to deal. You'll need to add the function prototype in the hand.h file and a body of the function in hand.cpp. Here's the prototype:

public: void DealFrom(Deck& d); void DealFrom(Deck& d, int numCards);

Note that it's ok to have two functions with the same names as long as the parameter lists are different.

You'll need to add the implementation of the new Hand::DealFrom to hand.cpp, it's very similar to the existing DealFromfunction, you might want to copy that and make small changes. You should remember to set the value of mySize in the new function, since the hand won't (necessarily) consist of five cards.

You'll also need to modify Hand::Print (currently always prints 5 cards). You should modify the function to use mySize. You'll need to test the new function by modifying play.cpp.

Part 3:

Extra Credit

Write the function Hand::IsFlush() whose header is shown below.

bool Hand::IsFlush() const which returns true if the hand is a flush, all cards the same suit, and returns false otherwise.

In addition, you'll need to modify hand.h to include the the prototype:

public: bool IsFlush() const;

In play.cpp, you should show the use of this function. To test it you can deal a hand of one card, that should return true no matter what. You can deal several other hands to test whether your function works.


Owen L. Astrachan
Last modified: Sun Nov 21 20:09:21 EST 1999