Assignment 10

due at 6pm on Mon 21 Nov

For this assignment, you will implement the card game Blackjack using functions, and following a template I have created for you.

The template is available here: a10given.cpp. It contains extensive documentation that you should read, in addition to the descriptions and tasks below. (If it doesn’t show up correctly in the browser, right-click and “save target as.”)

Description of the game

Note: This is not a complete or accurate implementation of the real game; for that, we’d need to learn a few more features of C.

A deck of cards has 52 cards. Each card has one of 13 ranks, which are the numbers 2 through 10, or Jack, Queen, King, Ace. Each card has one of 4 suits, which are Clubs, Hearts, Spades, and Diamonds. The suit is not used in this game, but we’ll still choose one and print it out for the sake of realism.

We can thus represent a card as a pair of integers: rank and suit. For rank, we’ll use an integer in the range 2 through 10, or these special constants for the other ranks:

const int ACE = 1;
const int JACK = 11;
const int QUEEN = 12;
const int KING = 13;

For the suits, we’ll just use these arbitrary constants:

const int CLUBS = 0;
const int HEARTS = 1;
const int SPADES = 2;
const int DIAMONDS = 3;

In the game, the player is initially dealt two cards, and the computer reports the score so far:

  ######################## starting game.
  2 of hearts
  King of spades
  Your score: 12

Scores are determined solely by the rank of the card. The numeric cards (2 through 10) are worth the amount indicated (2 through 10). Jack, Queen, and King (these are called face cards) are each worth 10 points. The Ace, for the purposes of this program, will be worth 11 points. (In the real game, you can choose to use it as just 1 point.) So, in the example above, 2 + King = 2 + 10 = 12 points.

Now, the player has a choice: he can choose to take another card (hit), or to stick with what he has (stay). We’ll ask the user to type in 1 or 0 to indicate the choice:

  Would you like to hit (1) or stay (0)? 1
  7 of clubs
  Your score: 19
  Would you like to hit (1) or stay (0)? 0
  Thanks for playing.

In this game, the user received a 7. Its score is added to the score from the first two cards, and he can choose again.

The goal of the game is to get as close as possible to 21 points, but not to exceed it. (In the real game, each player is competing with the dealer, and whoever gets closest to 21 wins.) We’ll use this constant to represent the target score:

const int TARGET_SCORE = 21;

If the player reaches 21 exactly, we don’t offer them the chance to hit again, and we announce Blackjack:

  King of hearts
  4 of diamonds
  Your score: 14
  Would you like to hit (1) or stay (0)? 1
  7 of clubs
  Your score: 21
  BLACKJACK!
  Thanks for playing.

If the player exceeds 21, them we announce Bust:

  King of hearts
  2 of hearts
  Your score: 12
  Would you like to hit (1) or stay (0)? 1
  3 of spades
  Your score: 15
  Would you like to hit (1) or stay (0)? 1
  Ace of diamonds
  Your score: 26
  BUST!
  Thanks for playing.

Algorithm for game play

The given code is organized into functions with very specific tasks. The top-level game play algorithm is provided for you in the function play_game:

void play_game()
{
printf("######################## starting game.\n");
int rank, score;
// First two cards.
rank = deal_one_card();
score = rank_to_score(rank);
rank = deal_one_card();
score += rank_to_score(rank);
printf("Your score: %d\n", score);
// Loop as long as user wants (or until we hit 21).
while(score < TARGET_SCORE && ask_user_hit())
{
rank = deal_one_card();
score += rank_to_score(rank);
printf("Your score: %d\n", score);
}
// All done. Was it Blackjack or Bust?
maybe_announce_result(score);
}

Your task is to fill in the definitions of many of these functions. They are marked with TODO in the comments, and described as tasks below.

Testing your program as you go

The main function, as given, calls two functions: all_tests and play_game. You may comment out one of these at a time, if you just want to focus on the tests or on the game itself.

Also, within all_tests, it may help if you comment out the tests that you’re not working on right now. So, when you are implementing rank_to_score, your all_tests might look like this:

void all_tests()
{
//test_print_card();
//test_deal_one_card();
test_rank_to_score();
//test_maybe_announce_result();
}

Task 1: Print card

void print_card(int rank, int suit)
{
}

This function should print out the card representing by the parameters rank and suit. Remember, these are just integers in the range 1–11 and 0–3, but you can use the constants like ACE and SPADES to distinguish them. You’ll probably use a couple of switch statements, and it’s fine to put a constant in a case, like this:

    case SPADES:
// ... code here

Task 2: Choose a random card

We covered the use of rand in class. It returns an integer between 0 and RAND_MAX, which is a large number over 2 billion. You can shrink the range using the modulus operator (%) and then add to offset the range.

For example, if you want to model rolling a die, we’d want to produce numbers in the range 1–6. That can be done like this:

      rand() % 6 + 1

because the modulo 6 produces numbers between 0–5, and adding one brings the range up to 1–6.

Your function deal_one_card should also call print_card, and then it should return just the rank.

Task 3: Determine score of a card

int rank_to_score(int rank)
{
return 0; // temporary
}

This function takes a rank (1–13) and returns its score. In our game, the ACE is always worth 11 points; JACK, QUEEN, KING are worth 10 points, and the numeric cards have their face value (2–10).

Task 4: User input

int ask_user_hit()
{
return 0; // temporary
}

Prompt the user to hit (1) or stay (0). The function should validate the input and ask again until a valid input is provided. It should return just 1 or 0.

©2011 Christopher League · some rights reserved · CC by-sa