2014-11-22 34 views
2

我對Prolog非常陌生,我試圖編寫一個簡單的方法來確定一個棋盤上的騎士是否可以跳到另一個方塊,或者輸出所有的一個騎士可以跳到正方形的方格。對於這個方法,假設第一個參數必須總是被實例化。它工作正常,給定兩個參數,但我不知道爲什麼它不會輸出只給定一個。Prolog - 參數沒有被充分實例化 - Knight/chessboard

% validSquare/2 
% validSquare(X1/Y1, X2/Y2) iff the coordinate is a valid position on an 8x8 chessboard. 
validSquare(X1/Y1, X2/Y2) :- 
    X1 >= 1, X1 =< 8, 
    Y1 >= 1, Y1 =< 8, 
    X2 >= 1, X2 =< 8, 
    Y2 >= 1, Y2 =< 8. 


% jump/2 
% jump(Square1, Square2) iff a knight could jump to the coordinate 
% Square1/Square2 on a chessboard. 
jump(X1/Y1, X2/Y2) :- 
    validSquare(X1/Y1, X2/Y2), 
    X2 is X1 + 1, 
    Y2 is Y1 + 2. 
jump(X1/Y1, X2/Y2) :- 
    validSquare(X1/Y1, X2/Y2), 
    X2 is X1 + 2, 
    Y2 is Y1 + 1. 
jump(X1/Y1, X2/Y2) :- 
    validSquare(X1/Y1, X2/Y2), 
    X2 is X1 + 1, 
    Y2 is Y1 - 2. 
jump(X1/Y1, X2/Y2) :- 
    validSquare(X1/Y1, X2/Y2), 
    X2 is X1 + 2, 
    Y2 is Y1 - 1. 
jump(X1/Y1, X2/Y2) :- 
    validSquare(X1/Y1, X2/Y2), 
    X2 is X1 - 1, 
    Y2 is Y1 - 2. 
jump(X1/Y1, X2/Y2) :- 
    validSquare(X1/Y1, X2/Y2), 
    X2 is X1 - 2, 
    Y2 is Y1 - 1. 
jump(X1/Y1, X2/Y2) :- 
    validSquare(X1/Y1, X2/Y2), 
    X2 is X1 - 1, 
    Y2 is Y1 + 2. 
jump(X1/Y1, X2/Y2) :- 
    validSquare(X1/Y1, X2/Y2), 
    X2 is X1 - 2, 
    Y2 is Y1 + 1. 

就像我說的,我對Prolog非常陌生,所以我不確定如何格式化查詢。這個查詢是錯誤的。

?- jump(1/1, X2/Y2). 
ERROR: >=/2: Arguments are not sufficiently instantiated 

感謝您的幫助。

+1

如果您只是簡單地使用CLP(FD)約束而不是低級整數算術,那麼它的工作原理與預期完全相同:使用更通用的'(#=)/ 2'而不是'(is)/ 2'。而不是'(> =)/ 2',使用更通用的'(#> =)/ 2'。而不是'(= <)/ 2',使用更通用的'(#= <)/ 2'。 – mat 2014-11-22 21:40:21

+1

將validSquare/2重寫爲validSquare/1! – false 2014-11-22 21:42:02

回答

1

這是打破在validSquare> =測試。基本上,因爲數字運算符沒有賦值,所以當兩者都沒有綁定時,您無法確定X <= Y的真值。你可以通過使用一個成員的座標綁定到有效的正方形解決這個問題,即

validSquare(X1/Y1, X2/Y2):- 
    member(X1, [1,2,3,4,5,6,7,8]), 
    member(X2, [1,2,3,4,5,6,7,8]), 
    member(Y1, [1,2,3,4,5,6,7,8]), 
    member(Y2, [1,2,3,4,5,6,7,8]). 

根據您所使用的Prolog的方言,member可能是一個內置的(如SWI-Prolog的)或沒有。

+0

太好了,謝謝。我希望這會很簡單。感謝您的幫助 – 2014-11-22 19:58:44

+0

不客氣! – Junuxx 2014-11-22 20:07:45

+2

@ChrisPhillips'(1,8,X1)'之間,請 – false 2014-11-22 21:28:04

2
:- use_module(library(clpfd)). 

jump(X0/Y0, X/Y) :- 
    abs(X0-X)+abs(Y0-Y)#=3, 
    X0 #\= X, 
    Y0 #\= Y, 
    [X0,Y0,X,Y]ins 1..8. 
+1

提問者可能會更感激它,如果你要編輯答案也解釋如何/爲什麼這個工程 – Markasoftware 2014-11-22 22:35:32

1

這裏是​​顯示的代碼的替代形式。它也基於

 
jump(X0/Y0, X/Y) :- 
    D_x #= X0-X, 
    D_y #= Y0-Y, 
    abs(D_x) #\= abs(D_y), 
    [D_x , D_y] ins (-2 .. -1)\/(1..2), 
    [X0,X,Y0,Y] ins 1..8. 

這是高效1,2


腳註1:與4.3.2 版本(64位)和版本7.3.11(64位)進行測試。
腳註2: SICStus Prolog要求合適的定義(ins)/2以在代碼上運行。