/******************************************************************************
*******************************************************************************/
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// Implementation of the ADT Card ********************************************
struct Card // You may use your own implementation instead.
{
char rank, // 2, 3, ..., 9, T, J, Q, K, A
suit; // In ascending order: C(lub), D(iamond), H(eart), S(pade)
int point, // Value of numbered card; 10 for face cards, 11 for A.
order, // 0 to 51; Aces are high
rankCode, // 0 to 12 matching above ranks, respectively.
suitCode; // 0 to 4 matching above suits, respectively
};
void display(const Card &c) // You may use your own implementation instead.
/*
c will be displayed with two characters.
For example: 2C will be two of clubs, TH will be ten of hearts.
You may choose to display c differently than described above to suit the
user interface you designed.
*/
{
cout << c.rank << c.suit << ' ';
}
// Implementation of the ADT Deck ********************************************
struct Deck{ // You may use your own implementation instead.
vector<Card> cards;
};
void initialize(Deck &d) // You may use your own implementation instead.
/*
The standard 52 cards is ordered by rank and suit, with Aces high,
from 0 to 51 matching the following
2C, 2D, 2H, 2S,
3C, 3D, 3H, 3S,
...
KC, KD, KH, KS,
AC, AD, AH, AS
*/
{
d.cards.clear();
Card tempCard;
for (int order = 0; order < 52; order++)
{
// Assign order
tempCard.order = order;
// Assign suitCode, cuit
int suitCode = order % 4; // 0, 1, 2, 3 for C(lub), D(iamond), H(eart), S(pade)
tempCard.suitCode = suitCode;
switch (suitCode)
{
case 0: tempCard.suit = 'C'; break;
case 1: tempCard.suit = 'D'; break;
case 2: tempCard.suit = 'H'; break;
case 3: tempCard.suit = 'S'; break;
}
// Assign rankCode, rank, point
int rankCode = order / 4; // 0, ..., 12 for 2, ..., 9, T, J, Q, K, A
tempCard.rankCode = rankCode;
if (rankCode == 12)
{ // The code represents A
tempCard.rank = 'A';
tempCard.point = 11;
}
else if (rankCode <= 7)
{ // The codes 0 to 7 represent ranks 2 to 9
tempCard.point = rankCode;
tempCard.rank = static_cast<char>('0' + rankCode + 2);
}
else
{
// Code represents a 10-point Card
tempCard.point = 10;
switch(rankCode)
{
case 8: tempCard.rank = 'T'; break;
case 9: tempCard.rank = 'J'; break;
case 10: tempCard.rank = 'Q'; break;
case 11: tempCard.rank = 'K'; break;
}
}
d.cards.push_back(tempCard);
}
}
void shuffle(Deck& d)
/*
The cards in d is shuffled.
*/
{
int n = d.cards.size();
srand(time(NULL)); // Seed the random number generator
for (int i = 0; i < n; i++) {
int j = rand() % n; // Generate a random index
// Swap cards at index i and j
Card temp = d.cards[i];
d.cards[i] = d.cards[j];
d.cards[j] = temp;
}
}
Card deal(Deck& d)
/*
This function removes and returns the last element of d.cards.
Be sure to read Ch. 11.8 p. 634 about returning a structure from a function.
Use the vector method pop_back if you are using a vector to implement Deck.
Review Program 7-29 on p. 444 to see the methods pop_back and push_back
in action.
*/
{
if (d.cards.empty()) {
throw runtime_error("Cannot deal a card from an empty deck");
}
Card c = d.cards.back();
d.cards.pop_back();
return c;
}
void display(const Deck &d) // You may use your own implementation instead.
{
for (int k = 0; k < 52; k++)
{
display(d.cards[k]);
cout << ' ';
}
cout << endl;
}
// Implementation of the ADT Hand *********************************************
struct Hand // You may use your own implementation instead.
{
vector<Card> cards;
};
void initialize(Hand& h)
/*
Clear the hand h so that h contains no cards.
*/
{
h.cards.clear();
}
int getPoints(const Hand &h)
/*
Returns the total number of points of all the cards inthe hand h.
*/
{
int points = 0;
int numAces = 0;
for (const auto& card : h.cards) {
points += card.point;
if (card.rank == 'A') {
numAces++;
}
}
// Adjust ace values to minimize the total score
while (numAces > 0 && points > 21) {
points -= 10; // Treat Ace as 1 instead of 11
numAces--;
}
return points;
}
void addCard(Hand& h, const Card& c)
/*
Add the card c to the hand h.
*/
{
h.cards.push_back(c);
}
void displayHands(bool showHole, const Hand& d, const Hand& p)
/*
This function displays the cards in the dealer's and player's hands, as well as the number of points for each hand.
When showhole is false, the dealer's hole is not displayed.
*/
{
cout << "Dealer's hand: ";
for (int i = 0; i < d.cards.size(); i++) {
if (i == 0 &&!showHole) {
cout << "X ";
} else {
display(d.cards[i]);
cout << ' ';
}
}
cout << endl;
cout << "Player's hand: ";
for (const auto& card : p.cards) {
display(card);
cout << ' ';
}
cout << endl;
}
void playerTurn(Hand& p, const Hand& d)
{
while (true)
{
int pScore = getPoints(p);
if (pScore == 21)
{
cout << "Player has Blackjack! You win!" << endl;
return;
}
if (pScore > 21)
{
cout << "Player busts! Dealer wins." << endl;
return;
}
char choice;
cout << "Do you want to hit or stand? (h/s): ";
cin >> choice;
if (choice == 'h')
{
addCard(p, deal(playdeck));
displayHands(false, d, p);
}
else if (choice == 's')
{
break;
}
else
{
cout << "Invalid input. Please enter 'h' or 's'." << endl;
}
}
}
void dealerTurn(Hand& d, const Hand& p, Deck& playdeck) {
while (getPoints(d) < 17) {
addCard(d, deal(playdeck));
}
displayHands(true, d, p);
}
void decideWinner(const Hand& d, const Hand& p) {
int playerScore = getPoints(p);
int dealerScore = getPoints(d);
if (playerScore > 21) {
cout << "Dealer wins (Player Loss Because Player Score is exceeding 21)" << endl;
} else if (dealerScore > 21) {
cout << "Player wins (Dealer Loss Because Dealer Score is exceeding 21)" << endl;
} else if (playerScore > dealerScore) {
cout << "Player wins" << endl;
} else if (playerScore < dealerScore) {
cout << "Dealer wins" << endl;
} else {
cout << "It's a tie!" << endl;
}
}
//***************************************************************************
int main()
{
Hand player, dealer;
Deck playdeck;
initialize(playdeck);
// display(playdeck); // This line needs to be commented out;
// only here for testing initalize(playdeck)
shuffle(playdeck);
initialize(dealer);
initialize(player);
for (int k = 1; k<=2; k++)
{
addCard(player, deal(playdeck));
addCard(dealer, deal(playdeck));
}
displayHands(false, dealer, player);
playerTurn(player, dealer);
dealerTurn(dealer, player);
decideWinner(dealer, player);
return 0;
}