Skip to content

Software Documentation

Deep Patel edited this page Aug 31, 2024 · 13 revisions

Application Version: 1.4.2

Programming Languages: C#, SQL

Framework: .NET 8.0.303

IDEs Used: Visual Studio Community 2022 17.10.5, Visual Studio Code 1.92.1

External Services Used: Amazon Web Services (AWS), Microsoft SQL Server Management Studio (SSMS), Docker



Installation

You may choose either of the three methods that best suits you


Download the .ZIP

  1. Download the latest release .ZIP folder for your respective OS
  2. Unzip the folder in your desired location
  3. Run the Blackjack application


Download the Docker Image

  1. Run the command below in your terminal
docker pull ghcr.io/deepthepatel/blackjack:latest
  1. Run the command below. The -it flag ensures the image runs in interactive mode. You may rename blackjack-container
docker run -it --name blackjack-container ghcr.io/deepthepatel/blackjack:latest

To run the app again with the existing container:

docker start blackjack-container
docker attach blackjack-container

NOTE: After running the attach command, the terminal may appear to do nothing, press Enter to see the application running


For whatever reason, if the ./publish folder's contents are modified or deleted, delete the remaining contents and run:

dotnet publish -c Release -o ./publish

Then

docker build -t blackjack-app .

Then

docker run -it --name blackjack-container ghcr.io/deepthepatel/blackjack:latest


Clone the Repository

  1. Clone the project into a folder on your computer
git clone https://github.com/DeepThePatel/Blackjack.git
  1. Ensure you have the .NET 8.0 SDK installed
  2. Open the project folder in a new terminal in Visual Studio
  3. Download the necessary packages
  4. Run
dotnet build
  1. Then
dotnet run


Libraries and Packages

All packages can be downloaded via the NuGet Package Manager Console Tools > NuGet Package Manager > Package Manager Console in Visual Studio 2022 by running:

Install-Package <package-name>

NOTE: Downloading packages is unnecessary when downloading the .ZIP or Docker image. It is only necessary when cloning the repository.

  • Microsoft.Data.SqlClient 5.2.1

  • Microsoft.Extensions.Configuration 8.0.0

  • Microsoft.Extensions.Configuration.Json 8.0.0



Gameplay

Main Menu

Upon successful login/account creation, player will be notified of their initial balance.

The player will have the choice to pick from three (3) different casinos:

  1.   Las Vegas         (Min. $50)
  2.   Monte Carlo    (Min. $200)
  3.   Dubai               (Min. $500)

Player will also have the option to quit (Q) the game.

Inside the Casino

Once the preferred casino is selected, player is prompted to enter a bet within the accepted value range or to exit (Q) the casino.

Once a valid bet is placed, the program begins to deal the player and dealer their hands in an alternating fashion.


Insurance

Once the cards are dealt and in the event that the dealer's first card is an Ace (where the player does NOT have a blackjack), the player has the ability to bet Insurance.

  • The player is able to bet up to half of their original bet or 0 if they do not wish to take insurance
  • If insurance is taken and the player wins, they will receive their original bet and 2x their insurance
  • If insurance is taken and the player loses, they will lose their original bet and their insurance
  • If insurance is not taken, the game will continue

Blackjack

Before the program continues, it checks to see whether the player or the dealer have a blackjack.

  • If either the player or the dealer have a blackjack, the player will be notified and the round will end
  • In the event that both the player and the dealer have a blackjack, the program will notify the player that there is a Push

The Player's Turn

Once the cards are dealt, player is shown their hand, the total of their hand, and the dealer's hand.

They are then given the option to Hit or Double or Stay. (Players may only double down once on their first turn. Players will NOT be able to double down after hitting a card)

Hit :  A random card is drawn into the player's hand

If the player does not bust:

  • The sum of the player's hand is updated
  • Player is given the option to Hit or Stay
  • This process is repeated until the player busts or decides to stay

If the player busts:

  • Player is notified they busted along with the total of their hand
  • Player's balance is updated
  • Player is then redirected to beginning where they can choose to bet again or exit the casino

Split :   Player has the ability to split their hand should their initial drawn cards equal in value

NOTE: In this version of blackjack, the player is NOT able to double down on split hands.

Double :   Player will be given the opportunity to double their bet and draw only one (1) card

NOTE: In this version of blackjack, the player is able to double down on any sum of their hand, not only 9, 10, and 11.

Stay :  Player does not draw a card and the program proceeds to play the dealer's hand


The Dealer's Turn

Once the player decides to stand with their hand or doubles down without busting, the dealer begins to draw cards.

The dealer will continue to draw cards until they either land on at least a soft 17 or bust, which then the program will determine the winner.


Rules of Blackjack

This program follows Bicycle Cards official blackjack rules.


Important Notes:

  • The Shuffle and Cut section is ignored as the cards dealt are randomly generated by the program
  • In this version of blackjack, player is able to double down on any sum of their hand, not only 9, 10, and 11
  • In this version of blackjack, player is NOT able to double down on split hands
  • Dealer must stand on soft 17
  • Blackjack pays 3:2


Application Variables

NOTE: Local variables will be defined in their respective methods in the Application Methods section below.

NOTE: It is NOT advised to change the values of any of the listed variables below as it can lead to compilation failure and hinder the performance of the application and will not function as intended.

  • private static double balance - Player's balance. Initialized at a value of 5000

  • private static string? readResult - String variable storing the user's input

  • private static string db_query - Query to be executed in the database

  • private static string casino - Casino choice

  • private static bool validEntry - Boolean variable storing (True) if player input is valid and (False) otherwise. Initialized as False

  • private static string? username - Player's username

  • private static string? db_authenticate - Database connection

  • private static bool isLoggedIn - Boolean variable storing (True) if the player is logged in and (False) otherwise. Initialized as False

  • private static bool isPlaying - Boolean variable storing (True) if the game is being played (player is logged in) and (False) otherwise. Initialized as True

  • private static bool isPlayingCasino - Boolean variable storing (True) if the player is currently playing a casino and (False) otherwise. Initialized as True

  • private static bool reset - Boolean variable storing (True) if the player's balance needs to be reset and (False) otherwise. Initialized as False

  • private static bool hasInsurance - Boolean variable storing (True) if player has taken insurance and (False) otherwise. Initialized as False

  • private static bool split - Boolean variable storing (True) if the player has opted to split their hand and (False) otherwise. Initialized as False

  • private static int playerCardSum - The sum of the player's unsplit hand

  • private static int playerFirstHandSum - The sum of the player's first hand when splitting

  • private static int playerSecondHandSum - The sum of the player's second hand when splitting

  • private static int dealerCardSum - The sum of the dealer's hand

  • private static Dictionary<string, List<int>> cards - Dictionary storing all 52 cards' in a standard deck in type string and their respective values in type List<int>. Aces hold both values of 11 and 1. Initialized as new Dictionary<string,List<int>>



Application Methods

NOTE: It is NOT advised to change the values of any of the listed local variables below as it can lead to compilation failure and hinder the performance of the application and will not function as intended.

  • public static void Main() - Program entry.

  • static void Home(string db_authenticate) - Home screen. Player can either register for an account or login to an existing account.
    • PARAMETERS
      • string db_authenticate - Database connection

  • static void Register(string db_authenticate) - Register screen. Prompts player to enter a username, their password, and reenter their password to successfully register for an account. Supports entering Q to return to Home screen and C to clear fields.
    • PARAMETERS
      • string db_authenticate - Database connection
    • CONSTRAINTS
      • Username cannot be an already registered username
      • Username can only contain alphanumeric characters and underscores

  • static void RegisterPassword(string username, string db_authenticate) - Handles password registration. Upon successful registration, SQL query is executed to add the entered username, hashedPassword, and initial balance of 5000 to the database. Supports entering Q to return to Home screen and C to clear fields.
    • LOCAL VARIABLES
      • bool passwordEntered - Boolean variable storing (True) if initial password was entered and (False) otherwise. This is for UX purposes. Initialized as (False)
        • True - Displays user's password in the Password: field as asterisks (*)
        • False - Prompts user to enter a password, hashes the password, and sets passwordEntered to True
      • string? password - User's password. Initialized as NULL
      • var hashedPassword - User's hashed password
    • PARAMETERS
      • string username - Userr's entered username
      • string db_authenticate - Database connection
    • CONSTRAINTS
      • Password can only contain alphanumeric characters or special characters (!,@,#,$,%,^,&,*, ( , ) )

  • static void Login(string db_authenticate) - Handles login. Prompts player to enter their username and password. Supports entering Q to return to Home screen and C to clear fields.
    • LOCAL VARIABLES
      • bool validUsername - Boolean variable storing (True) if entered username is valid and (False) otherwise
    • PARAMETERS
      • string db_authenticate - Database connection
    • CONSTRAINTS
      • Username must be an already registered username
      • Username can only contain alphanumeric characters and underscores

  • static void LoginPassword(string username, string db_authenticate) - Handles login password. Upon entering the password, SQL query is executed to validate if credentials match in the database. If successful, the player's balance is retrieved and isLoggedIn and validPassword are both set to True. Supports entering Q to return to Home screen and C to clear fields.
    • LOCAL VARIABLES
      • bool validPassword - Boolean variable storing (True) if password entered is valid and (False) otherwise
      • string? password - String variable storing the user's entered password
    • PARAMETERS
      • string username - User's entered username
      • string db_authenticate - Database connection
    • CONSTRAINTS
      • Password can only contain alphanumeric characters or special characters (!,@,#,$,%,^,&,*, ( , ) )

  • static bool UsernameExists(string username, string db_authenticate) - Executes SQL query to check if username exists in database
    • LOCAL VARIABLES
      • SqlConnection connection - Instantiating an instance of the SqlConnection class to connect to the database
      • SqlCommand command - Instantiating and instance of the SqlCommand class to execute a query
      • SqlDataReader reader - Instantiating an instance of the SqlDataReader class to read the result of the query
    • PARAMETERS
      • string username - User's entered username
      • string db_authenticate - Database connection
    • RETURN VALUES
      • bool - (True) if username exists (False) otherwise

  • static string ReadPassword() - Method to store entered password characters and display them as asterisks (*) while player is typing their password.
    • RETURN VALUES
      • string - User's password

  • static string MaskPassword(string password) - Method to mask the user's password as asterisks (*).
    • PARAMETERS
      • string password - User's entered password
    • RETURN VALUES
      • string - User's password as asterisks (*)

  • private static string HashPassword(string password) - Hashing the user's password for storage using the Secure Hash Algorithm 256-bit (SHA-256).
    • LOCAL VARIABLES
      • var sha256 - Instance of the SHA256 class used to compute the SHA-256 hash of the entered password
      • var bytes - Array of bytes storing the result of the SHA-256 computation
      • var builder - Instance of the StringBuilder class used to build the hashed password
      • var b - Loop variable used to iterate over each byte in the bytes array
    • PARAMETERS
      • string password - User's entered password
    • RETURN VALUES
      • string - User's hashed password

  • private static bool VerifyPassword(string password, string storedHash) - Method used to verify the stored hashed password with the user's entered password.
    • LOCAL VARIABLES
      • var hash - Variable used to store the hashed password
    • PARAMETERS
      • string password - User's entered password
      • string storedHash - Stored password hash
    • RETURNS VALES
      • bool - (True) if password matches (False) otherwise

  • static void PlayCasino(string casino, int minBet) - Method to play the casino
    • LOCAL VARIABLES
      • bool playingGames - Boolean variable storing (True) if casino games are being played and (False) otherwise. Initialized as True
      • var (bet, quit) - Variable storing the player's bet as an int and a boolean value quit that is True if the player exits the casino and False otherwise
      • var (playerCards, dealerCards) - Variable storing both the player's and dealer's hands as a List<Tuple<string, List<int>>>
      • List<Tuple<string, List<int>>>? playerFirstHand - Player's first hand if initial drawn hand is split.
      • List<Tuple<string, List<int>>>? playerSecondHand - Player's second hand if initial drawn hand is split.
    • PARAMETERS
      • string casino - Player's casino choice
      • int minBet - Player's bet

  • static (int, bool) EnterBet(int minBet) - Method to handle player's entered bet
    • LOCAL VARIABLES
      • string? bet - String variable capturing player's entered bet
      • int intBet - Integer variable storing player's entered bet
      • bool validEntry - Boolean variable storing (True) if user input is valid and (False) otherwise
      • bool quit - Boolean variable storing (True) if player quits the casino and (False) otherwise
      • bool validNumber - Boolean variable storing (True) if entered bet is a valid integer and (False) otherwise
    • PARAMETERS
      • int minBet - The minimum bet allowed by the casino
    • RETURN VALUES
      • int intBet - Bet entered by the player as an int
      • bool quit - (True) if player exits the casino and (False) otherwise

  • static (List<Tuple<string, List<int>>>, List<Tuple<string, List<int>>>) DealCards() - Method to deal initial hand of two (2) cards to each the player and the dealer.
    • LOCAL VARIABLES
      • List<string> deck - List variable storing the deck of cards. Initialized as new List<string>(cards.Keys)
      • Random dealCard - Instantiating an instance of the random class to deal a random card
      • List<Tuple<string, List<int>>> playerCards - List variable to hold a tuple of the player's cards consisting of the name of the card as a string and the integer values associated with that card as a List. Initialized as new List<Tuple<string, List<int>>>()
      • List<Tuple<string, List<int>>> dealerCards - List variable to hold a tuple of the dealer's cards consisting of the name of the card as a string and the integer values associated with that card as a List. Initialized as new List<Tuple<string, List<int>>>()
      • int index - Random integer associated with a randomly picked card
      • string randomCard - String value of the random chosen card
    • RETURN VALUES
      • List<Tuple<string, List<int>>> - Player's cards
      • List<Tuple<string, List<int>>> - Dealer's cards

  • static int CheckForInsurance(List<Tuple<string, List<int>>> dealerCards, List<Tuple<string, List<int>>> playerCards, int bet) - Method to check if insurance is an available option. This is only possible when the dealer's face-up card is an Ace.
    • LOCAL VARIABLES
      • var dealerFirstCard - Dealer's first (face-up) card
      • int maxInsuranceBet - The maximum insurance bet a player can make (Up to half of the original bet)
      • int insuranceBet - Player's insurance bet. If insurance bet is 0, no insurance is taken
      • bool validInsuranceNumber - Boolean variable storing (True) if insurance bet is a valid integer and (False) otherwise
    • PARAMETERS
      • List<Tuple<string, List<int>>> dealerCards - Dealer's cards
      • List<Tuple<string, List<int>>> playerCards - Player's cards
      • int bet - Player's original bet
    • RETURN VALUES
      • int - Player's insurance bet

  • static (bool, int, int) CheckBlackJack(List<Tuple<string, List<int>>> playerCards, List<Tuple<string, List<int>>> dealerCards, int bet) - Checks if either the player or the dealer or both have a blackjack.
    • LOCAL VARIABLES
      • int insurance - Player's insurance bet
    • PARAMETERS
      • List<Tuple<string, List<int>>> playerCards - Player's cards
      • List<Tuple<string, List<int>>> dealerCards - Dealer's cards
      • int bet - Player's original bet
    • RETURN VALUES
      • bool - Boolean variable storing (True) if there is a blackjack and (False) otherwise
      • int - The sum of the player's hand
      • int - The sum of the dealer's hand

  • static (List<Tuple<string, List<int>>>, List<Tuple<string, List<int>>>) Split(List<Tuple<string, List<int>>> playerCards) - Method to handle the case of the player splitting their hand.
    • LOCAL VARIABLES
      • List<Tuple<string, List<int>>> playerFirstHand - Player's first hand
      • List<Tuple<string, List<int>>> playerSecondHand - Player's second hand
      • int playerFirstCard - Value of the player's first initial dealt card
      • int playerSecondCard - Value of the player's second initial dealt card
      • bool invalidEntry - Boolean variable storing (True) if user's entry is invalid and (False) otherwise
      • List<string> deck - List variable storing the deck of cards. Initialized as new List<string>(cards.Keys)
      • Random dealCard - Instantiating an instance of the random class to deal a random card
      • int index - Random integer associated with a randomly picked card
      • string randomCard - String value of the random chosen card
    • PARAMETERS
      • List<Tuple<string, List<int>>> playerCards - Player's initial dealt hand
    • RETURN VALUES
      • List<Tuple<string, List<int>>> - Player's first hand
      • List<Tuple<string, List<int>>> - Player's second hand

  • static int CalculateBestHand(List<Tuple<string, List<int>>> cards) - Method to calculate the best possible value for player's hand. This is needed to account for the Ace card having a possible value of either 1 or 11.
    • LOCAL VARIABLES
      • int sum - Total sum of the hand
      • int aceCount - Amount of aces in the hand
    • PARAMETERS
      • List<Tuple<string, List<int>>> cards - Hand of cards
    • RETURN VALUES
      • int - The sum of the hand

  • static (bool, int, List<Tuple<string, List<int>>>, List<Tuple<string, List<int>>>, int) PlayerTurn(List<Tuple<string, List<int>>> playerCards, List<Tuple<string, List<int>>> dealerCards, int bet) - Method to handle the player's turn.
    • LOCAL VARIABLES
      • bool stand - Boolean variable storing (True) if player stands and (False) otherwise
      • bool canDouble - Boolean variable storing (True) if player is able to double and (False) otherwise
      • bool canSplit - Boolean variable storing (True) if player is able to split their hand and (False) otherwise
      • bool doubled - Boolean variable storing (True) if their bet was doubled and (False) otherwise
      • bool splitCompleted - Boolean variable storing (True) if the player's split completed and (False) otherwise
      • List<Tuple<string, List<int>>> playerFirstHand - List storing the player's first split hand (if applicable)
      • List<Tuple<string, List<int>>> playerSecondHand - List storing the player's second hand (if applicable)
      • int playerFirstHandSum - The sum of the player's first split hand
      • int playerSecondHandSum - The sum of the player's second split hand
      • var playerFirstCard - Value of the player's first dealt card (to check for ability to split)
      • var playerSecondCard - Value of the player's second dealt card (to check for ability to split)
      • var (blackjack, playerCardSum, dealerCardSum) - Variable storing bool blackjack that is (True) if there is a blackjack and (False) otherwise, int playerCardSum that is the sum of the player's hand, and int dealerCardSum that is the sum of the dealer's hand
      • var dealerFirstCard - String value of dealer's first card
      • List<string> deck - List variable storing the deck of cards. Initialized as new List<string>(cards.Keys)
      • Random dealCard - Instantiating an instance of the random class to deal a random card
      • int index - Random integer associated with a randomly picked card
      • string randomCard - String value of the random chosen card
    • PARAMETERS
      • List<Tuple<string, List<int>>> playerCards - Player's cards
      • List<Tuple<string, List<int>>> dealerCards - Dealer's cards
      • int bet - Player's initial bet
    • RETURN VALUES
      • bool - (True) if player does NOT bust and (False) otherwise
      • int - Player's initial hand sum
      • List<Tuple<string, List<int>>> - Player's first split hand (if applicable)
      • List<Tuple<string, List<int>>> - Player's second split hand (if applicable)
      • int - Player's bet

  • static void DealerTurn(List<Tuple<string, List<int>>> playerCards, List<Tuple<string, List<int>>> dealerCards, List<Tuple<string, List<int>>> playerFirstHand, List<Tuple<string, List<int>>> playerSecondHand, int bet) - Method handling the dealer's turn.
    • LOCAL VARIABLES
      • List<string> deck - List variable storing the deck of cards. Initialized as new List<string>(cards.Keys)
      • Random dealCard - Instantiating an instance of the random class to deal a random card
      • int index - Random integer associated with a randomly picked card
      • string randomCard - String value of the random chosen card
    • PARAMETERS
      • List<Tuple<string, List<int>>> playerCards - List containing player's cards
      • List<Tuple<string, List<int>>> dealerCards - List containing dealer's cards
      • List<Tuple<string, List<int>>> playerFirstHand - Player's first split hand (if applicable)
      • List<Tuple<string, List<int>>> playerSecondHand - Player's second split hand (if applicable)
      • int bet - Player's bet

  • static void DisplayPlayersHand(List<Tuple<string, List<int>>> playerCards, int playerCardSum) - Method to display the player's hand.
    • LOCAL VARIABLES
      • var playerCard - Loop variable used to iterate over each card in the player's hand
    • PARAMETERS
      • List<Tuple<string, List<int>>> playerCards - Player's cards
      • int playerCardSum - The sum of the player's hand

  • static void DisplayDealersHand(List<Tuple<string, List<int>>> dealerCards, int dealerCardSum) - Method to display the dealer's hand.
    • LOCAL VARIABLES
      • var dealerCard - Loop variable used to iterate over each card in the dealer's hand
    • PARAMETERS
      • List<Tuple<string, List<int>>> dealerCards - Dealer's cards
      • int dealerCardSum - The sum of the dealer's hand

  • static void DisplayPlayersSplitHands(List<Tuple<string, List<int>>> playerFirstHand, List<Tuple<string, List<int>>> playerSecondHand, int playerFirstHandSum, int playerSecondHandSum) - Method to display the player's split hands.
    • LOCAL VARIABLES
      • int numberOfCards - Maximum number of cards in either hand to ensure proper vertical display of cards as they are added to either hand
      • int cardWidth - Standard width of card names to ensure proper alignment and spacing between cards being displayed
      • string firstHandCard - String value of the first split hand's card
      • string secondHandCard - String value of the second split hand's card
    • PARAMETERS
      • List<Tuple<string, List<int>>> playerFirstHand - Player's first split hand
      • List<Tuple<string, List<int>>> playerSecondHand - Player's second split hand
      • int playerFirstHandSum - Sum of the player's first split hand
      • int playerSecondHandSum - Sum of the player's second split hand

  • static void GetBalance() - Executes SQL query to retrieve user's balance from the database.
    • LOCAL VARIABLES
      • SqlConnection connection - Instantiating an instance of the SqlConnection class to connect to the database
      • SqlCommand command - Instantiating and instance of the SqlCommand class to execute a query
      • object balance_db - Variable to store the value of the balance attribute in the database

  • static void CheckBalance(double balance, string username, string db_authenticate) - Method to check if the player's balance is < 50.
    • PARAMETERS
      • double balance - Player's balance
      • string username - Player's username
      • string db_authenticate - Database connection

  • static void UpdateBalance(double balance, string username, string db_authenticate) - Executes SQL query to update player's balance in the database.
    • LOCAL VARIABLES
      • SqlConnection connection - Instantiating an instance of the SqlConnection class to connect to the database
      • SqlCommand command - Instantiating and instance of the SqlCommand class to execute a query
      • int rowsAffected - Variables storing the amount of rows (Tuples) affected

  • static string Connect() - Establishing connection to database


Cloud Services

As of Blackjack v1.4.1, this application's database has been migrated to Amazon Web Services (AWS) from my local machine. This change resulted in a significant improvement in the resilience of this application as the login/register features can now be used succesfully without the need for my local machine to be on in order for the SQL database server to be running.



Release Notes

Refer to the releases page in the repository to see a full list of releases and their respective release notes.



Account Recovery

As of Blackjack v1.4.1, the ability to recover an account in the case of a forgotten password is NOT yet implemented. A new account must be registered as passwords are not saved and cannot be recovered.