Chapter 12 Exercise Set 0: Chapter Review

  1. Create files named Cards.h and Cards.cpp to hold the Card object developed in this chapter. Create a test_cards.cpp with the following contents:

    #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
    #include <doctest.h>
    #include <iostream>
    #include <string>
    #include "Cards.h"
    using namespace std;
    
    TEST_CASE("Test can create Cards") {
        Card c1;
        CHECK(c1.suit == 0);
        CHECK(c1.rank == 0);
        Card c2(3, 4);
        CHECK(c2.suit == 3);
        CHECK(c2.rank == 4);
    }
    

    This first test case tests that cards can be created using two constructors, one that takes no arguments and one that takes two. Put the Card struct, complete with the two constructor prototypes in Cards.h.

    Then write the function definitions for the two constructors in Cards.cpp. Be sure to add: #include "Cards.h" at the top of the file.

    Compile the test program with:

    g++ test_cards.cpp Cards.cpp -o test_cards -std=c++11
    

    and run it. It should report four passing tests.

  2. Add the following test case to test_cards.cpp:

    TEST_CASE("Test can render Cards") {
        Card c3(3, 12);
        CHECK(c3.to_string() == "Queen of Hearts");
        Card c4(2, 10);
        CHECK(c4.to_string() == "10 of Diamonds");
        Card c5;
        CHECK(c5.to_string() == "Joker");
    }
    

    You’ll need to add #include <string> at the top of both Cards.h and Cards.cpp. Then add the member function prototype:

    std::string to_string();
    

    to the Card struct declaration in Cards.h, and add this function definition to Cards.cpp:

    std::string Cards::to_string() {
        return "I am a string!";
    }
    

    This should compile without errors, and running test_cards should now report three failing tests.

    Finally, fix to_string so that the tests pass.

  3. Add tests for the ==, > and <= operators for Cards. Use the same process you used in the previous exercise to write tests first, write just enough scaffolding code to make the tests compile (and fail), and then finally write member function definitions to make the tests pass.

    Tests for == might look something like this:

    TEST_CASE("Test comparison of Cards") {
        Card c1(2, 9);
        Card c2(1, 10);
        Card c3(1, 10);
        CHECK(c1 == c2 == false);
        CHECK(c2 == c3 == true);
    }
    
  4. Again use this TDD process to add member functions for <, >= and !=.

  5. In the version of Card introduced in this chapter, aces are less than deuces (2s). Add the following tests and then change this so that aces are ranked higher than Kings, as they are in most card games:

    TEST_CASE("Test comparisons with Aces") {
        Card c1(4, 1);
        Card c2(4, 2);
        Card c3(4, 13);
        CHECK((c1 > c2) == true);
        CHECK((c1 > c3) == true);
    }
    
  6. Encapsulate the deck-building code from the Vectors of cards section in a function named build_deck that takes no arguments and that returns a fully-populated vector of Cards.