Blackjack Quickstart

Editing the Code

The file you need to edit is Blackjack.cs

The main method of interest is:

CalculateMove()

This receives a package of game state information, including the players’ stack sizes, bet size so far this deal, the round of betting and what cards you have and the dealer's face up cards.

From this information, it is your task to decide one of two things depending on round you are in:
1. What bet size you would like to make
2. What action you would like to take

You specify your decisions by calling ClientMoved with the move package - BlackjackMove

In the betting round use the BetSize parameter to specify your bet size.

In the actions round use the Action parameter to specify your action.

For example:

ClientMoved(new BlackjackMove(){
    BetSize = 10
});

Or:
ClientMoved(new BlackjackMove(){
    Action = BlackjackRequestMoveType.Hit
});

Case Study

Let’s say we would like to implement the following strategy:
1. In the betting round our default move is to bet 10 each time.
2. Randomly, 33% of the time we will play a larger bet size between 20 and 100.
3. In the actions round our default move is to hit for another card.
4. If our cards add up to 17 or more we will stand.
5. If they add up to 16 we will double.

We will use the PlayerCards property of the state to determine our hand value.
We will also create a function to help us calculate hand values.
The RangeRand method returns a random number, optionally rounded down to a round number
The code looks like the following:

    BlackjackMove move = new BlackjackMove();
    if (state.Round == BlackjackDealRound.SetBetsize) //If we are in the betting round
        //Default bet when no special cases are identified:
        move.BetSize = 10; //Bet 10
 
        if (RangeRand(0, 2) == 0) // 1/3 of the time, bet
            move.BetSize = RangeRand(20, 119, 20); // 20,40,60,80 or 100 with equal likeliness
 
    else //Otherwise, if we are in the actions round
        //Default action when no special cases are identified:
        move.Action = BlackjackRequestMoveType.Hit; //Hit
 
        int handValue = 0;
        foreach (Card c in state.PlayerCards) //For every card in your hand
            handValue += blackjackValue(c); //Add the value returned from blackjackValue to the total
 
        if(handValue >= 17) //If your hand value is greater than or equal to 17
            move.Action = BlackjackRequestMoveType.Stand; //Stand
 
        if(handValue == 16)//If your hand value is equal to 16
            move.Action = BlackjackRequestMoveType.Double; //Double
 
    // call server to process our move
    ClientMoved(move);

Helper Methods

Below are the helper methods you will need for our case study to work

private int blackjackValue(Card card)
{
    int value;
    if (card.Index == CardIndexType.Ace) //Is our card an A
    {
        value = 11; //Then it has value 11
    }
    else if (card.Index < CardIndexType.Ten) //Is our a 2/3/4/5/6/7/8/9
    {
        value = (int)card.Index; //Then it has value equal to its index
    }
    else //Is our card a 10/J/Q/K
    {
        value = 10; //Then it has value 10
    }
    return value;
}
 
private int RangeRand(int min, int max)
{
    return _random.Next(min, max + 1);
}
 
private int RangeRand(int min, int max, int roundTo)
{
    int res = _random.Next(min, max + 1);
    return (res - res % roundTo);
}

Note that an Ace can take values 1 or 11, this case is left to you.

State Values

In the calculate move function, prefix the following properties with "state." to access their values.

List<Card> AllCardsSeen; //List of cards seen in current deal
int Bet; //How much you have bet so far this deal
List<Card> DealerCards; //The list of cards the dealer has in their hand
int DealNumber; //Which deal you are on this game
int OpponentStack; //Number of chips your opponent has
List<Card> PlayerCards; //The list of cards in your hand
int PlayerStack; //Number of chips you have
List<Card> PreviousDealDealerCards; //The list of cards the dealer had in their hand last deal
List<Card> PreviousDealPlayerCards; //The list of cards you had in your hand last deal
BlackjackDealResult PreviousDealResult; //How the last game was won/lost
int RemainingCards; //The number of cards left in the deck
BlackjackDealRound Round; //Whether you are in the betting, action, or showdown round

Advanced

Also you may like to edit the method:

ProcessGameState()

This is called after any move is made by either player. The function displays the state of the game on the client screen, then only if the IsMover flag is set, it calls CalculateMove(). To maximise your efficiency, you may like to do some processing here while your opponent calculates their move. Note there is a Thread.Sleep in this method which pauses the client for a short time so that the user can see the result of the deal. Example:

protected override void ProcessGameState(BlackjackGameState state)
{
    Show the user the current game state
 
    Desk.ShowMove(state);
 
    Thread.Sleep(ThinkingTime);
 
    if (state.IsMover)
        CalculateMove(state);
    else
        ; // Could do some additional processing here while opponent thinks
}

Suggested reading…

Poker Primer

Bot Strategy

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License