2011-12-09 2 views
2

프롤로그 프로그램을 처음 프로그래밍 할 때 언어가 정확히 어떻게 사용되는지 파악하는 데 어려움이 있습니다. 나는 퍼즐을 분석하고 퍼즐을 해결하는 행동 (경로)의 목록을 반환하는 프로그램을 만들고 있습니다.프롤로그 목록 작성

puzzle(Size,start(StartX,StartY),goal(GoalX,GoalY),Clues,Path) :- 
    solve(Size,StartX,StartY,XX,YY,Turns,Clues,GoalX,GoalY,[field(StartX,StartY)],Path). 

solve(Size,X,Y,XX,YY,Turns,Clues,GoalX,GoalY,Visited,Path) :- 
    X=GoalX, Y=GoalY,!;  
    Turns == 0, neighbor(X,Y,XX,YY), append(link(X,Y,XX,YY),Path,Newpath), solve(Size,XX,YY,XXX,YYY,Turns,Clues,GoalX,GoalY,Visited,Newpath); 
    Turns > 1, turn(X,Y,XX,YY), append(link(X,Y,XX,YY), Path, Newpath), solve(Size,XX,YY,XXX,YYY,Turns,Clues,GoalX,GoalY,Visited,Newpath). 

내가 재귀 적 기능을 해결 호출하고 목표에 도달 할 때까지 모든 새로운 호출 점진적 경로에 특정 동작을 추가하여 경로를 만들 : 여기처럼 보이는 방법을 매우 단순화 된 버전입니다. 이제 내 문제는 마지막 재귀 호출에 내가 원하는 경로가있는 것입니다. 그러나 묻는다면

?- puzzle(3, start(1,1), goal(3,3), [clue(2,1,2),clue(2,2,2)],Path) 

경로를 반환하지 않습니다. 설명하기 :

Exit: (13) solve(3, 3, 2, 0, 1, _G1027, _G1028, 1, 0, 1, [clue(2, 2, 2)], 3, 3, [feld(3, 2), feld(3, 1), feld(2, 1), feld(1, 1)], [link(3, 1, 3, 2), link(2, 1, 3, 1), link(1, 1, 2, 1), _G1012]) ? creep 

[링크 (3, 1, 3, 2), 링크 (2, 1, 3, 1) 링크 (1, 1, 2, 1), _G1012] 경로 I이고 필요한 것.

Exit: (12) move2(3, 3, 1, 1, 0, _G1027, _G1028, 1, 0, 2, [clue(2, 2, 2)], 3, 3, [feld(3, 1), feld(2, 1), feld(1, 1)], [link(2, 1, 3, 1), link(1, 1, 2, 1), _G1012]) ? creep 
    Exit: (11) solve(3, 3, 1, 1, 0, _G1027, _G1028, _G1029, _G1030, 2, [clue(2, 2, 2)], 3, 3, [feld(3, 1), feld(2, 1), feld(1, 1)], [link(2, 1, 3, 1), link(1, 1, 2, 1), _G1012]) ? creep 
    Exit: (10) stepfromclue(3, 2, 1, 1, 0, 2, [clue(2, 2, 2)], 3, 3, [feld(2, 1), feld(1, 1)], [link(1, 1, 2, 1), _G1012]) ? creep 
    Exit: (9) checkclue(3, 2, 1, 1, 0, [clue(2, 1, 2), clue(2, 2, 2)], 3, 3, [feld(2, 1), feld(1, 1)], [link(1, 1, 2, 1), _G1012]) ? creep 
    Exit: (8) solve(3, 1, 1, 1, 0, 2, 1, _G1029, _G1030, 0, [clue(2, 1, 2), clue(2, 2, 2)], 3, 3, [feld(1, 1)], [_G1012]) ? creep 
    Exit: (7) puzzle(3, start(1, 1), goal(3, 3), [clue(2, 1, 2), clue(2, 2, 2)], [_G1012]) ? creep 
    Exit: (6) puzzle(1, [_G1012]) ? creep 

경로 = [_G1012]는 내가 얻는 경로입니다. 나는 진지하게 내가 프로그램을 완전히 다시 쓰지 않고서 내가 필요한 길을 묻는 방법에 대해 머리를 감쌀 수 없다.

+0

정확하게 checkclue에서 길을 잃지는 않습니다. X, Y, XX, YY), 경로, Newpath), checkclue (크기, XX, YY, DX, DY, 단서, GoalX, GoalY, Newbesucht, Newpath). 결과적으로 checkclue가 호출 될 때 하나의 링크가있는 이전 경로가 있습니다. Checkclue 자체는 경로 등등에 추가되는 다른 링크로 이어집니다. –

+1

더 많은 프로그램을 포함시키기 위해 질문을 편집 할 수 있습니까? 내가 잘못 추측 했어야했는데, 프로그램을 더 보지 않고서는 다른 사람들도 문제를 발견하기가 어려울 것이라고 생각합니다. – sarnold

+0

필자는 프로그램을 대표하는 코드를 추가로 편집했습니다. 그러나 정말로, 나는 그 문제가 이해하기가 단순 해 보일 것처럼 느낍니다. 왜냐하면 그것은 나에게 명백한 실수입니다. 즉, solve 함수를 재귀 적으로 호출하면 사실과 다른 값을 반환하지 않습니다. 그래서 X = GoalX, Y = GoalY 뒤에 write (Path)를 추가하면! 그것은 나를 위해 올바른 길을 쓸 것입니다. 하지만 내가 물어볼 때 Path 대신에 그것을 돌려주고 싶다면 - 퍼즐 (3, 시작 (1,1), 목표 (3,3), 단서 (2,1,2), 경로) 작업. 그것이 작동하려면 프로그램을 변경해야하며 어떻게 할 수 있는지 이해할 수 없습니다. –

답변

0

전체 코드 (link/4 사실 포함)를 보지 않고도 프로그램을 직접 추적 할 수 없기 때문에 추측하기가 조금 어렵습니다. 두 가지 문제는 여기

append(link(X,Y,XX,YY),Path,Newpath), 

있습니다 : 당신이하려고 무엇

변수 NewPath에서 새 경로를 생성 경로에 대한 링크를 추가하여 반복적으로 경로를 구성입니다 :하지만 문제는 다음과 같은 생각 . 첫 번째는 link(X,Y,XX,YY)이 목록이 아니기 때문에 append/3은 실패합니다. 두 번째로 더 중요한 것은 Path이 입력 변수이고 NewPath 출력이지만 NewPathsolve/11의 다음 호출로 전달되지만 상승하지는 않습니다. 이렇게하면 전체 경로가 호출자에게 절대 전달되지 않습니다. 따라서 puzzle/5 호출 수준에서 Path 변수는 인스턴스화되지 않은 상태로 유지됩니다.

solve에 대한 코드는 아마 다음과 같아야합니다

solve(_,X,Y,_,_,_,_,GoalX,GoalY,_,Path,Path) :- 
    X=GoalX, Y=GoalY,!. 
solve(Size,X,Y,XX,YY,Turns,Clues,GoalX,GoalY,Visited,PathIn,Path) :- 
    Turns == 0, 
    neighbor(X,Y,XX,YY), 
    append(PathIn,[link(X,Y,XX,YY)],PathOut), 
    solve(Size,XX,YY,XXX,YYY,Turns,Clues,GoalX,GoalY,Visited,PathOut,Path). 
solve(Size,X,Y,XX,YY,Turns,Clues,GoalX,GoalY,Visited,PathIn,Path) :- 
    turn(X,Y,XX,YY), 
    append(PathIn,[link(X,Y,XX,YY)],PathOut), 
    solve(Size,XX,YY,XXX,YYY,Turns,Clues,GoalX,GoalY,Visited,PathOut,Path). 

그것은 더 간단하게 할 수는 있지만.

+0

예, 그게 문제였습니다!나는 변수를 전달하는 방법을 몰랐다. 이것은 정말 좋은 방법입니다, 많이 고마워요. 내가 남긴 유일한 질문은 더 단순화하는 것입니다. –

+0

코드에서'Size','Clues' 및'Visited' 매개 변수는 절대로 사용되지 않으므로 제거 될 수 있습니다. 그들이 사용 된 호출을 편집했을 수도 있습니다. 마찬가지로 재귀적인'solve' 호출에서'XXX'와'YYY' 매개 변수도 마찬가지입니다. 마지막으로 2 절과 3 절의 마지막 두 줄은 동일하므로'(Turns == 0 -> neighbor (...); turn (...)), append (...)를 사용하여 두 절을 병합 할 수 있습니다. ' – twinterer