65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.08/5 (9投票s)

2004 年 8 月 8 日

6分钟阅读

viewsIcon

56029

downloadIcon

1503

此 DLL 和提供的测试 MFC 应用程序演示了如何高效地处理大量单词,实现闪电般的匹配速度——用于通配符匹配和存在性检查。此 DLL 是一体化的工具,正是文字游戏开发者所需要的——需要一个非常快速的字典功能。

Sample image

引言

您是文字游戏爱好者吗?如果是,您尝试编写文字游戏时,有多少次曾想过,如果有一个神奇的“东西”能告诉您

  1. 某个特定单词是否存在——传递单词给它,它会根据该单词是否是正确的英语单词返回 true/false?
  2. 一组有效单词,匹配给定的通配符模式,如“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 无法创建该消息框。它会尽力尝试,然后挂起。

上述观点可以通过调试我的代码来验证——只需一分钟的验证。这是消息框使用中的一个重要教训。

代码 - 显著特点

当您浏览和使用此代码时,如果您还不知道,它将教您

  1. 高效使用向量和标准模板库。
  2. 使用fstream进行文件 I/O。
  3. (在 MFC 应用程序中):如何在不使用CFileDialog MFC 类的臃肿变体的情况下,显示一个用于选择文件夹的对话框——事实上,此技术也适用于非 MFC 应用程序。这项技术不是我的,我很久以前从某个网站上得到的,记不清是谁了。
  4. (在 MFC 应用程序中):如何通过显式链接,在使用了专业库的应用程序中使用 Win 32 DLL。
  5. (在两者中):使用 WIN 32 API 进行大块内存处理。
© . All rights reserved.