Card Game War

Posted on by admin

Frequently Asked Questions

The game continues in this manner until both players turn over a card of the same rank, at which point you enter a war. A war can progress in one of three ways. Each player puts a card face-down on top of the tied card and then one face-up. Whoever has the higher face-up card. War is a simple card game where a player is supposed to win all cards or at least 3 wars against the opponent to win the game. PLAYER - At the begining the two players are dealt 26 cards each face-down (half of one complete deck). WASTE - Two empty waste piles, one for each player. WAR - Two empty war piles, one for each player. Each player turns up a card at the same time and the player with the higher card takes both cards and puts them, face down, on the bottom of his stack. If the cards are the same rank, it is War. Each player turns up one card face down and one card face up. The player with the higher cards takes both piles (six cards).

Q: Why won't you add rule-variations/replayable-games/any-other-feature? It would make the game much better.

A: We get a lot of requests from people that just want one tiny little feature added to a game. What they don't realize is that if we start implementing all the suggestions we get then the games will no longer be simple. The number one praise we get is that the interface is simple and uncluttered and it's easy to play. That's very much deliberate. There is no login, no loading screens, as few options as possible. We want to keep it as simple as possible, and that means each game only has one set of rules, you can't choose variations, we try to add as few controls as possible to the screen etc. So, don't feel bad if you make a suggestion and I deny it, we deny 99% of all suggestions.

Q: Why can't I see my statistics on another computer?

War

A: This goes back to simplicity again. We don't want people to have to login to the site. We don't want to keep passwords in a database and be responsible for them. Your statistics are stored in your browser, we don't store them anywhere. That means that as soon as you switch browsers you won't see the same statistics.

Q: Does this site use cookies and/or track people?

A: Yes, this site uses cookies. They are used for game purposes, like remembering your scores between rounds, but also to gather aggregate data on people's browsers, screen resolutions and more, which helps us figure out what we need to support. Finally they are also used for advertising purposes. A more detailed description of our cookie use can be found in our Privacy Policy, and you can always reach out and contact us if you're concerned about it.

Q: Do the computer players cheat? Are the games fixed?

A: No. In all the games the cards are dealt randomly at the start, and the computer players make their decisions based only on knowledge of their own hands, and knowledge of what has been played. Basically they use the same information as a human player would have available to them.

Q: I saw an offensive ad. Can you remove it?

A: If you see an ad that is offensive to you then please contact us and we'll try our best to block it. Due to the way advertising works we can't always immediately find the ads to block them, but if you send a screenshot of it, or you remember any text on it or a url then there's a much higher chance that we can find it and block it.

War

NOTE: This is Part 2 of a three-part series demonstrating how we might model the card game War as a C# program. Part 1 is over here. You might want to use the sample project over on GitHub to follow along with this post. Also, check out my other posts in the Modeling Practice series!

Now that we've got our Objects, observations, and other rules in place, it's time to start building them!

The Card

Let's start with the simplest object in this model: the card itself.

In our model, each Card has three properties:

  1. A Suit (Hearts, Clubs, Diamonds, or Spades)
  2. A Value
  3. A Display Name (e.g. '10D' for 10 of diamonds, 'AC' for Ace of Clubs, etc.)

I ended up using a C# enum to represent the Suit of the cards, so here's that enum plus the Card object:

Player

Now let's start with a very simple definition for the Player object. A player, in our model, has the following properties:

  1. A name
  2. A collection of cards (this is the player's deck).

So, our player object looks like this:

Now before you go yelling at me, let me explain why there is no Deck object...

Deck of Cards

Here's the first secret in our model: there actually isn't an object called Deck. Rather, we implement a deck of cards using the built-in Queue<> object in C#. That collection has almost all the functionality we need to implement a deck of cards, so why not use it?

Key word: Almost. We need one other method to make our code simpler: a method which can 'enqueue', or place into the collection, a collection of Cards rather than just a single one. Here's that extension method:

The Deck of Cards

Even though there is no Deck object, we will still need to create a standard 52-card playing card deck and shuffle it.

A standard deck has 13 cards for each of the four suits: an Ace, cards numbered 2-10, a Jack, a Queen, and a King.

Game

Here's a static class DeckCreator which will give us a standard deck of cards:

Note the unusual for declaration. We are going to make 13 cards per suit, but each card will have a value from 2 to 14. This is because Aces are high in this game (higher than Kings), and we want to compare values easily.

Also, note the Shuffle() method that we haven't implemented yet. I previously wrote a post on the Fisher-Yates card shuffling algorithm and that's what we're going to use to shuffle the cards.

Finally, we need to handle the GetShortName() method. We don't want to be displaying 'Ace of Spades' every time that card appears, rather we want to show the short name 'AS' (or '5C' for 5 of Clubs, or 'KD' for King of Diamonds, and so on). So we need a method to assign this short name to each card, like so:

With the card, player, and 'deck' in place, we can finally create the last and most complex object in our model: the game itself.

The Game

In this modeling practice, like several of the others, the game itself is represented by an object. The properties of this object are the things required to play a game. In real life, what we would need to play a game is simple: two players, and a deck of cards.

However, we also need to end games if they become infinite, so we need to keep track of the number of turns elapsed.

Remember that our model makes the deck a property of the Player object, and so it will not be declared in the Game object.

Now we need to think about the steps involved in playing a turn in War. Here's what I came up with.

  1. The first step is to create the players, shuffle the cards, and pass a deck to each player.
  2. The players play turns until one player is left without any cards.
  3. There is an 'end of game' check which sees if either player is out of cards.

The first step is relatively easy, so let's code that up:

The end-of-game step is also relatively easy, so that's next. In the real world, end-of-game happens whenever a player is out of cards.

Decision Point: In Part 1, we discussed the possibility of infinite games of War. In our model, we want to avoid said infinite games, and so we'll forcibly end the game after 1000 turns have elapsed (the reasoning for this particular number will be in Part 3 of this series).

Here's that end-of-game check method in the Game object:

Now we have to deal with the most difficult of the three steps: playing a turn.

Playing a Turn

Playing a turn in War would be simple, if it weren't for the whole War mechanic. Flip two cards, higher card gets both. This sounds simple, but the War mechanic makes this more difficult than it sounds.

Before we show the code for this part, let's walk through the logic involved.

  1. Each player flips a card. If one card is bigger than the other, that player gets both cards.
  2. If the two cards are the same value, we start a War. Each player lays down three cards, and flips the fourth one. If one of the flipped cards is bigger than the other, that player gets all the cards on the table.
  3. If both flipped cards are the same, repeat the process (place 3, flip fourth) until one player has a bigger card than the other
  4. If a player runs out of cards during this process, they automatically lose.

Card Game War Unblocked

Decision Point: In Part 1, I mentioned that the 'official' rules of War do not say what happens if a player runs out of cards during a War. In this model, I am making that scenario an immediate end-of-game, as it simplifies the system as a whole.

There's one trick we're going to employ: for the face-down cards during a War, we're going to put them in a common pool. At that point, it doesn't matter who placed them, it just matters that they go to the winner of the War.

With all this in mind, here's the code:

Decision Point: In Part 1, we discussed that War in real-life is not deterministic, meaning that the outcome cannot be known after the cards are shuffled because they will be added to players decks in random order. Our model, almost by accident, has made War deterministic; cards are always added to player decks in a known order. Therefore, if we wanted to, we could 'know' after dealing which player will win. It's up to you, dear readers, to decide what to do with this information.

Card Game War Variations

Guess what? We now have a simple C# application that can play games of War! But we're not done yet. In the final part of this series, we'll run this system thousands of times, to see whether or not we accidentally biased it and how we might improve.

Don't forget to check out the sample project on GitHub!. As always, constructive criticism and tips to improve this project are welcome. Share your thoughts in the comments!

Card Game War Rules

Happy Coding!