Thursday, April 1, 2010

Game In A Day - "Hangman"

The second installment to my Game In A Day series is a project I started many years ago, and have maintained in not-so-consistent fashion: Hangman.

I wrote this about 5-6 years ago in C++. The interface was console-based only and this lead to a lot of added headaches and bugs. I've been meaning to throw a GUI on this project for a while, but just never got around to it... until now!

As part of my Software Engineering capstone, my group and I are making a set of educational games to teach 4th and 5th grade curriculum in Math, English, and Reasoning Skills. The English side of things was lacking a bit, so I decided to create Hangman in the context of my capstone project. Note that at the time, there were only 4 weeks left in the course and we had moved every other project into their final phase. So, if Hangman was to be added, it would definitely have to be developed in less than 1 day!

Interface Design
I came up with the design in a fairly short amount of time while I was sitting in one of my morning classes. Obviously, Hangman is a classic game and interfaces for it can only vary so much, but I did add a few tweaks. First, I designed it so that the vowels and consonants are displayed to the user in horizontal list form. This assists in the curriculum for the target audience as they can learn to identify the different letters as well as learn the words and definitions. Second, guessed letters (both correct and incorrect) get removed from their respective lists. This helps the player keep track of what they've already guessed and what's available to guess. Last, I added a "Solve" button to the interface so that at any time they can choose to solve the puzzle.

Game Design
Much like the interface design, the gameplay for Hangman is relatively set in stone. The flow that I went with is as follows:
  • A definition is displayed to the player
  • Below the definition, a series of _ characters are displayed to the player to represent the number of letters in the answer
  • When the player types a letter, the game checks to see if that letter is in the puzzle, and if so, replaces each corresponding _ with the guessed letter.
  • A wrong guess results in the next Hangman image being displayed to the player on the interface. The images are looked up using the number of questions wrong as the index into the vector of images. In total, there are 9 images, and the game is over when you've missed 9 questions.
  • At any point the player can choose to hit "Solve" and try to solve the puzzle. An incorrect guess results in the player losing.
Pretty simple, eh?

Tools
I decided to use C++ and QT for this project because I'm very familiar with QT and it is an incredibly powerful library.

Implementation
Instead of adding a GUI to the pre-existing code I had, I decided to write the entire game from scratch. Using QT made this quite simple, actually. It allowed me to use the built-in QT types for everything (QString, QChar, QVector, etc...) and keep the code clean and consistent. You would think that writing a game entirely console-based would be easier, but when you have to deal with validating user input, alternating between std::string, char*, and char, things get messy in a hurry. Also, organizing game flow and game state create equally messy situations. A GUI environment like QT eliminates this mess with the use of dialogs and events to properly handle flow and state changes.

All in all, the implementation was fairly straight forward and consisted of the following pieces:
  • Event handler to grab alphabetic input (ignores all other input)
  • Function to check if a letter exists in the answer (and every location in which it does)
  • Function to handle solving the entire puzzle
  • Function to remove the last guessed character from both the vowel and consonant lists.
  • Functions to handle a correct and incorrect guess
  • Function to handle the end of the game
  • Function to handle resetting the game to the initial state
That's it. Total, the project only took around 5 hours from start to finish, so I'm very pleased with that result. The only thing left to do is to plug it in to our QuestionManager to dynamically grab pre-made questions.

Notable Code Snippets

Determining If Input Is An Alphabetic Character



Finding Every Occurrence Of A Letter In A Word

No comments: