SQLServerCentral Article

Playing popular game of Wordle using T-SQL

,

A current frenzy surrounding the game of Wordle has swept the community. I have been playing this game as well and it is addictive. Therefore, I have decided to spice up this game with Transact SQL. With this script, you can now  play this game on Microsoft SQL Server, using your favourite editor - SSMS, ADS, VS Code, and others.

the game outlook and concept is based on the original outlook:

wordle_gameplay.png
Gameplay with original Wordle

 

About the Game

Wordle  is a word guessing game, and your task is simple. You have to guess the searched (or secret) word in six or less tries. The secret word must be taken from the maintained and provided list of words (based on the official dictionary). And this applies also to all the tries.  When you  pass an incorrect word (or word that does not exist on  the dictionary list), you will be informed and this does not count as a try.

The game ends when you find the secret words or when you run out of tries. Along the way, the letters are coloured based on your previous tries. This help you to tinker and play better. Colour coding is straightforward:

  • a correctly guessed letter and it's position in the word is coloured green
  • a correctly guessed letter but on a wrong position is coloured yellow
  • an incorrect letter (a letter that is not part of the word) is coloured gray.

A letter that is correctly guessed (position and letter) turns green, a letter that is correct but placed in wrong wrong position turns yellow and an incorrect letter is coloured as gray.

Getting ready

Before we can start playing the game using T-SQL, there are some prerequisites.

List of words

In order to play Wordle using T-SQL, you will need to import the words. This list of words will serve not only as a corpus of words, but will also set the boundaries. If you import only 20 words, this will mean that you will be limiting yourself to 20 words. In order to get started, I have a curated list of words prepared. You can download the list of words for here. For the English download, use english.txt. In this Github repository, you also have three other languages available.

Create an empty table and import the list of words for the English words.

CREATE TABLE dbo.Words
( ID INT IDENTITY(1,1)
, word NVARCHAR(10) NOT NULL
, lang CHAR(3) NOT NULL
);
-- Insert English words
CREATE TABLE dbo.TempWords
( 
    word NVARCHAR(10)
);
BULK INSERT dbo.TempWords
FROM 'D:tsqlwordlelanguagesenglish.txt'
WITH (FIRSTROW = 1
    ,ROWTERMINATOR='n');
INSERT INTO dbo.Words
SELECT 
     word
    ,'EN' as lang
 FROM TempWords;
 
DROP TABLE IF EXISTS dbo.TempWords;

When you have words for selected language in the SQL Server table, you will also need the procedure for gameplay.

Graphics

Running the game in SQL Server Management Studio will have a slight graphical drawback. The results can not be graphically presented with colours. Therefore, I have created a simple transformation of the colours.

The transformation is the following:

  • when a letter (e.g.: C) is correct and the position of the letter is correct, the letter is enclosed in [[ C ]]  (denoting  green)
  • when a letter is correct, but the position is wrong, the letter is represented as {{ C }} (denoting yellow)
  • when a letter is incorrect, it is represented as ' C '.

I find this graphical presentation easy to read and quick to remember. You can always change this transformation based on your liking.

Keyboard View

The view of the keyboard will give you additional information about the gameplay. When you are playing the game, the keyboard view will instantly give you an overview of letter selection. If the letter (or the key) is correct and on the correct position, the key will turn [[ C ]]  (denoting  green). The correct letter in the wrong position will be represented as {{ C }} (denoting yellow) and if the key is incorrect, it will be replaced by the hash (#) sign.

DROP TABLE IF EXISTS dbo.Keyboard;
GO
CREATE TABLE dbo.Keyboard
(
    ID INT IDENTITY(1,1)
    ,Krow INT NOT NULL
    ,Kkey NVARCHAR(100) NOT NULL
    ,lang CHAR(3) NOT NULL
)
INSERT INTO dbo.Keyboard
SELECT 1, 'Q; W; E; R; T; Y; U; I; O; P', 'EN' UNION ALL
SELECT 2, 'A; S; D; F; G; H; J; K; L', 'EN' UNION ALL
SELECT 3, 'Z; X; C; V; B; N; M', 'EN' UNION ALL
SELECT 1, 'Q; W; E; R; T; Z; U; I; O; P; Š; Đ', 'SI' UNION ALL
SELECT 2, 'A; S; D; F; G; H; J; K; L; Č; Ć; Ž', 'SI' UNION ALL
SELECT 3, 'Y; X; C; V; B; N; M', 'SI'  UNION ALL
SELECT 1, 'Q; W; E; R; T; Z; U; I; O; P; Ü', 'DE' UNION ALL
SELECT 2, 'A; S; D; F; G; H; J; K; L; Ö; Ä', 'DE' UNION ALL
SELECT 3, 'Y; X; C; V; B; N; M', 'DE'   
SELECT 1, 'Q; W; E; R; T; Z; U; I; O; P', 'IT' UNION ALL
SELECT 2, 'A; S; D; F; G; H; J; K; L', 'IT' UNION ALL
SELECT 3, 'Y; X; C; V; B; N; M', 'IT'

After each try, you will get the keyword view displayed with updated correct, incorrect and unused keys.

Main Game Procedure

The game is played with a single procedure. During the gameplay, the procedure creates two tables to store intermediate results. The procedure also uses the CROSS APPLY, STRING_SPLIT and STRING_AGG clauses and functions to operate and manipulate strings and letters.

The code is shown here:

CREATE OR ALTER PROCEDURE dbo.WordGuess
/*
Script       :  Game.sql
Procedure	 : dbo.WordGuess
Purpose      : T-SQL stored procedure for playing Wordle in T-SQL
Date Created : 10 January 2022
Description  : Popular word game called Wordle in T-SQL 
			   for Microsoft SQL Server 2017+
			   Based on https://powerlanguage.co.uk/wordle/ 
Author		 : Tomaz Kastrun (Twitter: @tomaz_tsql)
				  			 (Github: github.comtomaztk)
Parameters   : Two input parameters
					 @lang -- defines language, thesaurus and keyboard
					 @guess -- 5-letter word for guessing
Output        :
				Result of the game:
					Table: dbo.TempTable - game play and tries		
					Table: dbo.TempKeyboard - coloured used keys 
Usage:
	EXEC dbo.WordGuess 
		 @lang='EN'
		,@guess = 'right' 
*/
     @lang char(3)
    ,@guess NVARCHAR(10)
AS 
BEGIN
	
	
	-- check if the word exists / is legitt :)
	IF (SELECT COUNT(*) as Computed  FROM  [dbo].[Words] where word = @guess AND lang = @lang) = 0
	BEGIN 
		SELECT 'Wrong word!' AS [Message from the Game]
		RETURN
	END
	
	
	-- create table and generate secret
	IF (OBJECT_ID(N'dbo.tempTable'))  IS  NULL
	BEGIN 
		 -- DROP TABLE IF EXISTS dbo.tempTable
	     CREATE TABLE dbo.tempTable (id int identity(0,1), secrets NVARCHAR(10), nof_guess INT, guess_word NVARCHAR(100), valid INT NULL)
		 DECLARE @secret NVARCHAR(10) = (SELECT top 1 word from dbo.words WHERE lang= @lang ORDER By newid())
            INSERT INTO dbo.tempTable (secrets, nof_guess,guess_word, valid)
            SELECT 
			 @secret AS secrets
            ,0 AS nof_guess
            ,null AS guess_word
            ,1 AS valid -- as valid word
	END
	-- create table for temp keyboard
	IF (OBJECT_ID(N'dbo.tempKeyboard')) IS NULL
	BEGIN
		CREATE TABLE dbo.tempKeyboard (Krow INT, Kkey NVARCHAR(100))
		INSERT INTO dbo.tempKeyboard (Krow, Kkey)
		SELECT
			--id
			 Krow
			,Kkey
		FROM dbo.Keyboard
		WHERE
			lang = @lang
	END
    
	-- guessing part
    DECLARE @nof_guess INT = (SELECT MAX(nof_guess) FROM tempTable)
    IF @nof_guess < 6
    BEGIN
	/*
	ADD part for determing colours
	*/
	DROP TABLE IF EXISTS #tt
	DECLARE @guess_sol NVARCHAR(100) = ''
	declare @guess_sol2 nvarchar(100) = ''
	SET @secret = (SELECT secrets FROM dbo.TempTable WHERE nof_guess = 0)
			;WITH sec AS (
				SELECT
					 SUBSTRING(a.b, val.number+1, 1) AS letter 
					,ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS RN
				FROM 
					(SELECT @secret AS b) AS a
				JOIN [master]..spt_values AS val 
				ON val.number < LEN(a.b)
				WHERE 
					[type] = 'P'
			
			), gu AS (
				SELECT 
					 substring(a.b, val.number+1, 1) AS letter 
					,row_number() over (order by (select 1)) as RN
				FROM 
					(SELECT @guess AS b) AS a
				JOIN [master]..spt_values AS val 
				ON val.number < len(a.b)
				WHERE  [type] = 'P'
			) ,green AS (
				SELECT
					 gu.letter as gul
					,sec.letter as secl
				    ,gu.rn as gurn
				 FROM gu 
				 JOIN sec
				 ON gu.rn = sec.rn
				 AND gu.letter = sec.letter
			
			), yellof AS (
				select distinct
				g.letter as gul
				,g.rn as gurn
				from gu as g
				cross join sec
				where   
					g.letter = sec.letter
				AND g.rn <> sec.rn
				AND NOT EXISTS (Select * from green  as gg 
								where gg.gul = g.letter 
								  and gg.gurn = g.rn)
			), gray AS (
				SELECT
					 letter as gul
					,rn as gurn
				FROM gu
				WHERE
						NOT EXISTS (SELECT * FROM green  WHERE gul = gu.letter)
					AND NOT EXISTS (SELECT * FROM yellof WHERE gul = gu.letter)
			
			) ,Aaa AS (
				SELECT gul AS letter, gurn AS pos  , 'green' as col FROM green  UNION ALL
				SELECT gul AS letter, gurn AS pos , 'yellow' as col FROM yellof UNION 
				SELECT gul AS letter, gurn AS pos , 'Gray'   as col FROM gray
			
			) , final AS (
			SELECT 
				 a.letter
				,a.col
				,CASE 
					WHEN a.col = 'Gray'  THEN ' '' ' +UPPER(a.letter)+ ' '' '
					WHEN a.col ='yellow' THEN ' {{ ' +UPPER(a.letter)+ ' }} '
					WHEN a.col ='green'  THEN ' [[ ' +UPPER(a.letter)+ ' ]] ' END as reco
				,a.pos
				,g.letter as guess_letter
			
				
			FROM aaa as a
			LEFT JOIN gu as g
			ON g.rn = a.pos
			)
		SELECT * 
		INTO #tt
		From final

		SELECT @guess_sol = COALESCE(@guess_sol + ' ', '') + reco
		FROM #tt
		ORDER BY pos ASC

		SELECT @guess_sol2 = COALESCE(@guess_sol2 + ' ,', '') + reco
		FROM #tt
		ORDER BY pos ASC
	-- store results
        INSERT INTO dbo.TempTable
        SELECT 
            (SELECT TOP 1 secrets  FROM dbo.tempTable) as Secrets 
            ,@nof_guess + 1 aS nof_guess
            ,@guess_sol 
			,1 as Valid;
        SELECT 
			 nof_guess AS [Try Number:]
			,guess_word AS [Guessed Word:]
		FROM TempTable
		WHERE
			ID > 0;
 
 	/*
	ADD part for keyboard denotation
	*/
		DROP TABLE IF EXISTS #tt2
		SELECT 
			 kkey
			,krow
			,ROW_NUMBER() OVER (ORDER BY krow) AS rn
			,TRIM([value]) AS [value]
		into #tt2	
		from dbo.tempkeyboard
		CROSS APPLY string_split(kkey, ';')

		DROP TABLE IF EXISTS #aa
		SELECT 
			[value] 
			,TRIM(REPLACE(cast(cast(cast(cast(cast(cast(cast(REPLACE(REPLACE(REPLACE(REPLACE([value] as nvarchar(max)) as nvarchar(max)) as nvarchar(max)) as nvarchar(max)) as nvarchar(max)) as nvarchar(max)) as nvarchar(max)),cast(cast(cast(cast(cast(cast(cast( ' [[ ' as nvarchar(max)) as nvarchar(max)) as nvarchar(max)) as nvarchar(max)) as nvarchar(max)) as nvarchar(max)) as nvarchar(max)),cast(cast(cast(cast(cast(cast(cast('' as nvarchar(max as nvarchar(max as nvarchar(max as nvarchar(max as nvarchar(max as nvarchar(max as nvarchar(max))))))))))))))), ' ]] ',''),' {{ ',''),' }} ',''), ' '' ','')) AS kak
		INTO #aa
		FROM STRING_SPLIT(@guess_sol2, ',')
		WHERE
			[value] <> ''
		-- updating values
		UPDATE t
		SET 
			t.[value] = a.[value]
		FROM #tt2 AS t
		JOIN #aa AS a
		ON a.kak = t.[value]
		UPDATE #tt2
		SET 
			[value] = '#'
		WHERE
			[value] LIKE ' '''
		-- Creating update keyboard outlook
		DROP TABLE IF EXISTS dbo.tempKeyboard
		SELECT 
		  krow
		 ,STRING_AGG([value], '; ') AS kkey
		INTO dbo.tempKeyboard
		FROM #tt2
		GROUP BY krow
		ORDER BY krow asc
		-- Output the keyboard
		SELECT * FROM  dbo.tempKeyboard
    END
	DECLARE @nof_guess2 INT = (SELECT MAX(nof_guess) FROM dbo.tempTable)
	IF @nof_guess2 = 6
	BEGIN
		SELECT 'End' AS [Message from the Game]
		DROP TABLE IF EXISTS dbo.TempTable;
		DROP TABLE IF EXISTS dbo.tempKeyboard;
	END

	IF (UPPER(@secret) = (@guess))
	BEGIN
		SELECT 'Yees, Won!' AS [Message from the Game]
		DROP TABLE IF EXISTS dbo.TempTable;
		DROP TABLE IF EXISTS dbo.tempKeyboard;
	END
END;
GO

Playing the Game

You will run the game with executing the procedure with two parameters, the language and the guess.

EXEC dbo.WordGuess 
	 @lang='EN'
	,@guess = 'table'

The language parameter defines the list of words and the guess parameter takes your guess. After each try, you will get the results of all previous results and the keyboard view.

When you guess the correct word, the procedure will let you know that you won.

If your guess is not on the list of words, the procedure will notify you about the false word, and the false try will not count as a try.

Continuing the Wordle-mania

Using transact SQL and playing this word game is not only relaxing, but also gives you the ability to expand the possibilities of T-SQL.  And now you can play a simple wordle game during the working hours, without your supervisor knowing, you are playing the game.

Enjoy the Wordle T-SQL game.

Rate

You rated this post out of 5. Change rating

Share

Share

Rate

You rated this post out of 5. Change rating