Как создать список доступных шагов в сетке?

У меня есть сетка 5x5, которая описывается max_size(5, 5). Мне нужно создать список всех ячеек из этого описания, используя DCG.

Вот код, который у меня есть до сих пор:

:- use_module(library(clpfd)).

map_size(5, 5).

natnum(0).
natnum(X) :-
    X #= X0 + 1,
    natnum(X0).

list_all_cells(Visited) -->
    { length(Visited, 25) },
    []. 
list_all_cells(Visited) -->
    [X-Y],
    { map_size(X_max, Y_max),
      natnum(X), natnum(Y),
      X #< X_max, Y #< Y_max,
      maplist(dif(X-Y), Visited) },
    list_all_cells([X-Y|Visited]).

Однако он не генерирует список и выводит только 4 пары.

Возможный запрос к DCG выглядит как list_all_cells([]), который должен отображать все ячейки в сетке. Например, это будет [0-0, 1-0, 1-1, 0-1] для сетки 2x2 (порядок не имеет значения).

На самом деле мне нужен этот предикат для создания другого предиката с именем available_steps/2, который будет генерировать список всех возможных ходов для данной позиции. Имея available_steps(CurrentPos, Visited), я смогу переборщить Hunt the Wumpus игру и найти все возможные пути к золоту.


person Radical Ed    schedule 10.03.2019    source источник
comment
@Guy, обновил вопрос, надеюсь, теперь все понятно. Спасибо   -  person Radical Ed    schedule 10.03.2019
comment
Теперь все исправлено :)   -  person Radical Ed    schedule 10.03.2019
comment
Я пытался сделать что-то похожее на path_from_to описанное здесь   -  person Radical Ed    schedule 10.03.2019
comment
Давайте продолжим это обсуждение в чате.   -  person Radical Ed    schedule 10.03.2019


Ответы (1)


list_all_cells(Cells) :-
    bagof(C,cell(C),Cells).

cell(X-Y) :-
    between(0,4,X),
    between(0,4,Y).

Пример запуска:

?- list_all_cells(Cells); true.
Cells= [0-0, 0-1, 0-2, 0-3, 0-4, 1-0, 1-1, 1-2, ... - ...|...] [write]  % The letter w was pressed.
Cells= [0-0, 0-1, 0-2, 0-3, 0-4, 1-0, 1-1, 1-2, 1-3, 1-4, 2-0, 2-1, 2-2, 2-3, 2-4, 3-0, 3-1, 3-2, 3-3, 3-4, 4-0, 4-1, 4-2, 4-3, 4-4] ;
true.
person Guy Coder    schedule 10.03.2019
comment
Почему у нас есть true в цели? - person Radical Ed; 10.03.2019
comment
@RadicalEd добавление ;true к цели используется, чтобы заставить SWI-Prolog запрашивать ввод пользователя перед возвратом, чтобы можно было ввести w, чтобы показать весь ответ. Без ;true ответ возвращается с ... и затем заканчивается. Я сделал это, чтобы показать вам, что все 25 значений находятся в списке. Когда вы используете это в своем коде, ; true не требуется. См.: SWI-Prolog, как показать весь ответ (список)?. Я оставляю это как комментарий, потому что на самом деле это не часть ответа и то, что любой хороший программист на Прологе должен знать при запуске. - person Guy Coder; 10.03.2019
comment
Почему не cell(X-Y)? - person repeat; 10.03.2019
comment
@repeat Спасибо, еще раз. Фиксированный. Да, это должно быть cell(X-Y). Последние несколько недель я выполнял DCG, возвращая структуры без имен и, таким образом, используя functor((parm1,pam2,...)).. Даже не заметил, как я это сделал. - person Guy Coder; 11.03.2019
comment
Эти дополнительные скобки могут иметь значение, иногда они необходимы, иногда они представляют собой небольшую проблему. Рассмотрим составной термин f((a,b,c,d)): это не f/4, а f/1 со списком запятых внутри (по умолчанию): (a,b,c,d) == (a,(b,(c,d))), который занимает больше памяти, чем составной элемент арности 4, а также медленнее для доступа (поскольку это дерево, а не плоское) . ХТН - person repeat; 11.03.2019
comment
Итак, у этих структур есть имя: (,)/2. - person repeat; 11.03.2019
comment
@повторить Спасибо. Никогда не считал (,)/2 именем, придется изучить его подробнее или задать вопрос, чтобы лучше его понять. - person Guy Coder; 11.03.2019