Why Most Wordle Clones are Wrong!
Tags: javascript, beginners, webdev, programming
Published: 2022-02-07 19:27:09

Wordle, the new online viral game everyone's talking about, at first glance, seems to be not such a difficult feat for an average programmer.

In this post, I will be talking about a mistake that even experienced developers make when coding Wordle and how it can be fixed.

The rules of Wordle are straightforward:

* Guess the secret word wihin 6 tries.
* Each guess must be a valid 5-letter word.
* After each guess, the color of the tiles will change to show how close your guess was to the word:
    GREEN: The letter is in the word and in the correct spot.
    YELLOW: The letter is in the word but in the wrong spot.
    GRAY: The letter is not in the word in any spot.

So why are most hobbyists and even content creators such as [Web Dev Simplified](https://www.youtube.com/watch?v=Wak7iN4JZzU) and [Burke Holland from Visual Studio Code](https://www.youtube.com/watch?v=eXow_OxrAeE) getting it wrong?\*

## The mistake

The common mistake that nearly all Wordle clone creators make is by oversimplifying the algorithm by misunderstanding an ambiguity in the rules.

During my attempt at creating a Wordle clone, I admit to have fallen for this trap initially myself until I realized that for some inputs, the most obvious solution is not a correct one.

Consider the following code snippet used for determining which color should be assigned to each letter in the guess. Can you spot the mistake?

```js
function colorRow(answer, guess) {
    const colors = [];
    for (let i = 0; i < guess.length; i++) {
        if (guess[i] === answer[i]) {
            colors.push("GREEN");
        } else if (answer.includes(guess[i])) {
            colors.push("YELLOW");
        } else {
            colors.push("GRAY")
        }
    }
    return colors;
}
```

The mistake here is that if the guess contains multiple of the same letter, they would all be marked with at least yellow, even if there was only one of them in the answer!

### Example:

Consider the correct answer is `"THOSE"`.

If a player were to guess the word `"GEESE"`, the algorithm above would produce the result:

!['GRAY', 'YELLOW', 'YELLOW', 'GREEN', 'GREEN'](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q7jyqngllovjhw1tr4jt.png)
```js
['GRAY', 'YELLOW', 'YELLOW', 'GREEN', 'GREEN']
```

This would imply that the correct answer has two E's in the wrong location and one E in the correct location (a total of three E's).

A correct algorithm, however, working the same as Wordle itself, would produce the result:

!['GRAY', 'GRAY', 'GRAY', 'GREEN', 'GREEN'](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q2hmn7w9chgso63tectj.png) 
```js
['GRAY', 'GRAY', 'GRAY', 'GREEN', 'GREEN']
```

### As another example:

If the answer is `"DREAD"`, and `"ADDED"` is guessed, the result produced would be:

!['YELLOW', 'YELLOW', 'YELLOW', 'YELLOW', 'GREEN'](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b8qnb698dwvt8ys7tc83.png) 
```js
['YELLOW', 'YELLOW', 'YELLOW', 'YELLOW', 'GREEN']
```

This implies no letters are missing, but in fact, one of the D's is wrong and the R is missing. Only *one* of the wrongly placed D's should be marked Yellow.

A correct algorithm would produce the result:

!['YELLOW', 'YELLOW', 'GRAY', 'YELLOW', 'GREEN'](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h7rwe7j9orb4u6azptpa.png) 
```js
['YELLOW', 'YELLOW', 'GRAY', 'YELLOW', 'GREEN']
```

Feel free to take a moment to challenge yourself to come up with a correct algorithm before continuing to the last section of the article.

## The solution

A single for-loop is not enough as the colors of the tiles will change depending on the colors of other tiles in the same row.

We always want correct letters in the correct spot to be green, so we will score those first and remove them from the answer so they cannot be scored again later as a yellow letter.

Next, we want to score the correct letters in the wrong spot as yellow. Again we need to remove them from the answer so they cannot be scored again later by an additional yellow letter (as in the case of `"DREAD"` and `"ADDED"`).

Finally, all the remaining letters that are not in the answer are gray.

Here is an example of an algorithm that has been corrected for this mistake (there is more than one possible solution):

```js
function colorRow(answer, guess) {
    // initialize all colors to GRAY
    const colors = Array(guess.length).fill("GRAY");
    // loop through guess and mark green if fully correct
    for (let i = 0; i < guess.length; i++) {
        if (guess[i] === answer[i]) {
            colors[i] = "GREEN";
            // remove letter from answer, so it's not scored again
            answer = answer.replace(guess[i], " ");
        }
    }
    // loop through guess and mark yellow if partially correct
    for (let i = 0; i < guess.length; i++) {
        if (colors[i] !== "GREEN" && answer.includes(guess[i])) {
            colors[i] = "YELLOW";
            // remove letter from answer, so it's not scored again
            answer = answer.replace(guess[i], " ");
        }
    }
    return colors;
}
```

In this algorithm, the *first occurrence* of a letter in the answer is replaced with a *space*, so that it still takes up an index in the answer string, but it is no longer able to be scored again.

After the first line, we will have an array containing "GRAY" for each letter in the guess.

Once we have completed the first loop, we will have an array containing "GREEN" for each letter in the guess that is fully correct, and "GRAY" for all other letters. The answer will now no longer have letters that have been scored as green.

After the second loop, we will have an array still containing the greens, but now also including all "YELLOW" tiles that have been scored. All letters that do not appear in the word will remain as "GRAY". `colors[i] !== "GREEN"` must be checked in the second loop since we don't want to change letters that were scored as "GREEN" into "YELLOW".

Finally, we will have an array containing all the colors for each letter in the guess and we can return it!

## Conclusion

I hope you found this tutorial useful. Maybe it will help you to make or fix a Wordle Clone of your own!

**\*I do not mean in any way to say that any creators or their tutorials are bad in any way. The creators who made these tutorials have great educational content and I do not think one should think less of them due to a commonly made error. Always remember to _be nice_ when approaching creators in comments.**

If you're interested in learning how to make a Discord Bot in Python to play Wordle, check out [my tutorial](https://www.youtube.com/watch?v=0p_eQGKFY3I)!

\- Jonah Lawrence

🐙 GitHub: [DenverCoder1](https://github.com/DenverCoder1)

📺 YouTube: [Jonah Lawrence - Dev Pro Tips](https://youtube.com/c/DevProTips)

🐦 Twitter: [@DenverCoder1](https://twitter.com/DenverCoder1)

----

*Update (2022-03-01): Anonymous#9495 pointed out on Discord that there was a slight error in the code (checking `guess[i] !== answer[i]` in the second loop instead of `colors[i] !== "GREEN"`). The code did not work in some cases such as where the answer is "MAXIM" and "MAMMA" is guessed, since the `answer` string has been changed to have spaces, so the guess and answer will no longer match.*