So yesterday I decided to see how long it would take to program a simple game.

Rock, Paper, Scissors has some of the most clearly defined rules for games.

Process

So, I fired up Visual Studio 2013 Express and started creating a console application. The initial version would take user move input as a text string, generate a cpu move using a “random” number, calculate the result and dump it to the console.

Enter your choice (Rock, Paper or Scissors): rock
user
User input: rock
Cpu Guess: paper
Result: user

Commit: ee80829cc56902ecf831e153a7214a12415bc67d

Timestamp: 2014-02-08 16:49:26

Then I chose to store the game data as a few enumerated values (named “moves”) rather than a selection of strings – this would lead to the game data being greatly smaller (a few padded bytes rather than a lot of padded strings). I also decided at this point to expand the rules to the “…Lizard, Spock” variant of the game.

You can read about the “Lizard Spock” variant here: [LINK]

Game data was still being accepted as strings and outputted as strings.

Commit: 70c89ca0130a850b7ccccd3ccf66c736081e5f5

Timestamp: 2014-02-08 17:46:14

At this point, I decided to change the program from a console application to a Windows forms application. This meant that the user wouldn’t be typing their guess, they would be choosing one from a drop down menu. The game loop was also moved off to the Windows form at this point.

Commit: 2064cac5943ae4e6c6cb3a68b93885224dff28a8

Timestamp:2014-02-08  18:54:30

I began removing deprecated code and cleaning things up. At this point, I decided to change the way that game results where reported to the user

Game number: 2
User move: Rock
CPU move: Paper
Result: Loss

This was reported to the user via a RichTextBox on the Windows form.

Commit: 6058914079c632dd84a3f4b7d2df2f75b621e56d

Timestamp: 2014-02-08 19:08:54

I had a minor reshuffle of the user interface, adding a PictureBox that would show the visual representation of the rules and a ToolTip for the rules picture.

Commit: 83f7e668460b8806490b6b0aa84ca524492fde7e

Timestamp: 2014-02-08 19:25:20

At this point, the game was 99% complete. The game took user input; generated a cpu move; calculated the result; reported the result to the user and stored previous game data to memory.

This was when I decided to change the build data (I forced x86 release mode, meaning that the compiled binary would run on both 32 and 64 bit versions of Windows) and added descriptions of the application in the build properties.

Commit: f5605b02a563e36f1fbe0425c9d7ea86b8cd75d9

Timestamp: 2014-02-08 19:31:51

The final source code commits of the day were related to formatting of the code and adding details to the readme (where to download the compiled binary from, how the game works, etc.).

Commit: efcdc6252c37bd6588478a7ce4ff134c17fe27be

Timestamp: 2014-02-08 19:48:50

Programming began at: 2014-02-08 16:49:26
Programming ended at: 2014-02-08 19:48:50
Total time taken: roughly 4 hours

Adding Bells and Whistles

Why not have the result stored in an enum? It’ll take up less space in memory than a bunch of strings.

So I edited the code to store the result of each game round in an enumeration (the values are “Win, “Loss” and “Draw”). This meant a re-write for calculating the result.

I also decided to build C# style accessors and mutators for the move data. This leads to greater readability. For example:

switch(game.UsersMove) //new style
switch(game._userMove) //older style

Then I decided to add regions to the code base. I use regions, when programming in C# with Visual Studio, as a great way of hiding code blocks that aren’t relevant to what I’m working on. If I’m working on a constructor, for instance, I can hide everything but the properties of the class.

Commit: f5605b02a563e36f1fbe0425c9d7ea86b8cd75d9

Timestamp: 2014-02-09 17:36:55

Why not add stats? Like the number of times that a user played a specific move, the number of wins and losses and such.

I needed a button that the user could press on to generate the statistics. A quick click-and-drag and I had one. Two more lines of code and the stats button was only enabled after 10 rounds.

Stats generation was added in the form of a new class. When the stats button is pressed, the current list of rounds is passed to the stats class, the stats are generated, then they are sent back to the main user interface as a string.

Wins: 0
Losses: 2
Draws: 8

User stats
Rock usage (%): 25
Paper usage (%): 50
Scissors usage (%): 25
Lizard usage (%): 0
Spock usage (%): 0

Cpu stats
Rock usage (%); 10

etc.

This string was then outputted via a MessageBox.

Commit: dec1d6dfaeefb1db51ccc0a302fc4bf219cc7370

Timestamp: 2014-02-09 18:14:03

The final piece of code I added was to have the returned stats string dumped to the RichTextBox that contained the results from each round.

Commit: ede9161f0d6a74e23a557106be73194f096e6d25

Timestamp: 2014-02-09 18:15:24

Additions began at: 2014-02-09 17:36:55
Additions ended at: 2014-02-09 18:15:24
Total time taken: roughly 45 minutes

Post Mortem

The extremely simple rules of “Rock, Paper, Scissors” meant that programming it was extremely quick – the initial “quick-and-dirty” version took very little time to program. Giving the game a Windows form user interface with buttons, a RichTextBox, PictureBox and a Tool.Tip took a little longer. Adding complexity and code safety took the longest amount of time.

Going from a blank Visual Studio project to a full version of the game with a Windows forms user interface, previous game rounds stored in memory, and statistics generated on demand took just under 5 hours across 2 sittings.

This is one of the reasons I really like C# and Windows forms applications for rapid application development. The inclusion of source control meant I could begin adding a feature and, if it didn’t work out, simply roll back to were I was before-hand.

Final Thoughts

“Rock, Paper, Scissors, Lizard, Spock” was an especially quick game to program. I took the time to comment the code base as I was writing it (as is my way – more on this in another post, I guess).

I’ve released the source code using a GPL v3 license

You may copy, distribute and modify the software as long as you track changes/dates of in source files and keep modifications under GPL. You can distribute your application using a GPL library commercially, but you must also provide the source code. GPL v3 tries to close some loopholes in GPL v2. – via tl;dr legal

The source code has been added to a GitHub repository, which can be found here: https://github.com/GaProgMan/RockPaperScissors

I’ve also created a compiled binary (which can be downloaded as a compressed zip file here). Give it a try and tell me what you think in the comments.

J

Related Post


GaProgMan

Jamie is a .NET developer specialising in ASP.NET MVC websites and services, with a background in WinForms and Games Development. When not programming using .NET, he is either learning about .NET Core (and usually building something cross platform with it), speaking Japanese to anyone who'll listen, learning about languages, writing for this blog, or writing for a blog about Retro Gaming (which he runs with his brother)