Creating a Quick and Dirty Online Blackjack GameBy Scott Mitchell
Every now and then I like to give myself a fun little programming challenge. I'll randomly pick some enjoyable task, like programming a game or blogging engine or what not, and impose a time limit, anywhere from an hour to an afternoon. Such little challenges keep the fun in programming and help me mentally recharge. After spending a week of programming boring data entry forms, such toy projects help remind me why I enjoy computer science and programming!
Anyway, a few months ago I decided to see if I couldn't create a simple online Blackjack game that would allow a single person to come to the site, enter their name and starting bankroll, and play Blackjack against a dealer. Blackjack is a popular casino game where players are playing against the House, which has a pre-defined set of rules. See the Blackjack Wikipedia entry for rules and basic strategy.
I was able to complete the task during an afternoon and thought I'd share it here for a more fun article during this holiday season. The application is created as an ASP.NET 2.0 web application and the complete code can be downloaded from the end of this article. Do keep in mind it was written in about three hours, so there may be some rough edges, but it does allow you to "create" multiple players, allows for doubling down, and so on. Read on to learn more about the code and technology used to create this game.
Blackjack in a Nutshell
Blackjack is a card game where one or more players sit down at the table, facing off against the House (the dealer). The dealer deals from a dealing shoe that may hold multiple decks of cards to reduce the effect of card counting. Each player starts by making a wager. Then, all players (including the dealer) are delt two cards, with one of the dealer's cards delt face up and the other face down. The objective is to construct a hand that is closer to 21 "points" than the dealer's, where face cards are worth 10 points, non-face cards worth their natural value, and the Ace being able to be worth either 11 or 1 (it assumes the value that is most beneficial to the hand it is part of). A player "busts" if their score exceeds 21 and they lose the hand.
After all players have completed their turn, the dealer reveals his face down card and must continually hit until his score is greater than or equal to 17 or he busts. If the dealer busts, all remaining players (those who did not bust) win. If the dealer did not bust, all players who had a lower score lose; those with an equivalent score "push", meaning they neither win nor lose their wager.
That's the concept behind blackjack. There are some edge cases not discussed here, such as splitting and doubling down and buying insurance, but these are the core rules.
Examining the Game's Workflow
The online blackjack game's workflow can be divided into two sections. First there's the initialization logic. After that, there is a workflow for playing a hand, and this workflow loops until a player reaches $0.00, at which point the system throws an Exception. I'm afraid I didn't have time to address this, so I'll leave this as a challenge for the reader! (Ideally, it should remove the user(s) who hit $0.00, or maybe let them go talk to the burly guy in the corner about a short-term loan. But as it stands, the system blows up if any user reaches $0.00 or less... so there's one incentive to bet conservatively.)
The initialization workflow starts by allowing the user to choose how many decks of cards will be in the dealing shoe.
Next, the user is asked to specify the names and starting bankrolls of those players who will be sitting at the table.
Each player is modeled by a
User object, which is defined by the
User.cs class in the
folder. There's also a
Game class that models the game and a
GameEngine class that has methods
that operates against the current
Game instance that is stored in session state.
GameEngine class has static methods for performing high-level, game-related operations: creating a new game,
Game object in session state, dealing, adding a player to the game, and getting a list of current
GameEngine class is used by an ObjectDataSource on the
PickUsers.aspx page to add
new users to the game through a DetailsView and to list the current players in a GridView, as the screenshot below shows.
Once the game's players have been entered, the in-game workflow begins. Each user is shown their current bankroll and asked how much they want to wager. A RangeValidator is used to ensure that the user's bet does not exceed their bankroll.
Next, list of users and their cards are displayed and each user can decide whether they want to hit or stay. (I also implemented doubling down, which is a blackjack variant where you double your bet but get only one card dealt and then your turn ends.) The dealer's one face up card is also shown. After each player makes his moves, the dealer reveals her hand and follows the rules prescribed to the House. The workflow then ends by adjusting the player's bankrolls based on the end results. In the screenshot below, Scott and Jisun busted because they exceeded 21 points. Sam reached 21, while Dave stayed on 19. The dealer ended up with 20, meaning Sam was the only winner!
Clicking the Play Again restarts the in-game workflow, returning to the page where they players may make their bets.
|Suggestions for Improvement|
Avid 4Guys reader Tim L. wrote in to share the following suggestion for improving the
The most universal way to represent cards in text form is [to] represent numbers 2 through 9 with that digit, represent 10 as "T", and Jack through Ace with the first letter (always [uppercase]). Suit can then be expressed as "c", "d", "h" or "s" (always lowercase).Thanks for the suggestion, Tim!
The Benefits of this Toy Application
If you decide to download and poke through this application, please do bear in mind that it was purposefully rushed, as I was racing against the clock to complete the project. Consequently, the code may be rather tattered in places, there are likely many spots where it should be refactored, and there are next to no comments. Regardless, I think that this application's code does offer some benefits for those brave enough to plow through it:
- It illustrates using the ObjectDataSource to interface with custom classes - all ASP.NET pages except for the trivial
Default.aspxuse ObjectDataSource controls to interface with the classes in the
App_Codefolder. In all but the game-playing page (
PlayHand.aspx), there's virtually no code in the page as it's all handled by the ObjectDataSource and data Web controls in the page.
- It's a working (fun!) game - Next time you're in that meeting with your laptop, but no Internet connection, open this project in Visual Studio and start playing! If your boss catches you or asks what in tarnation you are doing, you can explain you are multi-tasking - attending the meeting and improving your ASP.NET development skills