Wordle - The Viral Game

I bet you probably have seen this funny symbol popping up here and there in your feeds:


This is the game built by Josh Wardle "Wordle", which you can play right here: Wordle - A daily word game (powerlanguage.co.uk). It is an extremely simple game to play: you have 6 chances to guess the secret 5-letters word, by entering one valid 5-letter English word at a time. For each guess, the "engine" will tell you which letters you got in the right order (green), or out of order (yellow) or which ones are not present in the secret word (gray). And that's it!

The implementation of such program can be done in less than 200 lines of code. Here is the approach:

1/ Find a text dictionary on the web, save it locally. The one that I have has ~62K words. Good enough to have fun, but you can have any. Moreover, any language...
2/ There will be one class called WordleGame which will control all the logic
3/ Lots of standard coding (initializing structures, reading data, selecting the secret word, etc.) but the most important one is the code to check the guesses. You want to make it in such a way that a/ it checks the correct letters first, b/ followed by the other two checks
4/ I searched up how to color code the output, lots of resources

It works quite well, in the console:





Cheers, ACC

using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;

namespace Wordle
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length != 3)
            {
                Console.WriteLine("Usage: Wordle.exe   ");
                return;
            }

            WordleGame wordleGame = new WordleGame(Int32.Parse(args[0]), Int32.Parse(args[1]), args[2]);

            for (; ; )
            {
                if (!wordleGame.Play() || wordleGame.CheckGuesses()) break;
            }
        }
    }

    public class WordleGame
    {
        private int wordLen = 0;
        private int attempts = 0;
        private int currentAttempt = 0;
        private string[] words = null;
        private string[] board = null;
        private string dictionary = "";
        private Hashtable htWords = null;
        private string theWord = "";
        public WordleGame(int wordLen, int attempts, string dictionary)
        {
            this.wordLen = wordLen;
            this.attempts = attempts;
            this.dictionary = dictionary;

            board = new string[attempts];
            htWords = new Hashtable();

            ReadWords();
            SelectTheWord();
        }

        private void ReadWords()
        {
            FileInfo fi = new FileInfo(dictionary);
            StreamReader sr = fi.OpenText();
            while (!sr.EndOfStream)
            {
                string line = sr.ReadLine().ToUpper().Trim();
                if (!String.IsNullOrEmpty(line) && line.Length == wordLen && !htWords.ContainsKey(line))
                {
                    htWords.Add(line, true);
                }
            }
            sr.Close();

            words = new string[htWords.Count];
            int index = 0;
            foreach (string word in htWords.Keys)
            {
                words[index++] = word;
            }
        }

        private void SelectTheWord()
        {
            Random rd = new Random();
            theWord = words[rd.Next(0, words.Length)];
        }

        public bool Play()
        {
            if (currentAttempt >= attempts)
            {
                Console.WriteLine("Game Over: You lost :(. Secret Word = {0}", theWord);
                return false;
            }

            currentAttempt++;
            for (; ; )
            {
                Console.WriteLine("What's your guess number #{0}?", currentAttempt);
                string line = Console.ReadLine().ToUpper().Trim();
                if (line.Length != wordLen || !htWords.ContainsKey(line))
                {
                    Console.WriteLine("Guess must be a valid {0}-length English word!", wordLen);
                }
                else
                {
                    board[currentAttempt - 1] = line;
                    break;
                }
            }

            return true;
        }

        public bool CheckGuesses()
        {
            Hashtable setOfChars = new Hashtable();
            foreach (char c in theWord)
            {
                if (!setOfChars.ContainsKey(c)) setOfChars.Add(c, 0);
                setOfChars[c] = (int)setOfChars[c] + 1;
            }

            Console.WriteLine();
            Console.WriteLine("BOARD:");
            for (int i = 0; i < currentAttempt; i++)
            {
                Hashtable tempSetOfChars = (Hashtable)setOfChars.Clone();
                for (int j = 0; j < wordLen; j++)
                {
                    if (board[i][j] == theWord[j])
                    {
                        tempSetOfChars[board[i][j]] = (int)tempSetOfChars[board[i][j]] - 1;
                        if ((int)tempSetOfChars[board[i][j]] == 0) tempSetOfChars.Remove(board[i][j]);
                    }
                }

                int matches = 0;
                for (int j = 0; j < wordLen; j++)
                {
                    if (theWord[j] == board[i][j])
                    {
                        WriteLineColored((ConsoleColor.DarkGreen, board[i][j].ToString()));
                        matches++;
                    }
                    else if (!tempSetOfChars.ContainsKey(board[i][j]))
                    {
                        WriteLineColored((ConsoleColor.DarkGray, board[i][j].ToString()));
                    }
                    else
                    {
                        WriteLineColored((ConsoleColor.DarkYellow, board[i][j].ToString()));
                        tempSetOfChars[board[i][j]] = (int)tempSetOfChars[board[i][j]] - 1;
                        if ((int)tempSetOfChars[board[i][j]] == 0) tempSetOfChars.Remove(board[i][j]);
                    }
                }
                Console.WriteLine();
                if (matches == wordLen)
                {
                    Console.WriteLine();
                    Console.WriteLine("You Won!");
                    return true;
                }
            }
            Console.WriteLine();

            return false;
        }

        private void WriteLineColored(params (ConsoleColor color, string value)[] values)
        {
            foreach (var value in values)
            {
                Console.ForegroundColor = value.color;
                Console.Write(value.value);
            }
            Console.ResetColor();
        }
    }
}

Comments

Post a Comment

Popular posts from this blog

Changing the root of a binary tree

ProjectEuler Problem 719 (some hints, but no spoilers)

The Power Sum, a recursive problem by HackerRank