Yep, you read that right! We're going to code up a new game in Blazor WebAssembly, and I'm proud to announce that it is quite possibly the single biggest time-waster in all computer history: solitaire!
We're going to need a multi-part series to build this thing, but the project is already available on GitHub if you just can't wait to check it out:
Let's jump right in!
Play it Now!
This game is already available to play at my sister site, BlazorGames.net.
How to Play Solitaire
NOTE: The version of solitaire we are going to play is properly called Klondike, and the rules we're going to implement come from Bicycle Cards.
If you already know how to play Klondike, skip to the Breaking Down the Game section below. The rest of this post and all other posts in this series will refer to this game as Solitaire.
If you've never heard of Klondike, you'll want to check out the rules (from Bicycle Cards) below, and then follow the walkthrough.
Walkthrough
The playing surface of Solitaire is divided into several sections. Here's the layout of a typical Klondike Solitaire game:
In the upper left we have the draw pile; to the right of that are the discards, which shows the last three drawn cards, most recent first; to the right of those are the four suit piles (clubs, diamonds, spades, and hearts). Finally, at the bottom are the stacks. Some of the cards in the stacks are hidden, and cannot be revealed until no other cards are on top of them.
The goal of Solitaire is to get all cards into the suit piles, in order, starting from the Aces, then the twos, then the threes, and so on until the kings. Cards can be moved from the top of the discards, or from the bottom of a stack, into the suit piles.
For example: in the screenshot above, the Ace of Spades is showing at the bottom of the fourth stack. This could immediately be moved to the Spades suit pile.
Cards in the stacks can have other cards stacked on them, provided they are the opposite color and one rank lower. From that same screenshot, the queen of diamonds could be stacked on the king of spades, because a queen is one less than a king and the queen is red while the king is black. That looks like this.
Cards can continue to be stacked in this manner indefinitely; once a jack of spades or a jack of clubs (a black jack) is available, it could be stacked onto the queen of diamonds.
We now have two cards (one each in the fourth and fifth stacks) that have "hidden" cards at the bottom of the stack. We can now reveal those cards:
Following the same rules as before, the five of diamonds can be stacked on the six of clubs, and the ten of clubs can now be stacked on the jack of diamonds. Doing this allows us to reveal two more cards:
Cards from the discards can also be added to the stacks, provided they follow the same rules. For example, drawing more cards eventually reveals the nine of diamonds...
...which can be stacked on the ten of clubs:
One other thing: it's possible for a stack to be empty. We could move the four of spades to stack it on the five of diamonds, which creates an empty stack (represented by the grey card back):
Only kings may be placed onto empty stacks. In this case, let's move the king of clubs to the empty space, and reveal the card that's behind it.
Let's keep playing. Later on in the draw pile, we find the two of spades.
...which can be placed onto the spades suit pile.
Now we can add the three of spades to the suit pile, which makes another empty stack.
We can move entire stacks of cards, provided they follow the same rules as before. So, let's move the stack starting with the king of spades to the fourth stack (the empty one), and reveal the card behind it.
We could then move the cards in the sixth stack (starting with the jack of diamonds) to the newly-revealed queen of clubs, and reveal the card behind that stack.
Game play continues like this, until either all cards are in their suit piles, or the player cannot make any more moves. Not all games of Klondike Solitaire are winnable.
Rules Summary
In short:
- Players draw cards one at a time from the draw pile, and place them onto the discards.
- Players can move cards from the discards to the stacks, or from a stack to another stack, provided they stack on opposite colors, and in rank order (queen-jack-ten-nine, or six-five-four, or similar)
- Players can move entire stacks of cards from one stack to another, provided they follow the rank and color rules.
- Cards can be moved in order to the suit piles (starting with aces, then twos, then threes, and so one).
- Cards can also be moved individually from the suit piles to the stacks, provided they follow the same rules.
- Once all cards are in the suit piles, in order, the player WINS.
Breaking Down the Game
Let's take some time to identify how we might want to break down Solitaire into small components, so that we can implement those components in C# and Blazor.
The smallest unit available to us is the individual cards, so we'll need a class for them.
Each card has a suit (e.g. clubs) and a value (e.g. ten, jack, four, etc.), so we need to represent those as well.
Solitaire has several piles of cards:
- Draw pile
- Discards
- Suit piles
- Stacks
We can probably represent most of these with a single common base class. Said class will need to keep a collection of card objects, and provide ways to add, remove, or check cards.
Some of the piles will have specific functionality. For example, the suit piles must be able to know what card they expect next; we cannot place a spade into the hearts pile, or the two of clubs into the clubs pile without first having the ace of clubs there.
Stacks also have specific functionality, namely the rank-and-color rules (cards must be stacked in descending rank order, and with alternating colors, e.g. black jack, then red ten, then black nine, then red eight, etc.).
Finally, we need something to represent a game in progress, so that we can know if we want to display the game area to the user. This will most likely be a GameStatus
enumeration like we've used in previous games.
The Series
We're going to implement this game in several parts, similarly to how we did Tetris.
In each of these parts, we'll build another layer, feature, or component of the game as a whole. At the end of four parts, we'll have a working game; the fifth part will implement a couple of cool extras.
Here's the rest of the posts in this series:
- Part 2: Implement the C# classes, including the different kinds of piles and their common and distinct functionality.
- Part 3: Create the Blazor components for the draw pile, discards, suit piles, and the stacks, with their base functionality. We'll also write code to start a new game.
- Part 4: Implementing simple drag-and-drop. We'll use
EventCallback
and Blazor components to implement dragging cards to the suit piles and the stacks. We'll also implement revealing cards, as well as dragging from the suit piles to the stacks. At the end of this part, we should have a fully-working game. - Part 5: We'll code up a couple of nice extras: a double-click shortcut for stacking cards on the suit piles, and an autocomplete.
Posts will be published weekly, so don't go anywhere! Want to make sure you get all these posts in your inbox? Sign up for the mailing list today!
Summary
I am very excited to have a new game in the BlazorGames collection, and particularly one where I wasted so many hours when I should've been working. When we're done with this series, we'll have built a fully-functional, fun-to-play Solitaire game in Blazor WebAssembly!
Stick around, and Happy Coding!