Posted By Alex | 3/19/2009 11:12:39 PMNOTE: This post is for the technically savvy. Feel free to read it if you like, but if you don't understand it then do not worry. From time to time I have a geeky moment and I feel like this is the perfect medium to share it.
Today I worked my fingers raw typing out code for
ReferralNetworX.com and I decided to take a break. When I came back to
the computer I didn't feel like working right away so I called a friend
and we got to talking about gambling. Somehow we started talking about
Blackjack and whether or not the house had an advantage since it has to
play by house rules. I suggested that house rules (hitting anything
below 17) must pay off for them because the casino runs all day and all
night. In the long run it must be profitable.
We talked for quite a while before my friend asked what would
happen if everyone had to play by house rules. I thought that was a
good question and an idea struck me. The rules are so simple that I
knew I could reproduce a virtual computer match of Blackjack where both
computers could play by the rules. With no human element, the
programming was simple. I did all the coding in just under an hour. I
created an array containing all 52 cards in a deck. The array only
recorded each cards value since I had no need to represent the cards
with actual suits or face cards. The program then runs through a loop
and does all the proper math for playing the game and pulling cards
from the deck at random to simulate that the deck had been shuffled.
Once the deck is empty it is refilled and it begins again. I set the
program to run the competetors through 100,000 games; both computer
players are forced to follow casino Blackjack house rules. Lastly, I
ran the program five times (each run took about 1-2 minutes on my PC).
Here are the results below:
(I opted to simply track wins, losses, and draws instead of calculating bets, etc...)
* NOTE: When both players bust (go over 21) the program logs it as a draw for the sake of tracking.
Session 1:
Computer 1 ended up with 40701 wins.
Computer 2 ended up with 40394 wins.
Draws: 18905
Session 2:
Computer 1 ended up with 40758 wins.
Computer 2 ended up with 40444 wins.
Draws: 18798
Session 3:
Computer 1 ended up with 40456 wins.
Computer 2 ended up with 40540 wins.
Draws: 19004
Session 4:
Computer 1 ended up with 40643 wins.
Computer 2 ended up with 40283 wins.
Draws: 19074
Session 5:
Computer 1 ended up with 40323 wins.
Computer 2 ended up with 40730 wins.
Draws: 18947
I thought the results were very surprising. Discount draws since they are of no consequence to betting players, the wins and losses in each session were never more than a few hundred apart. I suspect that if I let the program go long enough the numbers would get even closer together and even out. The preliminary statistics for Blackjack played using house rules over a long period would seem to suggest a pattern. Maybe there is a reason why the casino must follow house rules. Before now I always thought it was crazy that the house would have to hit on 16, but it is starting to make some sense.
I know that this program could be greatly improved. I didn't account for betting odds, double downs, suited odds, etc... I didn't even account for the order of play wherein if the dealer gets Blackjack then its game over no matter what. The numbers involved with gambling have always interested me. I am only recently learning how to calculate odds in poker games. I am sure some interesting little programs will come out of that endeavor and I will post them in the future.
Here is the source code for the virtual Blackjack program in case you were interested. It is written using the C# coding language. Feel free to fix anything I may have missed.
( Yes, I did account for the Ace counting as either 11 or 1

)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace ConsoleApplication1
{
class Program
{
static ArrayList alDeck;
static void Main(string[] args)
{
Random r = new Random();
BuildDeck();
int iComp1 = 0;
int iComp2 = 0;
int iCard = 0;
int iCard2 = 0;
int iIndex = 0;
int iIndex2 = 0;
int iNumDraws = 0;
int iNumWins1 = 0;
int iNumWins2 = 0;
bool bFinished1 = true;
bool bFinished2 = true;
int x = 0;
while (x < 100000)
{
iCard = 0;
iComp1 = 0;
while (true)
{
iIndex = r.Next(alDeck.Count - 1);
iCard = Convert.ToInt32(alDeck[iIndex]);
alDeck.RemoveAt(iIndex);
if (alDeck.Count == 0)
BuildDeck();
if ((iCard == 11) && ((iComp1 + 11) <= 21))
{
iComp1 += 11;
Console.WriteLine("Card Worth: 11");
}
else if ((iCard == 11) && ((iComp1 + 11) > 21))
{
iComp1 += 1;
Console.WriteLine("Card Worth: 1");
}
else
{
iComp1 += iCard;
Console.WriteLine("Card Worth: " + iCard.ToString());
}
if ((iComp1 >= 17) && (iComp1 <= 21))
{
bFinished1 = true;
Console.WriteLine("Finished! " + iComp1.ToString());
Console.WriteLine();
//Console.ReadLine();
break;
}
else if (iComp1 > 21)
{
bFinished1 = false;
Console.WriteLine("BUST! " + iComp1.ToString());
Console.WriteLine();
//Console.ReadLine();
break;
}
}
/////////////////////////////////////////////////////////////////
iCard2 = 0;
iComp2 = 0;
while (true)
{
iIndex2 = r.Next(alDeck.Count - 1);
iCard2 = Convert.ToInt32(alDeck[iIndex2]);
alDeck.RemoveAt(iIndex2);
if (alDeck.Count == 0)
BuildDeck();
if ((iCard2 == 11) && ((iComp2 + 11) <= 21))
{
iComp2 += 11;
Console.WriteLine("Card Worth: 11");
}
else if ((iCard2 == 11) && ((iComp2 + 11) > 21))
{
iComp2 += 1;
Console.WriteLine("Card Worth: 1");
}
else
{
iComp2 += iCard2;
Console.WriteLine("Card Worth: " + iCard2.ToString());
}
if ((iComp2 >= 17) && (iComp2 <= 21))
{
bFinished2 = true;
Console.WriteLine("Finished! " + iComp2.ToString());
Console.WriteLine();
//Console.ReadLine();
break;
}
else if (iComp2 > 21)
{
bFinished2 = false;
Console.WriteLine("BUST! " + iComp2.ToString());
Console.WriteLine();
//Console.ReadLine();
break;
}
}
///////////////
if ((bFinished1) && (bFinished2))
{
if (iComp1 > iComp2)
{
iNumWins1 += 1;
}
else if (iComp2 > iComp1)
{
iNumWins2 += 1;
}
else if (iComp1 == iComp2)
{
iNumDraws += 1;
}
}
else if ((bFinished1) && (!bFinished2))
{
iNumWins1 += 1;
}
else if ((!bFinished1) && (bFinished2))
{
iNumWins2 += 1;
}
else if ((!bFinished1) && (!bFinished2))
{
iNumDraws += 1;
}
x++;
}
Console.WriteLine();
Console.WriteLine("Comp1 Wins: " + iNumWins1.ToString());
Console.WriteLine("Comp2 Wins: " + iNumWins2.ToString());
Console.WriteLine("Draws: " + iNumDraws.ToString());
Console.ReadLine();
}
static void BuildDeck()
{
alDeck = new ArrayList();
alDeck.Add("2");
alDeck.Add("3");
alDeck.Add("4");
alDeck.Add("5");
alDeck.Add("6");
alDeck.Add("7");
alDeck.Add("8");
alDeck.Add("9");
alDeck.Add("10");
alDeck.Add("10");
alDeck.Add("10");
alDeck.Add("10");
alDeck.Add("11");
alDeck.Add("2");
alDeck.Add("3");
alDeck.Add("4");
alDeck.Add("5");
alDeck.Add("6");
alDeck.Add("7");
alDeck.Add("8");
alDeck.Add("9");
alDeck.Add("10");
alDeck.Add("10");
alDeck.Add("10");
alDeck.Add("10");
alDeck.Add("11");
alDeck.Add("2");
alDeck.Add("3");
alDeck.Add("4");
alDeck.Add("5");
alDeck.Add("6");
alDeck.Add("7");
alDeck.Add("8");
alDeck.Add("9");
alDeck.Add("10");
alDeck.Add("10");
alDeck.Add("10");
alDeck.Add("10");
alDeck.Add("11");
alDeck.Add("2");
alDeck.Add("3");
alDeck.Add("4");
alDeck.Add("5");
alDeck.Add("6");
alDeck.Add("7");
alDeck.Add("8");
alDeck.Add("9");
alDeck.Add("10");
alDeck.Add("10");
alDeck.Add("10");
alDeck.Add("10");
alDeck.Add("11");
}
}
}
0 Comment(s) on this blog.