专为文字游戏开发者打造的闪电般快速的 DLL,包含字典文件






3.08/5 (9投票s)
2004 年 8 月 8 日
6分钟阅读

56029

1503
此 DLL 和提供的测试 MFC 应用程序演示了如何高效地处理大量单词,实现闪电般的匹配速度——用于通配符匹配和存在性检查。此 DLL 是一体化的工具,正是文字游戏开发者所需要的——需要一个非常快速的字典功能。
引言
您是文字游戏爱好者吗?如果是,您尝试编写文字游戏时,有多少次曾想过,如果有一个神奇的“东西”能告诉您
- 某个特定单词是否存在——传递单词给它,它会根据该单词是否是正确的英语单词返回 true/false?
- 一组有效单词,匹配给定的通配符模式,如“TRA*I?”
即使您能编写一个执行上述操作的 DLL,您在哪里获取字典?您的神奇 DLL 将读取哪个主文件来知道哪些单词存在?
即使您获得了相对完整的字典——遍历所有单词以匹配通配符不总是会影响性能吗?假设您正在编写经典的“完成单词并获胜”游戏。假设人类玩家已经输入了他的选择。那么您的程序应该提供一个智能的字母——您有多少次在尝试为程序找到一个快速的响应方式时感到沮丧?
这里有一个解决方案。这个 DLL,用 C++ (我使用了 VC++.NET) 编写,可以做到这一点。
使用的字典
此 DLL 使用 12 个文件,名称从 1.TXT 到 12.TXT——每个文件包含相同长度的所有英语单词——长度由文件名指示。所有文件都按字母顺序排序。这些文件包含在本文附带的代码下载链接中。
我从哪里得到的?我下载了 NETWORDZ,一个流行的拼字游戏。它带有一个字典,是 1998 年 SCRABBLE 锦标赛官方使用的单词的详尽列表。该游戏允许您将字典“导出”为文本文件。我这样做了,然后编写了一个快速脚本,将其分解为 12 个整洁的部分——每个部分包含相同长度的所有单词。为什么是 12 个?因为 NETWORDZ 不提供更多。欢迎您添加 13.TXT、14.TXT 等——只需更改宏“#define MAX_LENGTH 12”为您使用的最高长度,然后重新构建 DLL。
支持的功能
DLL 的功能是其导出的方法。那么,有什么比看看那个列表更好的呢?
导出的函数集...
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 ()
:您的游戏 EXE 必须在调用任何其他函数之前调用 wldrLoad()。此函数将读取字典文件并将单词加载到内存中。此函数将期望字典文件位于您在 WORDLDR.INI 的“Wordldr”部分,“BetaPath”条目中指定的路径。默认路径是游戏 EXE 和 DLL 所在的任何位置内的“DICS”子文件夹。如果您不想费力创建 INI 文件,只需在游戏 EXE 所在的文件夹内创建一个 DICS 子文件夹,并将 TXT 字典文件复制到其中。wldrGetLoadingStatus ()
:wldrLoad ()
将立即返回。它不会等到所有单词都加载完毕——因为这需要几秒钟。在调用任何其他有用函数之前,您必须检查加载是否完成。可以使用wldrGetLoadingStatus()
完成此操作。wldrGetWildCardMatches ()
不言而喻。这是最酷的部分——您传递一个通配符,然后返回一块内存,其中包含匹配项。您将获得HGLOBAL
——您需要做的就是- 锁定为字符数组
- 读取
- 解析匹配的单词——我安排了没有分隔符,因为这会不必要地增加缓冲区大小。相反,每个单独的匹配项都以小写字母结尾;其余部分为大写。例如,匹配字符串可以是
“BAySAyMAyTRAyCLAy”,
这意味着有 5 个匹配项——bay、say、may、tray 和 clay。 - 解锁并释放内存(不要忘记释放内存!)
- 请记住——在调用
wldrGetWildCardMatches()
之前,请勿自己分配内存。只需声明一个HGLOBAL
并传递其地址。DLL 将分配所需的内存。然后在使用匹配结果后,请记住释放该块。
wldrExists ()
再次不言而喻——传递一个单词(无通配符),它将简单地告诉您传递的单词是否存在于字典中。wldrDumpDics ()
允许您从 DLL 的内存中创建 TXT 文件——此功能在您编写游戏时可能很有用,因为通常您不会以纯 TXT 格式提供字典文件,这样您的用户就可以轻松查看并作弊/修改它们。这部分留给您的想象——如何处理。您可以编写一个快速脚本来加密这些文件的内容,然后使用我提供的 DLL 中的解密代码,之后,您可以将扩展名从 TXT 更改为像 DCT 这样的花哨的名称,那么任何不知道加密解密算法的人都无法查看您的文件。但然后他可以像 NETWORDZ 那样导出字典为文本文件。此导出函数就是为此目的提供的。
示例 EXE
提供了一个 MFC 示例对话框可执行文件,该文件加载并使用此 DLL。其 GUI 非常简单且不言自明。
性能
由于输入已经排序并按长度分解,再加上代码中的一些优化,此 DLL 的性能非常快。
一个重要的警告点:在 MFC 示例应用程序中,键入“*S”并尝试查看匹配项。它会挂起。为什么?不是因为 DLL 需要时间。它返回,正如我所说,闪电般快速。但在应用程序中,我将匹配项显示为消息框。当要显示的字符串非常长时,Windows 无法创建该消息框。它会尽力尝试,然后挂起。
上述观点可以通过调试我的代码来验证——只需一分钟的验证。这是消息框使用中的一个重要教训。
代码 - 显著特点
当您浏览和使用此代码时,如果您还不知道,它将教您
- 高效使用向量和标准模板库。
- 使用
fstream
进行文件 I/O。 - (在 MFC 应用程序中):如何在不使用
CFileDialog
MFC 类的臃肿变体的情况下,显示一个用于选择文件夹的对话框——事实上,此技术也适用于非 MFC 应用程序。这项技术不是我的,我很久以前从某个网站上得到的,记不清是谁了。 - (在 MFC 应用程序中):如何通过显式链接,在使用了专业库的应用程序中使用 Win 32 DLL。
- (在两者中):使用 WIN 32 API 进行大块内存处理。