Skip to content

Instantly share code, notes, and snippets.

@LukeMS
Created June 26, 2017 23:12
Show Gist options
  • Save LukeMS/41214c1f0e6e750ce95373dcdd1f6bcd to your computer and use it in GitHub Desktop.
Save LukeMS/41214c1f0e6e750ce95373dcdd1f6bcd to your computer and use it in GitHub Desktop.
blackjack.c - learning exercise
/* A simple blackjack game in C */
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define NUM_SUITS 4
#define NUM_RANKS 13
#define HEARTS 3
#define DIAMONDS 4
#define CLUBS 5
#define SPADE 6
#define H 196
#define V 179
#define TL 218
#define BL 192
#define TR 191
#define BR 217
#define CARD_ROWS 7
struct Card {
char suit;
char rank;
char value;
bool ace;
};
void play_sound(int n) {
for(;n > 0; n--) {
printf("\a");
}
}
const char rank_code[] = {'2', '3', '4', '5', '6', '7', '8',
'9', 'T', 'J', 'Q', 'K', 'A'};
const char suit_code[] = {CLUBS, DIAMONDS, HEARTS, SPADE};
bool better_then(int a, int b) {
return a <= 21 && (21 - a) < (21 - b);
}
int get_dealer_action(int dealer_score) {
// The dealer must stand on 17 or higher and hit below 17.
if (dealer_score >= 17) {
return 2;
}
return 1;
}
void print_cards(struct Card *cards, size_t num_cards, bool dealer) {
for (int line = 0; line < CARD_ROWS; ++line) {
for (unsigned i = 0; i < num_cards; ++i) {
if (i > 0 && dealer && line > 0 && line < 6) {
printf("%c#####%c", V, V);
continue;
}
switch (line) {
case 0:
printf("%c%c%c%c%c%c%c", TL, H, H, H, H, H, TR);
break;
case 1:
printf("%c%c %c", V, cards[i].suit, V);
break;
case 3:
if (cards[i].rank == 'T') {
printf("%c 10 %c", V, V);
} else {
printf("%c %c %c", V, cards[i].rank, V);
}
break;
case 5:
printf("%c %c%c", V, cards[i].suit, V);
break;
case 6:
printf("%c%c%c%c%c%c%c", BL, H, H, H, H, H, BR);
break;
default:
printf("%c %c", V, V);
break;
}
}
printf("\n");
}
}
void print_game_table(int player_score, int dealer_score, struct Card *player_cards, struct Card *dealer_cards, size_t num_player_cards, size_t num_dealer_cards, bool player_done, bool dealer_done) {
printf("\nDealer(%2d): \n", dealer_score);
print_cards(dealer_cards, num_dealer_cards,
!player_done && !dealer_done);
printf("\nYou(%2d):\n", player_score);
print_cards(player_cards, num_player_cards, false);
}
struct Card draw(bool (*in_hand)[NUM_SUITS][NUM_RANKS]) {
struct Card card;
int rank, suit;
for (;;) {
suit = rand() % NUM_SUITS; /* picks a random suit */
rank = rand() % NUM_RANKS; /* picks a random rank */
if (!(*in_hand)[suit][rank]) {
card.suit = suit_code[suit];
card.rank = rank_code[rank];
if (rank == 12) {
card.value = 1;
card.ace = 1;
} else if (rank < 9) {
card.value = rank + 2;
card.ace = 0;
} else {
card.value = 10;
card.ace = 0;
}
(*in_hand)[suit][rank] = true;
return card;
}
}
}
int get_score(struct Card *cards, size_t num_cards) {
int sum = 0, aces = 0;
for (unsigned i = 0; i < num_cards; ++i) {
sum += cards[i].value;
aces += cards[i].ace;
}
for (; aces > 0; aces--) {
if (better_then(sum + 10, sum)) {
sum += 10;
}
}
return sum;
}
int deal(float *cash, float *bet) {
bool in_hand[NUM_SUITS][NUM_RANKS] = {{ false }}; // control cards so that they don't repeat
size_t num_cards = 21;
struct Card dealer_cards[num_cards], player_cards[num_cards];
size_t num_dealer_cards = 0, num_player_cards = 0;
bool player_done = false, dealer_done = false;
int player_score, dealer_score;
float result = 0.0f;
srand((unsigned) time(NULL));
printf("\n*** Welcome to ClackJack - a C BlackJack! ***\n");
for (; num_player_cards < 2; ++num_player_cards) {
player_cards[num_player_cards] = draw(&in_hand);
}
for (; num_dealer_cards < 2; ++num_dealer_cards) {
dealer_cards[num_dealer_cards] = draw(&in_hand);
}
int player_action, dealer_action;
for (;;) {
player_score = get_score(player_cards, num_player_cards);
dealer_score = get_score(dealer_cards, num_dealer_cards);
print_game_table(player_score, dealer_score,
player_cards, dealer_cards,
num_player_cards, num_dealer_cards,
player_done, dealer_done);
if ((player_score == 21) && (dealer_score == 21)) {
printf("Tied hand!");
break;
}
else if (player_score == 21) {
if (num_player_cards == 2) {
result = (*bet) * 1.5;
printf("Blackjack!");
play_sound(4);
} else {
result = (*bet);
printf("You win!");
play_sound(2);
}
break;
} else if (dealer_score == 21) {
result = -(*bet);
printf("Dealer wins!");
play_sound(1);
break;
} else if (player_done && dealer_done) {
if (better_then(player_score, dealer_score)) {
result = (*bet);
printf("You win!");
play_sound(2);
break;
} else {
result = -(*bet);
printf("Dealer wins!");
play_sound(1);
break;
}
}
else if (player_score > 21) {
result = -(*bet);
printf("You busted!");
play_sound(1);
break;
} else if (dealer_score > 21) {
result = (*bet);
printf("Dealer busted!");
play_sound(2);
break;
}
printf("\n(1 - Hit, 2 - Stand)\n");
printf("What would you like to do? ");
if (!player_done) {
scanf("%1d", &player_action);
switch (player_action) {
case 1:
if (num_player_cards < num_cards) {
player_cards[num_player_cards] = draw(&in_hand);
++num_player_cards;
player_score = get_score(player_cards, num_player_cards);
if (player_score >= 21) {
player_done = true;
}
}
break;
case 2:
player_done = true;
break;
}
}
// Once the dealer has dealt additional cards to all the players, the dealer draws cards for his/her hand.
if (player_done && !dealer_done) {
dealer_action = get_dealer_action(dealer_score);
switch (dealer_action) {
case 1:
dealer_cards[num_dealer_cards] = draw(&in_hand);
++num_dealer_cards;
break;
case 2:
dealer_done = true;
break;
}
dealer_score = get_score(dealer_cards, num_dealer_cards);
if (dealer_score >= 21) {
dealer_done = true;
}
}
}
if (result > 0) {
printf(" You've earned $%.2f\n", result);
} else if (result < 0) {
printf(" You've lost $%.2f\n", result);
}
return result;
}
void change_bet(float *cash, float *bet) {
float new_bet;
for (;;) {
printf("\nEnter a valid bet: ");
scanf("%f", &new_bet);
if (new_bet <= (*cash)) {
(*bet) = new_bet;
return;
}
}
}
int main(void) {
float cash = 1000.0f, bet = 250.0f;
float *cash_p = &cash;
float *bet_p = &bet;
int player_action;
do {
if (cash < bet) {
bet = cash;
}
if (cash <= 0.01f) {
printf("You are broke! Sounds like a good time to stop...");
break;
}
printf("\n(Options: 1 - Deal (bet %.2f); 2 - Change bet; 0 - Quit)\n",
bet);
printf("What would you like to do? (cash %.2f)", cash);
scanf("%1d", &player_action);
switch (player_action) {
case 1:
cash += deal(cash_p, bet_p);
break;
case 2:
change_bet(cash_p, bet_p);
break;
default:
return 0;
break;
}
} while (1);
printf("\n");
return 0;
}
@LukeMS
Copy link
Author

LukeMS commented Jun 26, 2017

Screenshot:

ex0014_cards_deal

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment