Ask Dave Taylor
  • Facebook
  • Instagram
  • Linkedin
  • Pinterest
  • Twitter
  • YouTube
  • Home
  • YouTube Videos
  • Top Categories
  • Subscribe via Email
  • Ask A Question
  • Meet Dave
  • Home
  • Linux Shell Script Programming
  • How Can I Write a Wordle Clone as a Linux Shell Script?

How Can I Write a Wordle Clone as a Linux Shell Script?

February 10, 2023 / Dave Taylor / Linux Shell Script Programming / No Comments

I’ve been looking at the Wordle app and it seems to me that it’s pretty darn easy to duplicate. I’m teaching myself shell script programming so am wondering if there’s a way to create a wordle for the command line in Linux?

There’s a lot about Wordle that was really smart from the first release, not the least of which is that it’s simple to grasp and hard to master. Since it only has one word puzzle per day, it’s also a perfect casual game for a mobile device on the way to school, work, even while laying in bed, slowly waking up. Six guesses. Five letters. It shows if you guess a letter in the correct slot, a letter that’s in the word but not the first slot, and any letters in your guess that are missing from the word.

The other facet that worked really well is that it’s really easy to share your results with friends on social media. Of course, friends who don’t play Wordle won’t be interested, but hey, those that do can easily compare their number of guesses with yours, and sweet are the days when you get the word in just a few guesses! Since there are no clues, it’s definitely tough because there are thousands upon thousands of 5-letter words in the English dictionary.

Still, if you can code it, you can also code it as a shell script, though it might not be the most efficient or elegant (particularly compared to the simple and effective design of the mobile app). Let’s dig in and see how to recreate Wordle as a Linux and MacOS shell script.

STEP 1: PICK A WORD FROM THE DICTIONARY

Various distros of Linux include dictionaries, but they often include hundreds of quite obscure words that don’t even show up in standard English language dictionaries. The game’s no fun if it’s prompting for words you’ve never heard of, right? Fortunately, the Web comes through and there’s a nice text file of about 5,000 5-letter English words you can grab right off the net at

https://www-cs-faculty.stanford.edu/~knuth/sgb-words.txt

Grab it and save it as “5-letter-words.txt”. Then define a variable so we can refer to it as “dict” in the future:

dict="5-letter-words.txt".

Now let’s get into the first interesting bit of coding: Picking a random word from a text file. This can be done by calculating the number of lines in the file, then using the built-in $RANDOM variable in the shell to generate a random 2**32 integer, modded down to be between 0 and the number of lines – 1:

# 1. Pick a word from the list
lines="$(wc -l < $dict)"
randomchoice="$(( $RANDOM % $lines ))"
word="$(head -n $randomchoice $dict | tail -1)"

Hopefully, that’s all clear to you, using $randomchoice to remember what line we want, then head|tail to pull out just that line from the dictionary. The result is that $word is the word to guess.

Now, while we have it, let’s break it into five one-letter variables. There are lots of ways to do it, but I’ll use a simple cut in a subshell approach:

w1="$(echo $word | cut -c1)" ; w2="$(echo $word | cut -c2)"
w3="$(echo $word | cut -c3)" ; w4="$(echo $word | cut -c4)"
w5="$(echo $word | cut -c5)"

Step one’s done. $word contains the word to guess and $w1 thru $w5 contain the five letters that comprise that word.

STEP 2: PROMPT USER FOR THEIR GUESS

The second step is to create a loop and within it prompt the user for their guess. Easily done:

until [ 0 -eq 1 ] ; do
  echo "\nGuess: \c"
  read answer
  more code will go here done

The rest of our code (with the exception of a function that will show up in a bit) will be tucked after ‘read answer’ but before ‘done’. While we’re processing the guess, let’s break it down into five sequential variables too:

a1="$(echo $answer | cut -c1)" ; a2="$(echo $answer | cut -c2)"
a3="$(echo $answer | cut -c3)" ; a4="$(echo $answer | cut -c4)"
a5="$(echo $answer | cut -c5)"

You can always slice a variable with a ${varname:x:y} notation, but I prefer separate variables for clarity.

STEP 3: CHECK GUESS AGAINST DICTIONARY

Since one of the Wordle rules is that your guess has to be a proper English word, we’ll need to check for that too. Turns out it’s pretty darn easy…

if [ "$(grep -E "^$answer\$" $dict)" = "" ] ; then
  # Is answer in dictionary? If not, don't evaluate it?
  echo "Your guess is not in my dictionary."
else

I’ve formatted this as a conditional because it’s one of a number of tests we’ll apply…

STEP 4: COMPARE EACH LETTER AGAINST TARGET

The next step, and by far the most complicated, is to test each letter of the user’s guess against not just that same letter slot in the target word, but against all the letters in the word. To accomplish this I’m going to create a shell function:

lettercheck()
{
  # answer-letter lettercount
  # all answer letters are already in w1 w2 etc
  # returns value in "$returnchar"

  if [ "$1" = "$(eval echo \$w$2)" ] ; then
    # letter guessed in correct spot!
    returnchar="$(echo $1 | tr "[:lower:]" "[:upper:]" )"
  elif [ "$(echo $word | grep "$1")" != "" ] ; then
    # letter present, wrong spot (needs refinement)
    returnchar="$1"
  else
    # letter not present in word
    returnchar="-"
  fi
}

Since you can pass variables to functions in the shell, it will be invoked with the first parameter the letter guessed and the second parameter the ordinal slot (in other words, if I guessed “carom” then letter 3 would be “r” and it would be the #3 letter in my guess.

Since I can’t change the color of letters guessed, I’m instead using the notation that echoing back the guess with a letter transliterated to uppercase means it’s the right letter in the right spot, if it’s lowercase then it’s the right letter in the wrong spot, and if it’s just a “-” it’s a letter that isn’t present. Can you see how that all shows up in the code above?

STEP 5: EVALUATE GUESS WITH LETTERCHECK

With the function written, it’s time to utilize it, and here’s how I do just that:

echo "Result of your guess: \c"
lettercheck "$a1" 1 ; echo " $returnchar \c"
lettercheck "$a2" 2 ; echo " $returnchar \c"
lettercheck "$a3" 3 ; echo " $returnchar \c"
lettercheck "$a4" 4 ; echo " $returnchar \c"
lettercheck "$a5" 5 ; echo " $returnchar"

I’m taking advantage of the \c notation in echo to have it not include a carriage return, allowing the script to build up an output line letter by letter. Handy!

PUTTING IT ALL TOGETHER

Before I show you all the code with loops, let’s have a look at the output, a quick game of SHWORDLE:

$ sh shwordle.sh 

Guess: birds
Result of your guess: - - - - S

Guess: carps
Result of your guess: - a - - S

Guess: reels
Result of your guess: - E e L S

Guess: zeals
You guessed it: ZEALS! Well done.

I cheated because I knew the word in advance, but you can see that it’s hard, but when you remember that uppercase means correct letter, correct slot, and lowercase means correct letter, wrong slot, it works perfectly. Well, not quite, but I’ll get back to that.

For now, here’s the entire script, line-for-line, including comments:

#!/bin/sh

# SHWORDLE - duplicates functionality of the Wordle word guessing game
#       written by Dave Taylor. Still has a few bugs to iron out.

dict="/Users/taylor/bin/5-letter-words.txt"

lettercheck()
{
    # answer-letter lettercount
    # all answer letters are already in w1 w2 etc
    # returns value in "$returnchar"

    if [ "$1" = "$(eval echo \$w$2)" ] ; then
      # letter guessed in correct spot! 
      returnchar="$(echo $1 | tr "[:lower:]" "[:upper:]" )"
    elif [ "$(echo $word | grep "$1")" != "" ] ; then
      # letter present, wrong spot (needs refinement)
      returnchar="$1"
    else
      # letter not present in word
      returnchar="-"
    fi
}

# 1. Pick a word from the list
lines="$(wc -l < $dict)"
randomchoice="$(( $RANDOM % $lines ))"
word="$(head -n $randomchoice $dict | tail -1)"
w1="$(echo $word | cut -c1)" ; w2="$(echo $word | cut -c2)"
w3="$(echo $word | cut -c3)" ; w4="$(echo $word | cut -c4)"
w5="$(echo $word | cut -c5)" 

# here's a cheat: echo " -- $word -- $w1 $w2 $w3 $w4 $w5 "

# 2. Loop to prompt user for a guess.

until [ 0 -eq 1 ] ; do

echo "\nGuess: \c"
read answer

# 3. break down guessed word into letters 

a1="$(echo $answer | cut -c1)" ; a2="$(echo $answer | cut -c2)"
a3="$(echo $answer | cut -c3)" ; a4="$(echo $answer | cut -c4)"
a5="$(echo $answer | cut -c5)" 

if [ "$answer" = "$word" ] ; then
  # got it! well done
  echo "You guessed it: $(echo $word | tr '[:lower:]' '[:upper:]')! Well done."
  exit 0
elif [ "$answer" = "quit" -o "$answer" = "" ] ; then
  # escape the infinite loop
  echo "The word was $(echo $word | tr '[:lower:]' '[:upper:]'). See ya next time."
  exit 0
else
  # evaluate the guess
  if [ "$(grep -E "^$answer\$" $dict)" = "" ] ; then
    # 4. Is answer in dictionary? If not, don't evaluate it?

    echo "Your guess is not in my dictionary."
  else
    # 5. evaluate and output result:

    echo "Result of your guess: \c"
    lettercheck "$a1" 1 ; echo " $returnchar \c"
    lettercheck "$a2" 2 ; echo " $returnchar \c"
    lettercheck "$a3" 3 ; echo " $returnchar \c"
    lettercheck "$a4" 4 ; echo " $returnchar \c"
    lettercheck "$a5" 5 ; echo " $returnchar"
  fi
fi

done

exit 0

So what’s not quite right? The main functionality issue appears when you have duplicate letters in a word. If you look at the lettercheck code closely, you’ll realize that if the word is, say, zeals and I guess bossy, both ‘s’ letters will be shown as matching a letter in the final word, even though only the first one should be a match. That bug, however, I will leave for you to solve, and remember that it can happen with a duplicate letter in the guess or in the target word. Otherwise, this should give you a big headstart in creating Wordle for the Linux command line. Have fun!

Pro Tip: I’ve been writing about Linux since the dawn of the operating system, and Unix before that. Please check out my extensive Linux help area and Linux shell script programming area for lots of additional tutorial content while you’re visiting. Thanks!

About the Author: Dave Taylor has been involved with the online world since the early days of the Internet. Author of over 20 technical books, he runs the popular AskDaveTaylor.com tech help site. You can also find his gadget reviews on YouTube and chat with him on Twitter as @DaveTaylor.

Let’s Stay In Touch!

Never miss a single article, review or tutorial here on AskDaveTaylor, sign up for my fun weekly newsletter!
Name: 
Your email address:*
Please enter all required fields
Correct invalid entries
No spam, ever. Promise. Powered by FeedBlitz
Please choose a color:
Starbucks coffee cup I do have a lot to say, and questions of my own for that matter, but first I'd like to say thank you, Dave, for all your helpful information by buying you a cup of coffee!
wordle for linux, wordle program

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Search

Recent Posts

  • Guide to Keeping All Your Mac Software Up-To-Date
  • How Can I Send My Friend a Voice Message via iMessage?
  • No, You Didn’t Just Win a Free Golf Cart from Lowe’s [Scam]
  • Handy Advanced Search Techniques for Microsoft Outlook.com
  • How Can I Rearrange Shortcuts on Android 13?

On Our YouTube Channel

Mophie PowerStation XL 20W USB-C Charger -- REVIEW

FOSI Audio Waterproof Bluetooth Speaker B2 -- DEMO & REVIEW

Categories

  • AdSense, AdWords, and PPC Help (106)
  • Amazon, eBay, and Online Shopping Help (164)
  • Android Help (229)
  • Apple iPad Help (149)
  • Apple Watch Help (53)
  • Articles, Tutorials, and Reviews (346)
  • Auto Tech Help (17)
  • Business Advice (200)
  • ChromeOS Help (34)
  • Computer & Internet Basics (783)
  • d) None of the Above (166)
  • Facebook Help (384)
  • Google, Chrome & Gmail Help (188)
  • HTML & Web Page Design (247)
  • Instagram Help (49)
  • iPhone & iOS Help (626)
  • iPod & MP3 Player Help (173)
  • Kindle & Nook Help (99)
  • LinkedIn Help (88)
  • Linux Help (174)
  • Linux Shell Script Programming (90)
  • Mac & MacOS Help (915)
  • Most Popular (16)
  • Outlook & Office 365 Help (34)
  • PayPal Help (68)
  • Pinterest Help (54)
  • Reddit Help (19)
  • SEO & Marketing (82)
  • Spam, Scams & Security (97)
  • Trade Show News & Updates (23)
  • Twitter Help (222)
  • Video Game Tips (66)
  • Web Site Traffic Tips (62)
  • Windows PC Help (952)
  • Wordpress Help (206)
  • Writing and Publishing (72)
  • YouTube Help (47)
  • YouTube Video Reviews (159)
  • Zoom, Skype & Video Chat Help (62)

Archives

Social Connections:

Ask Dave Taylor


Follow Me on Pinterest
Follow me on Twitter
Follow me on LinkedIn
Follow me on Instagram


AskDaveTaylor on Facebook



microsoft insider mvp


This web site is for the purpose of disseminating information for educational purposes, free of charge, for the benefit of all visitors. We take great care to provide quality information. However, we do not guarantee, and accept no legal liability whatsoever arising from or connected to, the accuracy, reliability, currency or completeness of any material contained on this site or on any linked site. Further, please note that by submitting a question or comment you're agreeing to our terms of service, which are: you relinquish any subsequent rights of ownership to your material by submitting it on this site. Our lawyer says "Thanks for your cooperation."
© 2023 by Dave Taylor. "Ask Dave Taylor®" is a registered trademark of Intuitive Systems, LLC.
Privacy Policy - Terms and Conditions - Accessibility Policy