Introduction
Recently I came across the hangman sample code
on ASP101.com. This code illustrates how to create a hangman
game using VBScript in an ASP Web page. I decided this would be a fun project to implement
in ASP.NET. Rather than attempting to port the application directly, I decided to write it from
scratch. In this article we'll look at the code for the hangman game in ASP.NET (using VB.NET).
If you'd like to take a moment and try out the game first, feel free.
The rules of hangman are quite simple. There's a secret word that you must guess by choosing one letter
at a time. If you chose a letter that appears one or more times in the secret word, the letters and
their positions are revealed. If, however, you guess a letter that is not in the secret word,
then a piece of the man being hanged is added to the gallows. If you incorrectly guess six letters,
the complete hangman character is drawn, meaning you lose!
Investigating the Hangman User Interface
As with any application, it is important to examine what, specifically, how we want the user interface to
appear before tackling any coding. Traditionally hangman is played on paper, with the hangman figure
drawn in the upperleft-hand corner. Beneath this character can be found underscores representing the
letters of the secret word. As the person playing hangman guesses correct letters, the underscores are filled in with
the appropriate letters. When incorrect letters are guessed, the hangman figure is updated. The game ends
when the person fully spells out the word, or when he has guessed incorrectly six times.
Our user interface for this game will borrow heavily from the interface for the paper version. Specifically,
we will have a hangman figure in the upperleft-hand corner. Beneath him will be the secret word, with
underscores used for each letter that has yet to be guessed. Finally, a number of hyperlinks will
exist labeled A through Z. A user guesses a letter by clicking the appropriate hyperlink.
The hangman figure shown to the right is one of seven different images representing the seven different
states of the hangman figure. The first image has drawn just the gallows; the second the head;
the third the head and torso; and so on, up until the seventh figure, which has the complete head,
torso, arms, and legs. These images were shamelessly taken from the hangman example on ASP101.com,
and have been saved locally in the /images directory with filenames
hang_x.gif, where the image specifies the hangman figure to be used
after x incorrect guesses. For example, the image to the right is the image
/images/hang_4.gif, since it represents the figure after four incorrect guesses.
To see the complete user interface, take a moment to view the hangman
demo. The code to generate the user interface can be seen below:
The hangmanImage is an Image Web control that we'll use to display the
current hangman image. The currentWordLiteral control displays the
letters that have been correctly guessed for the secret word (and their positions in the word).
For letters in the secret word that have yet to be guessed, an underscore is displayed. Finally, the
lblEndGameMessageLabel control is used to display a message when the
game is over, either because the player has won or lost.
Choosing a Secret Word
When a player starts a game of hangman, a random word must be selected. This, of course, is the word
that the player must attempt to guess before choosing six incorrect letters. How do we choose a random
secret word? There are a number of approaches, such as having a database table with various words,
and then randomly selecting a word from that table (see this
FAQ for more information on this topic), or having an XML file with elements whose text content is
the secret word, and then randomly choosing an XML element and using that.
I chose to use, in my eyes,
the simplest approach, which involves a text file that contains each potential secret word on a separate
line. To select a random word, the text file is opened and its contents are read line-by-line into
an ArrayList. A random item is then selected from this ArrayList and is chosen
as the secret word. I've not performed any performance tests, but I'd wager this approach is comparable,
if not faster, than the database approach for relatively small lists of secret words. If you want
thousands or hundreds of thousands of potential hangman secret words, the database approach will perform
best.
The following function demonstrates how to extract a random line from a text file. Specifically, the
function opens the text file specified by its input parameter filePath, reads in the
contents into the ArrayListwords, and then randomly selects and returns a word
from words.
Function GetRandomWord(filePath as String)
'Open the file
Dim objTextReader as TextReader = File.OpenText(filePath)
'Read in all the lines into an ArrayList
Dim words as ArrayList = new ArrayList()
Dim word as String = objTextReader.ReadLine()
While Not word is Nothing
words.Add(word)
word = objTextReader.ReadLine()
End While
'Close the Text file
objTextReader.Close()
'Now, randomly choose a word from the word ArrayList
Dim rndNum as Random = new Random()
Dim iLine as Integer = rndNum.Next(words.Count)
Dim selectedWord as String = words(iLine)
Return selectedWord
End Function
Starting the Game
When the user first visits the page, we want to "start" the game. This means that we want to
display the initial hangman image of the gallows (/images/hang_0.gif), select a random
secret word, display the underscores for each letter in the secret word, and other such tasks.
These tasks are performed by a helper subroutine, ResetGame(). Note that the hangman
game uses three session variables. The first, hangman_word, specifies the secret word
the player is trying to guess, while wrong_guesses indicates how many incorrect guesses the
player has currently made. Finally, current_word contains the current partial matches of the
secret word, with asterisks for letters that have yet to be guesses.
For example, if the secret word
is "scott" and the user has made three guesses, guessing letters "S", "T", and "A", the value
of Session("hangman_word") would be "Scott", the value of
Session("wrong_guesses") would be 1 (since one of the three guesses was incorrect)
and the value of Session("current_word") would be "S**TT", since "C" and "O" had yet to
be guessed.
Sub ResetGame()
'This is the first time the user is visiting the page,
'use the defaults
hangmanImage.ImageUrl = "/images/hang_0.gif"
'Choose a random word from a text file
Session("hangman_word") = _
GetRandomWord(Server.MapPath("/demos/hangmanWords.txt"))
Session("wrong_guesses") = 0
'Specify the current "guess", which is no letters guessed
Dim i as Integer
Dim initialGuess as String
For i = 0 to Session("hangman_word").ToString().Length - 1
initialGuess &= "*"
Next i
Session("current_word") = initialGuess
'Put in blanks for the various letters
DisplayCurrentWord()
End Sub
As the above code shows, the list of hangman secret words is at the URL
http://aspnet.4guysfromrolla.com/demos/hangmanWords.txt.
Additionally, the above code utilized a subroutine called DisplayCurrentWord(). This
subroutine simply displays Session("current_word") in the
currentWordLiteral control. The code for this helper subroutine is shown
below:
Sub DisplayCurrentWord()
currentWord.Text = ""
Dim i as Integer
For i = 0 to Session("current_word").ToString().Length - 1
If Session("current_word").ToString().Substring(i,1) = "*" then
currentWord.Text &= "_ "
Else
currentWord.Text &= _
Session("current_word").ToString().Substring(i,1).ToUpper() & _
" "
End If
Next i
End Sub
Now that we've looked at how to get the game rolling, we need to discuss what to do when the user selects
a letter. We'll examine this facet of the hangman game in Part 2.