From ca3142a6cd0f216bcb1d59fe9b8fb6e53800df41 Mon Sep 17 00:00:00 2001 From: Sander Speetjens Date: Tue, 13 Jun 2023 09:33:43 +0200 Subject: [PATCH] Added the blackjack lib --- blackjack/CMakeLists.txt | 18 +++++++ blackjack/Card.cpp | 100 +++++++++++++++++++++++++++++++++++++ blackjack/Card.hpp | 52 +++++++++++++++++++ blackjack/Deck.cpp | 30 +++++++++++ blackjack/Deck.hpp | 21 ++++++++ blackjack/IterableEnum.hpp | 95 +++++++++++++++++++++++++++++++++++ blackjack/Player.cpp | 48 ++++++++++++++++++ blackjack/Player.hpp | 21 ++++++++ 8 files changed, 385 insertions(+) create mode 100644 blackjack/CMakeLists.txt create mode 100644 blackjack/Card.cpp create mode 100644 blackjack/Card.hpp create mode 100644 blackjack/Deck.cpp create mode 100644 blackjack/Deck.hpp create mode 100644 blackjack/IterableEnum.hpp create mode 100644 blackjack/Player.cpp create mode 100644 blackjack/Player.hpp diff --git a/blackjack/CMakeLists.txt b/blackjack/CMakeLists.txt new file mode 100644 index 0000000..1a6cd83 --- /dev/null +++ b/blackjack/CMakeLists.txt @@ -0,0 +1,18 @@ +add_library(blackjack "") +target_sources(blackjack + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/Deck.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Player.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Card.cpp +) + +target_include_directories(blackjack + PUBLIC + ${CMAKE_CURRENT_LIST_DIR} + ${PROJECT_BINARY_DIR} + ${PROJECT_DIR}/external +) + +target_compile_options(blackjack PRIVATE $<$: + -Wall -Wextra -pedantic-errors -Wconversion -Wsign-conversion -g + >) \ No newline at end of file diff --git a/blackjack/Card.cpp b/blackjack/Card.cpp new file mode 100644 index 0000000..11af4f2 --- /dev/null +++ b/blackjack/Card.cpp @@ -0,0 +1,100 @@ +#include "Card.hpp" + +Card::Card(Rank rank, Suit suit) : rank_(rank), suit_(suit) {} + +Card::Rank Card::getRank() const +{ + return rank_; +} +Card::Suit Card::getSuit() const +{ + return suit_; +} + +std::string Card::rank_to_string(void) const +{ + std::string rank; + switch (rank_) + { + case Rank::ACE: + rank = "Ace"; + break; + case Rank::TWO: + rank = "Two"; + break; + case Rank::THREE: + rank = "Three"; + break; + case Rank::FOUR: + rank = "Four"; + break; + case Rank::FIVE: + rank = "Five"; + break; + case Rank::SIX: + rank = "Six"; + break; + case Rank::SEVEN: + rank = "Seven"; + break; + case Rank::EIGHT: + rank = "Eight"; + break; + case Rank::NINE: + rank = "Nine"; + break; + case Rank::TEN: + rank = "Ten"; + break; + case Rank::JACK: + rank = "Jack"; + break; + case Rank::QUEEN: + rank = "Queen"; + break; + case Rank::KING: + rank = "King"; + break; + case Rank::end: + default: + rank = "Invalid"; + break; + } + + return rank; +} + +std::string Card::suit_to_string() const +{ + std::string suit; + switch (suit_) + { + case Suit::HEARTS: + suit = "Hearts"; + break; + case Suit::DIAMONDS: + suit = "Diamonds"; + break; + case Suit::CLUBS: + suit = "Clubs"; + break; + case Suit::SPADES: + suit = "Spades"; + break; + case Suit::end: + default: + suit = "Invalid"; + break; + } + return suit; +} + +std::string Card::to_string() const +{ + return rank_to_string() + " of " + suit_to_string(); +} + +bool Card::operator==(const Card &other) const +{ return (rank_ == other.getRank() + && suit_ == other.getSuit()); +} diff --git a/blackjack/Card.hpp b/blackjack/Card.hpp new file mode 100644 index 0000000..7d37d85 --- /dev/null +++ b/blackjack/Card.hpp @@ -0,0 +1,52 @@ +#pragma once + +#include +#include +#include +#include +#include +#include // for "shuffle" + +#include "IterableEnum.hpp" + +class Card +{ +public: + ITERABLE_ENUM_BEGIN(Rank) + ACE = 1, + TWO, + THREE, + FOUR, + FIVE, + SIX, + SEVEN, + EIGHT, + NINE, + TEN, + JACK, + QUEEN, + KING + ITERABLE_ENUM_END; + + ITERABLE_ENUM_BEGIN(Suit) + HEARTS, + DIAMONDS, + CLUBS, + SPADES + ITERABLE_ENUM_END; + + Card(Rank rank, Suit suit); + + Rank getRank() const; + Suit getSuit() const; + + std::string rank_to_string() const; + std::string suit_to_string() const; + std::string to_string() const; + + bool operator==(const Card &other) const; + +private: + Rank rank_; + Suit suit_; +}; diff --git a/blackjack/Deck.cpp b/blackjack/Deck.cpp new file mode 100644 index 0000000..76978d2 --- /dev/null +++ b/blackjack/Deck.cpp @@ -0,0 +1,30 @@ +#include "Deck.hpp" + +Deck::Deck(void) +{ + for (Iterable suit; suit < Card::Suit::end; suit++) + { + for (Iterable rank = Card::Rank::ACE; rank < Card::Rank::end; rank++) + { + cards_.push_back(std::make_unique(rank.val(), suit.val())); + } + } +} + +void Deck::shuffledeck(void) +{ + std::random_device rd; + std::mt19937 g(rd()); + std::shuffle(cards_.begin(), cards_.end(), g); +} + +std::unique_ptr Deck::drawCard(void) +{ + if (cards_.empty()) + { + return nullptr; + } + std::unique_ptr card = std::move(cards_.back()); + cards_.pop_back(); + return card; +} \ No newline at end of file diff --git a/blackjack/Deck.hpp b/blackjack/Deck.hpp new file mode 100644 index 0000000..ee8b03e --- /dev/null +++ b/blackjack/Deck.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include +#include +#include +#include + +#include "Card.hpp" +#include "IterableEnum.hpp" + +class Deck +{ +public: + Deck(void); + + void shuffledeck(void); + std::unique_ptr drawCard(); + +private: + std::vector> cards_; +}; diff --git a/blackjack/IterableEnum.hpp b/blackjack/IterableEnum.hpp new file mode 100644 index 0000000..6c10462 --- /dev/null +++ b/blackjack/IterableEnum.hpp @@ -0,0 +1,95 @@ +#pragma once + +#define ITERABLE_ENUM_BEGIN(name) enum class name : int { +#define ITERABLE_ENUM_END ,end, begin = 0 } + +template +class Iterable +{ +public: + Iterable(T value = T::begin) : mValue(value) {} + Iterable(const Iterable& other) : mValue(other.mValue) {} + + Iterable& operator++() + { + assert(mValue >= T::begin && mValue < T::end); + mValue = static_cast(static_cast(mValue) + 1); + return *this; + } + + Iterable operator++(int) + { + Iterable prev = *this; + mValue = static_cast(static_cast(mValue) + 1); + return prev; + } + + Iterable& operator--() + { + assert(mValue >= T::end && mValue < T::begin); + mValue = static_cast(static_cast(mValue) - 1); + return *this; + } + + Iterable operator--(int) + { + Iterable prev = *this; + mValue = static_cast(static_cast(mValue) - 1); + return prev; + } + + Iterable operator+(int i) + { + return static_cast(static_cast(mValue) + i); + } + + Iterable operator+(T i) + { + return static_cast(static_cast(mValue) + static_cast(i)); + } + + Iterable operator-(int i) + { + return static_cast(static_cast(mValue) - i); + } + + Iterable operator-(T i) + { + return static_cast(static_cast(mValue) - static_cast(i)); + } + + + bool operator >(const T& other) const + { + return static_cast(mValue) > static_cast(other); + } + + bool operator >=(const T& other) const + { + return static_cast(mValue) >= static_cast(other); + } + + bool operator <(const T& other) const + { + return static_cast(mValue) < static_cast(other); + } + + bool operator <=(const T& other) const + { + return static_cast(mValue) <= static_cast(other); + } + + bool operator ==(const T& other) const + { + return static_cast(mValue) == static_cast(other); + } + + bool valid() const { return mValue != T::end; } + + operator T() const { return mValue; } + operator T&() { return mValue; } + T val() const { return mValue; } + +private: + T mValue; +}; \ No newline at end of file diff --git a/blackjack/Player.cpp b/blackjack/Player.cpp new file mode 100644 index 0000000..fb19fd7 --- /dev/null +++ b/blackjack/Player.cpp @@ -0,0 +1,48 @@ +#include "Player.hpp" + +void Player::addCard(std::unique_ptr card) +{ + hand_.push_back(std::move(card)); +} + +Card Player::getLastCard(void) const +{ + return Card(hand_.back()->getRank(), hand_.back()->getSuit()); +} + +int Player::getHandValue() const +{ + int value = 0; + int aces = 0; + for (const auto &card : hand_) + { + int cardValue = (int)card->getRank(); + if (cardValue >= 10) + { + cardValue = 10; + } + else if (cardValue == (int)Card::Rank::ACE) + { + aces++; + cardValue = 11; + } + value += cardValue; + } + + while (value > 21 && aces > 0) + { + value -= 10; + aces--; + } + return value; +} + +std::string Player::getHandString() const +{ + std::string handString; + for (const auto &card : hand_) + { + handString += card->to_string() + " "; + } + return handString; +} diff --git a/blackjack/Player.hpp b/blackjack/Player.hpp new file mode 100644 index 0000000..408f237 --- /dev/null +++ b/blackjack/Player.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include +#include +#include +#include + +#include "Card.hpp" + +class Player +{ +public: + void addCard(std::unique_ptr card); + + Card getLastCard(void) const; + int getHandValue() const; + std::string getHandString() const; + +private: + std::vector> hand_; +};