2016-11-18 3 views
0

Я пишу программу в Прологе, которая представляет правила карточной игры. Тем не менее, я бегу в бесконечный цикл со следующим кодом.Бесконечная петля в Прологе. Как я могу это предотвратить?

succ(seven_of_hearts,eight_of_hearts). 
succ(eight_of_hearts,nine_of_hearts). 
succ(nine_of_hearts,ten_of_hearts). 
succ(ten_of_hearts,jack_of_hearts). 
succ(jack_of_hearts,queen_of_hearts). 
succ(queen_of_hearts,king_of_hearts). 
succ(king_of_hearts,ace_of_hearts). 
succ(X,Y) :- 
    succ(X,Z), 
    succ(Z,Y), 
    !. 

beats(X,Y) :- 
    succ(Y,X). 

В принципе, моя попытка с этим несколько строк, чтобы создать систему для определения, если одна карта бьет другого по Succ (или последовательность) отношений я установил. Таким образом, я запускаю запрос beats (X, Y), где X и Y и атомы соответствуют картам. Этот запрос завершается успешно, если это правда. Например, если я запрашиваю биты (jack_of_hearts, seven_of_hearts), он возвращает true и завершает работу.

Однако запрос входит в бесконечный цикл, если он является ложным. Например, когда я запрашиваю биты (seven_of_hearts, jack_of_hearts). Я проследил запрос и обнаружил, что из-за рекурсивного характера последнего succ-запроса запрос следует цепочке операторов succ вплоть до семи_очередников или вплоть до ace_of_hearts, а затем непрерывно пытается оценить succ (seven_of_hearts, X) или succ (ace_of_hearts, X) вместо того, чтобы возвращать false.

У меня есть два вопроса: используя эту текущую структуру, как я мог предотвратить это? Или, если это невозможно, что такое альтернативная структура, которую я мог бы использовать для достижения своей цели?

EDIT: Вот скриншот моего следа для одного из неисправных запросов:

Call: (267) beats(seven_of_hearts, jack_of_hearts) ? creep 
Call: (268) succ(jack_of_hearts, seven_of_hearts) ? creep 
    Call: (269) succ(jack_of_hearts, _G7104) ? creep 
    Exit: (269) succ(jack_of_hearts, queen_of_hearts) ? creep 
    Call: (269) succ(queen_of_hearts, seven_of_hearts) ? creep 
    Call: (270) succ(queen_of_hearts, _G7104) ? creep 
    Exit: (270) succ(queen_of_hearts, king_of_hearts) ? creep 
    Call: (270) succ(king_of_hearts, seven_of_hearts) ? creep 
    Call: (271) succ(king_of_hearts, _G7104) ? creep 
    Exit: (271) succ(king_of_hearts, ace_of_hearts) ? creep 
    Call: (271) succ(ace_of_hearts, seven_of_hearts) ? creep 
    Call: (272) false ? creep 
    Fail: (272) false ? creep 
    Redo: (271) succ(ace_of_hearts, seven_of_hearts) ? creep 
    Call: (272) succ(ace_of_hearts, _G7104) ? creep 
    Call: (273) false ? creep 
    Fail: (273) false ? creep 
    Redo: (272) succ(ace_of_hearts, _G7104) ? creep 
    Call: (273) succ(ace_of_hearts, _G7104) ? creep 
    Call: (274) false ? creep 
    Fail: (274) false ? creep 
    Redo: (273) succ(ace_of_hearts, _G7104) ? creep 
    Call: (274) succ(ace_of_hearts, _G7104) ? creep 
    Call: (275) false ? creep 

ответ

1

Вашего предикат, очевидно, продолжает называть себя: succ(X, Y) :- succ(Y, X), .... Простое решение - не использовать одно и то же имя для вашего предиката, поскольку вы делаете свои факты. Избавьтесь от своего предиката succ/2 в пользу:

successor(X, Y) :- succ(X, Y). 
successor(X, Y) :- succ(X, Z), succ(Z, Y). 

beats(X, Y) :- successor(Y, X). 
Смежные вопросы