我在Prolog中做了很少的编程,到目前为止发现它很难。
我被问到:大猩猩沿着8x8网格移动,只能向右或向上移动。它必须保持在网格内,并且必须从(8,8)开始,从任意位置开始。
编写描述所有可能移动的移动谓词。
我的尝试:
move(X,Y,X+1,Y).
move(X,Y,X,Y+1).
编写一个路径谓词,使用移动谓词来确定机器人所采用的路径。
我的尝试:
path('right'):-
move(X,Y,X+1,Y).
path('up'):-
move(X,Y,X,Y+1).
编写prolog谓词,模拟(1,2),(4,2)和(4,1)的阻塞。
到目前为止,从我发现的情况来看,似乎我需要建立一个能够提供所有可能位置的列表。
我写了一份可能的职位清单,但不明白如何实施:
[(1,1),(1,2),(1,3),(1,4),(1,5),(1,6),(1,7),(1,8),
(2,1),(2,2),(2,3),(2,4),(2,5),(2,6),(2,7),(2,8),
(3,1),(3,2),(3,3),(3,4),(3,5),(3,6),(3,7),(3,8),
(4,1),(4,2),(4,3),(4,4),(4,5),(4,6),(4,7),(4,8),
(5,1),(5,2),(5,3),(5,4),(5,5),(5,6),(5,7),(5,8),
(6,1),(6,2),(6,3),(6,4),(6,5),(6,6),(6,7),(6,8),
(7,1),(7,2),(7,3),(7,4),(7,5),(7,6),(7,7),(7,8),
(8,1),(8,2),(8,3),(8,4),(8,5),(8,6),(8,7),(8,8)]
这似乎是一个简单的程序,但我似乎无法掌握这些概念,或者至少将它们整合到一个可行的程序中。
非常感谢任何指导方面的帮助。
答案 0 :(得分:1)
所以你可能想在你做这件事时说出你在哪里。所以我会建议这样的谓词move/3
:
% move(From_Position, To_Position, Direction).
move((X,Y),(X,Y1), up) :-
grid(G),
member((X,Y1),G),
Y1 is Y + 1.
move((X,Y),(X1,Y), rigth):-
grid(G),
member((X1,Y),G),
X1 is X + 1.
网格调用是为了确保您始终保持在网格上。您还可以使用更智能的谓词in_grid
并避免member
调用(这非常耗时)。
grid([(1,1),(1,2),(1,3),(1,4),(1,5),(1,6),(1,7),(1,8),
(2,1),(2,2),(2,3),(2,4),(2,5),(2,6),(2,7),(2,8),
(3,1),(3,2),(3,3),(3,4),(3,5),(3,6),(3,7),(3,8),
(4,1),(4,2),(4,3),(4,4),(4,5),(4,6),(4,7),(4,8),
(5,1),(5,2),(5,3),(5,4),(5,5),(5,6),(5,7),(5,8),
(6,1),(6,2),(6,3),(6,4),(6,5),(6,6),(6,7),(6,8),
(7,1),(7,2),(7,3),(7,4),(7,5),(7,6),(7,7),(7,8),
(8,1),(8,2),(8,3),(8,4),(8,5),(8,6),(8,7),(8,8)]).
路径应该是方向列表:
path((8,8), []).
path(Position, [Direction| Before]):-
\+ Position = (8,8),
move(Position, NewPosition, Direction),
path(NewPosition,Before).
要累积,您可以使用bagof
或setof
all_paths(Position,Paths):-
setof(Path,path(Position,Path),Paths).
答案 1 :(得分:1)
您的代码存在一些问题。让我们一次一个地完成它。
<强> 1。可能的职位
虽然你的可能位置列表没问题,但我不会像那样硬编码。如果一个位置在网格上,检查是非常容易的:
grid_position(X, Y) :-
X >= 1,
X =< 8,
Y >= 1,
Y =< 8.
请注意,这只能用于验证给定的位置。如果您希望能够生成所有可能的职位,可以使用in/2
中的library(clpfd)
。
<强> 2。允许的职位
如果对于被阻止的位置没有如上所述的简单逻辑,除了自己枚举之外别无他法。
blocked(1, 2).
blocked(4, 2).
blocked(4, 1).
使用这个,我们可以确定我们的大猩猩允许的位置:网格上的任何位置,但不会被阻挡。
allowed_position(X, Y) :-
grid_position(X, Y),
\+blocked(X, Y).
第3。移动强>
这里的主要问题是在条款的开头写X+1
并不能完成您的想法。要评估算术表达式,您需要使用is
谓词。
此外,如果允许下一个位置,我只允许移动。由于大猩猩已经在当前位置,我不会检查是否确实允许这个位置。
move(X, Y, X2, Y) :-
X2 is X + 1,
allowed_position(X2, Y).
move(X, Y, X, Y2) :-
Y2 is Y + 1,
allowed_position(X, Y2).
<强> 4。路径强>
以下是我对该要求的解释:给定一个起始位置,返回用于到达终点位置的移动列表。
为此,我们需要3个参数:X和Y位置以及输出。这里的输出将是一个位置列表而不是一个移动列表,如果需要,我会留给您更改。
那么我们的道路是什么?好吧,首先你做一个动作,然后你从下一个位置找到剩下的路径。
path(X, Y, [(X,Y)|Ps]) :-
move(X, Y, X2, Y2),
path(X1, Y1, Ps).
当然,我们必须确保它在目标位置结束,因此对于基本情况我们可以使用:
path(8, 8, (8, 8)).
您可能还想验证初始位置是否为允许的位置,我已经遗漏了。
结合一切,你得到如下的输出。
?- path(5,6,L).
L = [(5,6),(6,6),(7,6),(8,6),(8,7)|(8,8)] ? ;
L = [(5,6),(6,6),(7,6),(7,7),(8,7)|(8,8)] ? ;
L = [(5,6),(6,6),(7,6),(7,7),(7,8)|(8,8)] ? ;
...
这可能不是您正在寻找的,但我希望它能帮助您顺利完成。