Are you a word game freak? If yes, how many times have you attempted to write a word game and then wondered how great it would have been if you had a magic “something” that would tell you:
- Whether a particular word exists or not – pass it the word and it will return true/ false depending on whether it is a correct English word or not?
- The set of valid words that match a given wild card pattern like “TRA*I?”
Even if you could write a DLL that does the above, where will you get the dictionary? What master file, will your magic DLL read to know which words exist?
Even if you get hold of a reasonably complete dictionary – is not going through all those words to match wild cards always a hit on performance? Say you are writing the classic “Complete the Word and Win” Game. Say the human player has entered his pick. Then your program is supposed to play an intelligent letter – how many times have you been frustrated while trying to find a fast way for your program to respond?
Here is a solution. This DLL, written in C++ (I used VC++.NET) does that.
This DLL uses 12 files named 1.TXT through 12.TXT – each containing all the English words of the same length – the length suggested by the file name. All the files are alphabetically sorted. The files are included in the code download link accompanying this article.
Where did I get it? I downloaded NETWORDZ, the popular scrabble game. It comes with a dictionary that is the exhaustive list of words used in the official 1998 SCRABBLE tournament. The game allows you to “export” the dictionary as a text file. I did that, and then wrote a quickie that broke it up in 12 neat parts – each containing all the words of equal length. Why 12? Because NETWORDZ does not give more than that. You are welcome to add 13.TXT, 14.TXT, etc – just re-build the DLL changing the macro “#define MAX_LENGTH 12” to the highest length you are using.
A DLL’s functionalities are its exported methods. So what better than have a look at that list?
Exported set of functions...
WORDLDR_API int wldrLoad( void );
WORDLDR_API bool wldrGetLoadingStatus( void );
WORDLDR_API int wldrGetWildCardMatches( char *, HGLOBAL * );
WORDLDR_API bool wldrExists( char * );
WORDLDR_API void wldrDumpDics( char * );
wldrLoad (): Your Game EXE must call wldrLoad () before calling any other function. This function will read the dictionary files and load the words in memory. This function will expect the dictionary files to be placed in the path that you mention in WORDLDR.INI, “Wordldr” section, “BetaPath” entry. The default path is “DICS” subfolder inside wherever the Game EXE and the DLL are residing. If you do not want to go into the hassles of creating an INI file, just create a DICS subfolder inside the folder where the game EXE is residing and copy the TXT dictionary files in it.
wldrLoad () will return immediately. It will not wait until all the words are loaded – because that will take a few seconds. Before you can call any other useful function, you must check whether loading is finished. That can be done using
wldrGetWildCardMatches () is obvious. This is the coolest part – you pass a wild card and you get a chunk of memory back containing the matches. You get
HGLOBAL back – all you have to do is:
- Lock as character array
- Parse the matching word out – I arranged for no delimiters, as that would unnecessarily increase the buffer size. Instead, each individual match ends in lower case; the rest is in upper case. For example, the match string can be:
which means there are 5 matches – bay, say, may, tray & clay.
- Unlock and free the memory (do not forget to free the memory !)
- Remember – before calling
wldrGetWildCardMatches(), do not allocate memory yourself. Just declare a
HGLOBAL and pass its address. The DLL will allocate the required memory. Then after using the match results, remember to free the chunk.
wldrExists () is obvious again – pass it a word (no wild cards) and it will simply say whether the passed word exists in the dictionary or not.
wldrDumpDics () lets you create back TXT files from the memory of the DLL – this functionality may be useful when you write a game, because typically you would not supply the dictionary files in plain TXT format where your users can easily see and cheat/ alter them. That part I leave to your imagination – how to handle that. You could write a quickie to encrypt the contents of these files, and then use the decrypting code in the DLL I am providing you, and after that, you could change the extension from TXT to fancy ones like DCT and then no one who does not know the encryption decryption algorithm will not be able to view your files. But then he could export the dictionary as text files just like NETWORDZ allows you. This exported function is provided just for that purpose.
A MFC sample dialog executable is provided, that loads and uses this DLL. Its GUI is very simple and self explanatory.
The performance of this DLL is lightning fast, due to the already sorted and lengthwise broken input, plus some optimizations done in the code.
An important point conveyed as a scare: In the sample MFC application, type in “*S” and try to see the matches. It will hang. Why? Not because the DLL is taking time. It returns, as I said, lightning fast. But in the application, I am showing the matches as a message box. Windows cannot create that message box when the string to be displayed is VERY LONG. It tries hard, and hangs.
The above point can be verified by debugging my code – a mere minute’s verification. This is an important lesson in the usage of message boxes.
The Code - Salient Features
When you peruse and use this code, this will teach you, if you do not already know:
- Usage of vectors and standard template library efficiently.
- File I/O using
- (In the MFC Application): How to display a dialog for selecting a folder without using bulky variations of
CFileDialog MFC class – in fact, this technique will work in non-MFC applications as well. The technique is not mine, I got it from somebody I do not remember, long ago from some website.
- (In the MFC Application): How to use a Win 32 DLL from a specialty library using application using explicit linking.
- (In both): Large chunks of memory handling using WIN 32 API-s.