2016-11-18 24 views
0

私はカードゲームのルールを表すプログラムをPrologで書いています。しかし、私は次のコードで無限ループに陥っています。Prologの無限ループ。これをどうやって防ぐのですか?

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(または連続)に応じて関係を打つかどうかを決定するためのシステムを設定することです。だから私が実行しているクエリは、XとYと原子がカードに対応する、ビート(X、Y)です。この問合せが真であれば、この問合せは正常終了します。たとえば、Iクエリがビート(jack_of_hearts、seven_of_hearts)の場合、trueを返して終了します。

ただし、falseの場合、クエリは無限ループに入ります。たとえば、私が質問するとき(seven_of_hearts、jack_of_hearts)。私はクエリをトレースし、最後のsuccステートメントの再帰的性質のため、クエリは、succステートメントのチェーンをたどってseven_of_heartsまで、またはace_of_heartsまでずっと続けて、次にsuccを評価しようとします(seven_of_hearts、X)またはsucc(ace_of_hearts、X)を返します。

私は2つの質問があります:この現在の構造を使用して、どうすればこの問題を防ぐことができますか?それが不可能な場合、私の目標を達成するために使用できる代替構造は何ですか?

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). 
関連する問題