Modeling Practice: UNO in C# Part 3 - Final Steps and Playing The Game

Note: This post is the third in a three-part series which attempts to model the card game UNO as a C# application. Here's Part One and Part Two. You may want to use the GitHub repository to follow along.

The Game Manager

The most critical component that we haven't yet built is a class called GameManager. In a real UNO game, the players themselves are responsible for keeping track of everybody else following the rules. However, in our model, we'll need a non-player class to do this, as well as control the game flow and keep track of which player's turn is next.

Here's the skeleton of the GameManager class. The next step will be to establish what each of these methods actually do.

Creating the Game

The first method is just the GameManager class's constructor, which we will use to set up the game being played. The only input to this method is an int numPlayers, which is the number of players that will be playing the game.

Given the number of players, the GameManager must set up the game, which consists of:

With all that setup out of the way, we can finally let GameManager start an actual game!

Playing the Game

GameManager kicks off the game by telling Player 1 to take his turn. Play must then proceed (to Player 2, then Player 3, so on) until somebody plays a Reverse card. At that point, we need GameManager to note that a Reverse card was played and reverse the turn order.

GameManager also needs to stop the game when a player no longer has any cards in his/her hand.

We can implement the actual playing of the game using the PlayGame() and AddToDiscardPile() methods like so:

Whew! We are finally done with our code. All that's left to do now is to run a sample game!

Running a Sample Game

With all the code in place, let's run the app a few times to make sure it works the way we think it does.

The first time we boot the app (there's a complete working version over on GitHub), we'll see something like this:

Well well, looks like Player 3 has a pretty good hand, what with all the wilds. But, let's run the app to see how everyone does.

And, sure enough, Player 3 ends up winning the game. Those wilds help.

Drawbacks of This Model

As I've said many times throughout this series, the point of those posts is not to model UNO precisely, the point is to take a complex real-world problem and break it down into smaller, more manageable little problems.

That said, I can identify a few ways in which, given unlimited time, I might improve this model:

Different player "personalities": Not every player is going to be a stupid jackass. I'd like to model different kinds of player strategy (e.g. offensive vs. defensive, hold wilds vs play them, etc.).

A GUI: I mean, I know the hardcore programmers among us LOVE them some command line, but really this could use a GUI to make it pop.

Rules modification: Different UNO sets use different kinds of rules, and I love to find a way to model lots of different rules and have the players react to them.

That said, I'm pretty darn happy with how this turned out.

Summary

The point of modeling practice is to practice. Sounds obvious, I know, but I firmly believe that the difficulty in creating complex software programs is not writing the code, but in getting the correct requirements. Modeling practice helps us consider all possibilities, and when we do it against a known game like UNO (or Candy Land or Minesweeper) we have a distinct set of rules to work against, something we often lack in real-world projects.

As always, feel free to leave any comments you may have (good or bad) in the comments section below, and check out the GitHub repository and maybe even run the app a few times. I'm quite proud of how it turned out.