Representing Progress

The word the player is guessing is a string, made up of characters. Two of the most important kinds of data structures we deal with in Clojure are maps (keyed by an index) and sequences (which rely on sequential traversal). We have a number of choices for representing the progress in the game, but choosing between an indexed or sequential view is the critical decision.

So let’s think, at least at a high level, about the operations that use this data structure in the code. The update-progress function seems like the one we care about the most. Given the word and the guessed letter, you need to check whether each letter in the word matches the guess, and if so, update the progress, which keeps track of all letters guessed so far in the word.

Looking back at that description of the update operation, you need to check whether “each letter in the word” has some property. This indicates that a sequential traversal based on the original word would be a good match (considering all values). You then need to update the progress data structure in the corresponding location if there is a match.

If the progress is an indexed data structure, you need to traverse the original word and keep track of the index as you do so, to know which index to update in the progress. The Clojure sequence library includes some functions, keep-indexed and map-indexed, that help with this kind of thing.

If you instead treat the progress as a sequential data structure and update it at the same time that you traverse the original word, you can avoid tracking or using the indexes at all. When the progress is a sequential data structure where each element might need to be updated, you should strongly consider map, which transforms every element. Additionally, map is one of the only sequence functions that can traverse multiple sequences at the same time.

So let’s proceed on the assumption that a sequential structure with each element corresponding to a letter in the original word is the working model. You could use some kind of flag to indicate which letters have been guessed: (false false true true false). Or you could use the actual letters and a known “blank” character: (\_ \_ l l \_). (Recall that literal characters are represented with a leading in Clojure.) The latter representation gives you a built-in human readable representation of our progress, so it might be slightly more useful, but in truth either would work.

We’ve spent enough time thinking about our data structure at this point. While that took a while, it was time well spent because you can proceed with your functions with a clear sense of the needs and constraints of the data.

Start with new-progress. Given a word (a string), you need a sequence of blank characters of the same length. Here you can reach into the sequence function bag of tricks and pull out repeat, which creates a sequence of the same element of a specific length, here the count of the word:

 (​defn​ new-progress [word]
  (repeat (count word) ​\_​))

Now for the update. We already established that you want to map over both the word (a string, automatically treated as a sequence of characters) and the progress (a sequence of characters, either the actual character or a blank). The map function will take two inputs—a letter from the word and the corresponding letter from the progress. It needs to output the new letter in the updated progress. You also have available from the outer function the letter that was the guess.

Putting all that together is actually pretty easy—you just need to check whether the guessed letter matches the word character, and if so, include it in the updated progress. If not, then use the original progress character to remember the progress so far.

 (​defn​ update-progress [progress word guess]
  (map #(​if​ (= %1 guess) guess %2) word progress))

Finally, checking whether the player is “done” is just a check of whether the characters in the original word match the progress. Because the word is a string, explicitly convert it to a sequence for comparison purposes.

 (​defn​ complete? [progress word]
  (= progress (seq word)))

And that’s the core of our game loop. Now you need a player.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
52.14.172.93