Собственно, буквально за несколько дней до того как Белокрылов
привел нам пример экспертной системы, которая угадывает слово
по принципу ответа да/нет, мой начальник на работе показал
мне очень похожую прогу, написанную им самим и предложенную как
альтернатива зачёту в одной из групп ИТМО. 
Прога называется Cat 
Принцип работы, как и реализация, очень прост:
Программа при старте спрашивает "Это кот?"
Если нет, то идет по вершинам дерева свойств предметов.
Если слово отгадано, то игра заканчивается,
если нет, то прости ввести само слово и его свойство.
Все изменения в дереве сохраняются.
Конечно это упрощенный вариант того о чем говорил Белокрылов,
но все же позволяет понять принцип её работы!
Exe-шник с небольшим деревом ответов
Инструкции:
набирать в консоли можно только буквами латиницей
положительный ответ "Y", отрицательный "N"
А вот исходный код:
(всего то ~200 строк кода
)
#define EE_MARK "ee"
struct TREE_ITEM
{
char *question;
TREE_ITEM *down, *next;
};
TREE_ITEM*
AllocateNode(const char *question)
{
TREE_ITEM *pItem = (TREE_ITEM*)malloc(sizeof(TREE_ITEM));
if (!pItem)
return NULL;
pItem->down = pItem->next = NULL;
pItem->question = strdup(question);
return pItem;
}
void
FreeNode(TREE_ITEM *pNode)
{
if (!pNode)
return;
free(pNode->question);
free(pNode);
}
void FreeTree(TREE_ITEM *pTree)
{
if (!pTree)
return;
FreeTree(pTree->next);
FreeTree(pTree->down);
FreeNode(pTree);
}
void SaveSubTree(FILE *fp, TREE_ITEM *pTree, INT n = 0)
{
char *s = (char *)calloc(n + 1, 1);
memset(s, ' ', n);
if (!pTree)
{
fprintf(fp, "%s%s\n", s, EE_MARK);
free(s);
return;
}
fprintf(fp, "%s%s\n", s, pTree->question);
SaveSubTree(fp, pTree->next, n + 1);
SaveSubTree(fp, pTree->down, n + 1);
free(s);
}
void PrintTree(TREE_ITEM *pTree)
{
puts("---------------------------------");
SaveSubTree(stdout, pTree);
puts("---------------------------------");
}
void SaveTree(TREE_ITEM *pTree)
{
CopyFile("tree", "tree.old", FALSE);
FILE *fp = fopen("tree", "wt");
if (!fp)
return;
SaveSubTree(fp, pTree);
fclose(fp);
}
char *SkipSpaces(char *p)
{
while (*p && (*p == ' '))
p++;
return p;
}
TREE_ITEM* LoadSubTree(FILE *fp)
{
char str[1024];
fgets(str, sizeof(str), fp);
if (str[strlen(str) - 1] == '\n')
str[strlen(str) - 1] = 0;
char *p = SkipSpaces(str);
if (!strcmp(p, EE_MARK))
return NULL;
TREE_ITEM *pRet = AllocateNode(p);
pRet->next = LoadSubTree(fp);
pRet->down = LoadSubTree(fp);
return pRet;
}
TREE_ITEM *LoadTree()
{
FILE *fp = fopen("tree", "rt");
if (!fp)
return NULL;
TREE_ITEM *pRet = LoadSubTree(fp);
fclose(fp);
return pRet;
}
bool
YesNo()
{
while (TRUE)
{
char c = toupper(getchar());
getchar();
if (c == 'Y')
return true;
else if (c == 'N')
return false;
}
}
void Run(TREE_ITEM *pRoot)
{
TREE_ITEM *pCur = pRoot, *pPrev;
while (pCur)
{
printf("Eto %s? ", pCur->question);
if (YesNo())
{
if (pCur->down)
Run(pCur->down);
else
puts("Uraaaaaaaaaa!!!");
return;
}
else
{
pPrev = pCur;
pCur = pCur->next;
}
}
puts("Chto eto?");
char name[1024];
gets(name);
char dif[1024];
printf("Chem otlichaetsia ot %s?\n", pPrev->question);
gets(dif);
pPrev->next = AllocateNode(dif);
pPrev->next->down = AllocateNode(name);
}
int _tmain(int argc, _TCHAR* argv[])
{
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
TREE_ITEM *pRoot = LoadTree();
if (!pRoot)
{
pRoot = AllocateNode("Kot");
if (!pRoot)
return -1;
}
PrintTree(pRoot);
Run(pRoot);
PrintTree(pRoot);
SaveTree(pRoot);
FreeTree(pRoot);
puts("Press ENTER to exit");
getchar();
return 0;
}