寻求关于使用 DAWG 实现文字游戏的建议

Posted

技术标签:

【中文标题】寻求关于使用 DAWG 实现文字游戏的建议【英文标题】:Seeking suggestions on a Word Game implementation using DAWG 【发布时间】:2020-08-13 12:58:21 【问题描述】:

我正在尝试使用以下规则实现一个小游戏: 给定一组随机字母(例如 10 个),我想从这些字母中找出所有可能的单词。我为此使用了标准字典。

字母可以多次使用,并不是所有的字母都必须使用,只要是4个字符以上的单词即可。我觉得这和解字谜很像,只是字母可以被多次使用。

例如 给出的字母:q r b d t e s 可能的词:床上用品、甜点等。

在寻找支持 O(1) 以检查字典中是否存在建议单词的数据结构时,我找到了这个 paper,随后还找到了一个有效的 Java DAWG 实现 here。

这就是我卡住的地方: 当尝试生成可以从这些字母中创建的可能单词列表时,我想知道使用 DAWG 实现是否遗漏了一些东西。我在这里看到了其他线程建议使用 Trie 并递归地遍历节点,但我希望我可以用 DAWG 做类似的事情。

我目前正在使用的实现是遍历字典中的所有单词,然后跳过任何包含不属于先前分配的字母的字母的单词。这可行,但速度很慢,要遍历字典中的所有单词 * 最坏情况下约 20 个字母。

for(String word : dawg.getAllStrings()) 
     boolean blacklist = false;
     for(int i = 0; i<nonLetters.length(); i++) 
         if(word.indexOf(nonLetters.charAt(i)) >= 0) 
             blacklist = true;
             break;
         
     

     if(!blacklist)
         possibleWordList.add(word);

我尝试实现递归单词匹配,但由于该实现不公开对其 Node 实现的访问权限,但我可以在本地进行更改。

如果无法访问节点,我可以使用 dawg.contains(letter),但由于需要多次使用字母,我想知道这是否真的有帮助。例如。我会从'A'开始,然后是'AA',......停在例如20 A。

使用 Trie 会更容易吗?找到匹配词仍然相当快,但更容易生成可能的词列表?

是否有其他 DAWG 库公开节点遍历或具有 ref 实现来生成所有可能的单词?

感谢任何帮助或指点!

【问题讨论】:

【参考方案1】:

我认为这是一个好方法。我在问题中引用的 DAWG 实现的 ModifiableDAWGSet 中添加了一个递归方法。

getWords 使用字符串前缀调用,将字符相加。 我首先实现了这个来生成 DAWG 中的所有单词,并与 ModifiableDAWGSet.getAllStrings() 的现有方法进行比较。 然后我添加了跳过不包含单词的单词,不包括可能字符列表中的字符。

private ArrayList<String> allMatchingWords = new ArrayList<String>();
private ArrayList<Character> possibleCharacters;

private void getWords(ModifiableDAWGNode originNode, String prefix) 
    NavigableMap<Character, ModifiableDAWGNode> transitionTreeMap = originNode.getOutgoingTransitions();

    for(Map.Entry<Character, ModifiableDAWGNode> transition : transitionTreeMap.entrySet())
    
        Character c = transition.getKey();
        if(!possibleCharacters.contains(c))
            continue;

        ModifiableDAWGNode n = transition.getValue();
        if(n.isAcceptNode()) //this is a word
        
            allMatchingWords.add(prefix + c);
        
        getWords(n, prefix + c);
    


public ArrayList<String> getAllMatchingWords(Character mustContain, ArrayList<Character> possibleCharacters)

    allMatchingWords.clear();
    this.mustContain = mustContain;
    this.possibleCharacters = possibleCharacters;
    getWords(sourceNode, "");
    return allMatchingWords;

【讨论】:

后来看到了。从上面的 Github 链接获取原始项目并将代码块添加到 ModifiableDAWGSet。【参考方案2】:

我有一个想法,我不确定,但希望对你有所帮助。 首先创建字典作为工作键,键将是单词包含的所有字母,按字母顺序排列。 例如:经典 -> acils ,字母 -> elrt。 与随机字符串类似。 你可以为你的程序准备这个。 并获得浏览具有 O (n) 复杂度的字典所需的一切

for(Word word : dawg.getAllStrings())
    if(randomString.contains(word.getKey()))
    possibleWordList.add(word);

【讨论】:

不错!谢谢,我会试试这个。在我发布后不久,我看到我正在使用的 DAWG 库也有一个带有键/值的 Map 实现,所以我会检查我是否可以使用它。 祝你成功 快速更新,不幸的是,性能方面的主要问题似乎是通过字典本身以任何方式确定匹配的单词。如果通过查找不匹配的字母或检查已排序的字符串是否与已排序的单词匹配来完成此操作,似乎并没有太大区别。我会再看看其他一些想法(Trie 似乎在这里更容易或尝试以某种方式遍历 DAWG)。现在再次感谢! 我在下面发布了一个答案,它通过 DAWG 的节点递归运行

以上是关于寻求关于使用 DAWG 实现文字游戏的建议的主要内容,如果未能解决你的问题,请参考以下文章

html5多人游戏建议

关于(半)在 Flash/PHP 游戏中获得高分的建议

寻求对内联命名空间的澄清

在创建 2D OpenGL-ES 2.0 游戏的基本、简单的方法中寻求帮助

寻求一个大学生互动小游戏,课堂上做的。

给游戏开发初学者的10条建议