如何实现“ 20个问题”算法?


16

自从童年,我已经不知道该怎么20Q电子游戏工作。您想到的是物体,事物或动物(例如土豆驴子)。然后,设备会问您一系列问题,例如:

  • 它比一条面包大吗?
  • 在户外找到吗?
  • 它用于娱乐吗?

对于每个问题,您都可以回答“ 是”,“ 不是”,“ 也许 ”或“ 未知”。我一直以为它可以与巨大的嵌套条件if语句(-statements)一起使用。但是,我认为这是一个不太可能的解释,因为它对程序员来说很复杂。

我将如何实施这样的系统?

Answers:


19

我不知道20Q具体是怎么做到的,但是关于如何实施20个问题的游戏,有很多信息。

解决此问题的方法有很多,但我将描述一种方法。这些游戏可以实现某种决策树。对于20Q这样的电子游戏,该树将被预先计算并且相当容易遍历。有一些使用学习决策树的方法,如果游戏无法猜出用户在问什么,则游戏可以在问题结束时接受新对象。

当问题是一系列的是或否答案时,您将得到一棵二叉树。每个节点都是一个问题,叶子就是答案。当问题的答案不确定或不确定时,可以合并子节点,并依次询问其问题,以进一步考虑可能的答案。

在此处输入图片说明

基本上这是一个过程:

  1. 从对象的完整列表开始。这些都可以以相同的可能性开始,或者可以按照在测试中选择对象的可能性来对它们进行排序。
  2. 从决策树中的第一个问题开始。将其推送到问题队列。
  3. 在队列顶部提出问题。
  4. 流程响应:
    1. 是/否答案会根据问题从每个答案中删除/添加预定的概率。
    2. “也许”答案删除/添加了预定数量“是”的一部分。
    3. “不知道”不会改变概率
  5. “未知”或“也许”响应将下一个节点的两个问题都推送到问题队列中。“是”或“否”响应仅将一个相应的“是/否”节点添加到问题队列中。
  6. 转到步骤3,直到没有问题或单个答案的可能性超出预定义的“确定性”阈值。
  7. 提供最可能的答案。

生成树可能是另一个问题的主题。但基本上,它选择的问题是尽可能将答案分开的问题。将最能平分问题的问题放在开头,这样可以最快地剔除最多数量的问题。


15

简单的答案是,掌上游戏20Q是由位于http://20Q.net的人工智能创建的。在20Q.net,您可以玩“二十个问题”游戏的不同版本,类似于玩具,不同之处在于该游戏可以从每个游戏中学习。手持玩具使用相同的神经网络算法。神经网络选择要提出的问题以及进行猜测。这种方法意味着,即使您回答的问题与AI所教的内容不同,AI也会经常正确猜测。另一个优点是,即使您在思考同一件事,游戏也会在每个游戏中提出不同的问题。

经典英语游戏(动物,蔬菜,矿物)的算法和神经网络由Robin Burgener于1988年创建。。。我。

感谢您的询问。


1
您好罗宾,欢迎来到该网站。谁比发明人自己回答这个问题更好。有趣的是,我们知道20Q到底有多复杂。感谢您对网站的贡献,也感谢您对人工智能的贡献。希望您偶尔访问该网站并回答AI问题:)。
MichaelHouse

1
呵呵,在发生这种情况时爱它xD。
jmacedo 2012年

6

我在Google上搜索了“ 20q代码”并找到了它:http : //mosaic.cnfolio.com/B142LCW2008A197

此版本仅适用于动物,但实际的20个问题可能具有类似的算法。

这是我链接的代码的快速概述:
程序中硬编码了几个不同的答案。然后将几个TRUE或FALSE属性分配给它们:

#define ANIMALS_LIST      "daddylonglegs bee penguin eagle giraffe octopus tiger elephant jellyfish bull \nparrot dolphin python crocodile cat leopard monkey zebra sheep rat \nowl spider frog polarbear snail tortoise rabbit salmon rhino fox"
#define MAMMALS                    "0 0 0 0 1 0 1 1 0 1 0 1 0 0 1 1 1 1 1 1 0 0 0 1 0 0 1 0 1 1"
#define FLYING_ANIMALS             "1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"
#define WATER_ANIMALS              "0 0 1 0 0 1 0 0 1 0 0 1 0 1 0 0 0 0 0 0 0 0 1 1 0 1 0 1 1 0"
#define BEAK                       "0 0 1 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0"
...

如您所见,蜜蜂不是哺乳动物,但它确实会飞,等等。

每个组都有一个数组:

int   mammals[ TOTAL_ANIMALS ] = { 0 };
int   flying_animals[ TOTAL_ANIMALS ] = { 0 };
int   water_animals[ TOTAL_ANIMALS ] = { 0 };
...

提出每个问题时:

  askUserQuestion( guesses, "\nQuestion %d: Is your animal a mammal? \n", mammals );

该程序将查看适当类别的定义,并根据TRUE或FALSE值以及输入的问题的是或否来跟踪您最想考虑的动物。

可以通过以下方式完成:

void askUserQuestion( int guessNumber, char* question, int* animalData );

0

它不是一个庞大的决策树,也不是一堆硬编码的if / else语句。发明人Robin Burgener 在2005年的专利申请中完全记录了他的算法。这很巧妙。


4
您可能不想给出其他答案,而是想对算法进行简短描述,而不仅仅是发布其链接。
Jari Komppa 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.