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.
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 input: rock
Cpu Guess: paper
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.
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.
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
This was reported to the user via a RichTextBox on the Windows form.
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.
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.
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.).
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.
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.
Rock usage (%): 25
Paper usage (%): 50
Scissors usage (%): 25
Lizard usage (%): 0
Spock usage (%): 0
Rock usage (%); 10
This string was then outputted via a MessageBox.
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.
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
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.
“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.