I’m such a tease. For the last two weeks, I’ve been tempting you with a game of hangman, promising you real PHP code that actually works… none of that silly pseudo-code business. Can you blame me? I’ve got to keep you all coming back somehow…
Well. Today, I tease no more, my friends. Not only do I have real code for you in today’s blog post, I actually have code that you can download. For free. With tons of comments throughout that explain everything. Yes, I’m awesome like that.
And, even better, you can actually run this code on your own server (or hop on over to mine), and play an real working game (or several) of hangman. (No, really! Click the link, it’s awesome. And then come back and read the rest of the post.)
THE CODE: the abridged version
If you download the code itself, you’ll see there are a few things I don’t talk about today, like sessions and form HTML. These are way, way beyond the scope of today’s post, although I may get to them someday. But I’ve tried to leave comments within the code that will explain everything so it’s not too difficult to understand.
For the purpose of today’s post, this is the code we’re looking at, which is really just an excerpt of the code you can download:
$word = 'sushi'; if ($guessLength < strlen($word) && $hangman < 6) { $message = "The game's not over yet..."; $match = false; $guess = [users guess]; $positions = array(); if (in_array($guess, $alreadyGuessed)) { $message = "You already guessed '" . $guess . "'!"; $isGuessed = true; } if (!$isGuessed && $guess != null) { $alreadyGuessed[] = $guess; for ($j = 0; $j < strlen($word); $j++) { if (strcmp(substr($word, $j, 1), $guess) == 0) { $match = true; $positions[] = $j; } } if ($match == true) { foreach ($positions as $k => $position) { if (strcmp($display[$position], '_') == 0) { $display[$position] = $guess; $guessLength++; } } } else { $hangman++; } } } echo $hangman . ' bad guesses.'; foreach ($display as $l => $letter) { echo $letter . ' '; } echo $message;
Like always, let’s go through it, line by line.
Initial Variables
$word = 'sushi'
; This one’s easy. (Although in the actual game code, it randomly chooses from a list of words instead.) All you’re doing is setting your $word
variable equal to the value, ‘sushi’. Sushi has to go in quotes (technically you can use either single quotes: ‘ ‘ or double quotes: ” “) because it’s a string – a bunch of characters all put together.
In the actual code, there are a few other variables like $hangman
, $guessLength
, $alreadyGuessed
, $hangmanImage
, and $display
that are also set, using sessions. For the purpose of today, you don’t have to know how it’s done, just know that they’re there.
The Outer If-Statement
Next, we open the if-statement. (Yes, it was a while loop in last week’s pseudo-code. While hypothetically that works great, since in a true human game it’s continuous, it doesn’t work quite so nicely in the computer world. So we use an if-statement instead.) Since it’s an if-statement, we need a condition to test, right? Here, our condition is actually two conditions, that both must be true. The first one, $guessLength < strlen($word)
, says that we’re only going to keep playing the game so long as the number of letters that we’ve guessed right is less than the number of letters in the word. Because if you think about it, there’s no point in continuing to play the game if you’ve already guessed the entire word, right?
The second condition in the if-statement, $hangman < 6
, tells us that we’re only going to keep going if there are less than 6 parts in the hangman. (Head, body, two arms, two legs.) If the hangman is complete, meaning there are already 6 parts there, then the player has lost the game and we don’t want to continue playing.
You see the opening curly brace right after the conditions, but where’s the closing one? Remember – just like in HTML, your PHP code is like an onion. So each layer has to completely enclose the layers within it, and be completely enclosed by the layers outside of it. So the closing curly brace for our if-statement is at the end – after all the other inner loops have closed. The indentation makes this simple – you can easily see the closing brace because it’s on the same indentation level as the opening one.
Even More If-Statements
Just inside of the outer if-statement, you see a few more statements before your for-loop. The first is a variable that’s set to text which we’ll print out later. Then two variables: $match
which is set to the boolean value false, and $guess
which is set to the single letter that the user has guessed. Super easy. Making sense so far?
Before you step inside the for-loop, you also create an array called $positions
… but don’t put anything in it quite yet. But we will, soon. Don’t worry.
Then a couple of if-statements. By now, you should be able to make some sense of them. The first one is simply making sure that the letter isn’t one you’ve already guessed, and printing out a message if you have. And the second one is saying that if you haven’t guessed the letter and your guess isn’t blank, then keep going with the code inside. You put the guess into the array of letters you’ve already guessed, so you can’t choose it again… and then you get to your first for-loop.
Moving On, The For Loop
Next comes your for-loop. Remember last week, when I explained the code you see here? Well, this week you see it in action. We’re starting at zero ($j = 0;
), looping for the length of the word ($j < strlen($word);
) and incrementing by one each time you go through the loop.
Then there’s an if-statement. It’s the fourth one you’ve seen in today’s code, so you’re sure to be cool with it by now. And I know you’ve seen that strcmp() function before. So what’s that substr() function do? It takes the sub-string of the string $word
, starting at position $j
in the string and taking the next 1 letter. So since our word is ‘sushi’, and if we’ve looped so $j = 1, substr($word, $j, 1)
will be ‘u’. (“But why? Isn’t the first letter in ‘sushi’ ‘s’?” Yes, however remember that in programming, you always start at zero. So the letter at position 0 in ‘sushi’ is actually ‘s’, and the letter at position 1 is therefore ‘u’.)
So, if the substring is the same letter as the one the player guessed, then we’ll say that yes, there is a match – we’ll set $match = true;
. In addition, we set $positions[] = $j;
. But wait, what does that mean? Like the name suggests, the $positions
array is an array that tells us which positions in the word have been guessed correctly. So if our word was ‘sushi’, and the player guessed ‘u’, then we would add $j
(which at that point equals 1) to the array.
And we keep looping through the for-loop until we’ve checked your guess against every letter in the word.
Even Better, A For-Each Loop
Another if-statement. Yes, I know, y’all are experts at if-statements by now. I’m so proud of you. So we’ll skip over that, and look at that foreach loop. All it’s saying is that for each object in the $positions
array, we’re going to call the key $k
, and the value $position
. (Remember that they’re paired up – every key matches up with a value. Like how every SSN matches up with a person.) So that little block of code just says, if the position you’re looking at still shows up as _
, meaning you haven’t guessed it yet, then put in the guessed letter. Otherwise, if there isn’t a match, then add a part to the hangman.
Hold On… That’s It?
Yep. That’s all. As you can see, all that’s left after that are echo statements (and another sneaky but simple foreach). See? You got this!