编写一个Prolog程序来模拟大猩猩在网格上移动

编写一个Prolog程序来模拟大猩猩在网格上移动,prolog,Prolog,我很少用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编程,到目前为止,我觉得很难

我被问到一个问题:大猩猩沿着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).
编写一个路径谓词,该谓词使用移动谓词来确定机器人应该选择的路径

我的尝试:

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)]
这似乎是一个简单的程序,但我似乎无法掌握这些概念,或者至少无法将它们组合成一个可行的程序


任何方向上的帮助都将不胜感激。

因此,您可能希望在这样做的同时说出您的移动位置。因此,我建议使用如下谓词
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.
网格调用用于确保您始终保持在网格上。您还可以在网格中使用更智能的谓词
,避免
成员调用(这相当耗时)

路径可能应该是一个方向列表:

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).

所以你可能想说你在做这件事的时候要去哪里。因此,我建议使用如下谓词
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.
网格调用用于确保您始终保持在网格上。您还可以在网格中使用更智能的谓词
,避免
成员调用(这相当耗时)

路径可能应该是一个方向列表:

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).

所以你可能想说你在做这件事的时候要去哪里。因此,我建议使用如下谓词
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.
网格调用用于确保您始终保持在网格上。您还可以在网格中使用更智能的谓词
,避免
成员调用(这相当耗时)

路径可能应该是一个方向列表:

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).

所以你可能想说你在做这件事的时候要去哪里。因此,我建议使用如下谓词
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.
网格调用用于确保您始终保持在网格上。您还可以在网格中使用更智能的谓词
,避免
成员调用(这相当耗时)

路径可能应该是一个方向列表:

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。可能的职位

虽然你的可能职位列表还可以,但我不会那样硬编码。检查位置是否在网格上非常容易:

grid_position(X, Y) :- 
    X >= 1,
    X =< 8,
    Y >= 1,
    Y =< 8.
使用这个,我们可以确定大猩猩允许的位置:网格上的任何位置,但没有被阻止

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。路径

以下是我对需求的解释:给定开始位置,返回用于到达结束位置的移动列表

path(X, Y, [(X,Y)|Ps]) :- 
    move(X, Y, X2, Y2), 
    path(X1, Y1, Ps).
为此,我们需要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)] ? ; 
...

这可能不是您想要的,但我希望它能帮助您顺利完成任务。

您的代码存在一些问题。让我们一次看一个

1。可能的职位

虽然你的可能职位列表还可以,但我不会那样硬编码。检查位置是否在网格上非常容易:

grid_position(X, Y) :- 
    X >= 1,
    X =< 8,
    Y >= 1,
    Y =< 8.
使用这个,我们可以确定大猩猩允许的位置:网格上的任何位置,但没有被阻止

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。路径

以下是我对需求的解释:给定开始位置,返回用于到达结束位置的移动列表

path(X, Y, [(X,Y)|Ps]) :- 
    move(X, Y, X2, Y2), 
    path(X1, Y1, Ps).
为此,我们需要3个参数:X和Y位置,以及输出。这里的输出将是一个位置列表,而不是一个移动列表,如果需要的话,我将把它留给您来更改

那么,是什么组成了我们的道路?好吧,首先你做一个动作,一个动作