сдвиг списка в Прологе

Следующий код приводит к бесконечному циклу с возможной ошибкой «Out of Local Stack». В основном я уменьшаю значение GX до тех пор, пока оно не станет таким же, как MX. Пример ввода [[m,g,b],[w,w,w]],путь

wallBlock('w').
wallBlock('b').
item('f').
item('p').
item('m').
item('u').
item('6').
item('r').
item('g').
anyCell(Cell) :- 
    wallBlock(Cell).
anyCell(Cell) :-
    item(Cell).


ghostPathing(Maps, Path) :-
    append(Maps, NewMap), 
    length(Maps, N), 
    findGhost(NewMap, N, GX, GY), 
    findPacman(NewMap, N, MX, MY),
    moveGhost(NewMap, N, MX, MY, GX, GY, Path).

/*FINDS THE COORDINATES OF THE GHOST W=row X=column*/
findGhost(NewMap, N, X, Y) :-
    findGhostSpot(NewMap, S),
    X is floor(S / N) + 1,
    Y is (S mod N) +1 .

findGhostSpot(['g'|_], 0) :-
    print('Found Ghost. ').
findGhostSpot(['r'|_], 0) :-
    print('Found Ghost. ').
findGhostSpot(['6'|_], 0) :-
    print('Found Ghost. ').
findGhostSpot([_|Tail], S) :-
    findGhostSpot(Tail, S1),
    S is S1+1 .

/*FINDS THE COORDINATES OF THE GHOST W=row X=column*/
findPacman(NewMap, N, X, Y) :-
    findPacmanSpot(NewMap, S),
    X is floor(S / N) + 1,
    Y is (S mod N) + 1.

findPacmanSpot(['m'|_], 0) :-
    print('Found Pacman. ').
findPacmanSpot([_|Tail], S) :-
    findPacmanSpot(Tail, S1),
    S is S1+1 .

/* Base Case, Ghost is on the Pacman*/
moveGhost(_, _, X, Y, X, Y, []).

/*IF PACMAN AND THE GHOST ARE IN THE SAME COLUMN*/
moveGhost(NewMap, N, MX, Y, GX, Y, ['u'|Rest]) :-
    itemNext(NewMap, CN, Z),
    item(Z),
    moveGhost(NewMap, N, MX, Y, X, Y, Rest),
    GX is X + 1,
    MX < GX,
    CN is ((X * N) + Y).
moveGhost(NewMap, N, MX, Y, GX, Y, ['d'|Rest]) :-
    itemNext(NewMap, CN, Z),
    item(Z),
    moveGhost(NewMap, N, MX, Y, X, Y, Rest),
    GX is X - 1,
    MX > GX,
    CN is ((X * N) + Y).

/*IF PACMAN AND THE GHOST ARE IN THE SAME ROW*/
moveGhost(NewMap, N, X, MY, X, GY, ['l'|Rest]) :-
    itemNext(NewMap, CN, Z),
    item(Z),
    moveGhost(NewMap, N, X, MY, X, Y, Rest),
    GY is Y + 1,
    MY < GY,
    CN is ((X * N) + Y).
moveGhost(NewMap, N, X, MY, X, GY, ['r'|Rest]) :-
    itemNext(NewMap, CN, Z),
    item(Z),
    moveGhost(NewMap, N, X, MY, X, Y, Rest),
    GY is Y - 1,
    MY > GY,
    CN is ((X * N) + Y).

itemNext([Cell|_], 0, Cell) :-
    item(Cell). 
itemNext([First|Rest], CN, Cell) :-
    anyCell(First),
    itemNext(Rest, N, Cell),
    CN is N + 1.

поскольку это массив 2d, добавление превращает его в 1d, а арифметика в NextCell берет длину строки, находит координаты соседней ячейки и возвращает значение этой ячейки. Призрак не может двигаться в этом направлении, если ячейка представляет собой «w» или «b». вы можете предположить, что Карты КВАДРАТНЫЕ!


person theB3RV    schedule 03.12.2012    source источник
comment
Если GX — свободная переменная, вы получаете ‹/2: Аргументы недостаточно конкретизированы. так что GX равно X+1 должно быть написано перед MX ‹ GX.   -  person joel76    schedule 03.12.2012
comment
@ joel76 joel76, когда я это делаю, я получаю бесконечный цикл с возможным переполнением локального стека.   -  person theB3RV    schedule 03.12.2012
comment
например, МХ=3, Y=3, GX=4, Y=3   -  person theB3RV    schedule 03.12.2012
comment
Хорошо, есть проблема с дизайном. Вы должны опубликовать больше кодов.   -  person joel76    schedule 03.12.2012
comment
@ joel76 joel76 это весь код, который у меня есть. это работает только в том случае, если pacman и призрак находятся в одной строке / столбце, когда он закончен, но хотелось бы, чтобы он работал везде, где находится призрак.   -  person theB3RV    schedule 03.12.2012


Ответы (1)


(Я предполагаю, что ваш вопрос заключается в том, почему ваша программа зацикливается.)

Чтобы локализовать причину незавершения вашей программы, я вставил в вашу программу цели false. Поскольку оставшаяся программа (срез ошибки) не завершается, исходная программа также не завершается. Вам нужно что-то исправить в оставшейся видимой части. Или, говоря иначе: пока текущий фрагмент остается неизменным, проблема будет сохраняться! И в качестве небольшого замечания, лучше избегать print/1 целей в чистой программе, как у вас.

Для получения дополнительной информации см. тег failure-slice

?- ghostPathing([[m,g,b],[w,w,w]],Path), false.


item('f') :- false.
item('p') :- false.
item('m').
item('u') :- false.
item('6') :- false.
item('r') :- false.
item('g').

anyCell(Cell) :- false,
    wallBlock(Cell).
anyCell(Cell) :-
    item(Cell).

ghostPathing(Maps, Path) :-
    append(Maps, NewMap), 
    length(Maps, N), 
    findGhost(NewMap, N, GX, GY), 
    findPacman(NewMap, N, MX, MY),
    moveGhost(NewMap, N, MX, MY, GX, GY, Path), false.

/*FINDS THE COORDINATES OF THE GHOST W=row X=column*/
findGhost(NewMap, N, X, Y) :-
    findGhostSpot(NewMap, S),
    X is floor(S / N) + 1,
    Y is (S mod N) +1 .

findGhostSpot(['g'|_], 0) :-
    print('Found Ghost. ').
findGhostSpot(['r'|_], 0) :- false,
    print('Found Ghost. ').
findGhostSpot(['6'|_], 0) :- false,
    print('Found Ghost. ').
findGhostSpot([_|Tail], S) :-
    findGhostSpot(Tail, S1),
    S is S1+1 .

/*FINDS THE COORDINATES OF THE GHOST W=row X=column*/
findPacman(NewMap, N, X, Y) :-
    findPacmanSpot(NewMap, S),
    X is floor(S / N) + 1,
    Y is (S mod N) + 1.

findPacmanSpot(['m'|_], 0) :-
    print('Found Pacman. ').
findPacmanSpot([_|Tail], S) :- false,
    findPacmanSpot(Tail, S1),
    S is S1+1 .

/* Base Case, Ghost is on the Pacman*/
moveGhost(_, _, X, Y, X, Y, []) :- false.

/*IF PACMAN AND THE GHOST ARE IN THE SAME COLUMN*/
moveGhost(NewMap, N, MX, Y, GX, Y, ['u'|Rest]) :- false,
    itemNext(NewMap, CN, Z),
    item(Z),
    moveGhost(NewMap, N, MX, Y, X, Y, Rest),
    GX is X + 1,
    MX < GX,
    CN is ((X * N) + Y).
moveGhost(NewMap, N, MX, Y, GX, Y, ['d'|Rest]) :-  false,
    itemNext(NewMap, CN, Z),
    item(Z),
    moveGhost(NewMap, N, MX, Y, X, Y, Rest),
    GX is X - 1,
    MX > GX,
    CN is ((X * N) + Y).

/*IF PACMAN AND THE GHOST ARE IN THE SAME ROW*/
moveGhost(NewMap, N, X, MY, X, GY, ['l'|Rest]) :-
    itemNext(NewMap, CN, Z),
    item(Z),
    moveGhost(NewMap, N, X, MY, X, Y, Rest), false,
    GY is Y + 1,
    MY < GY,
    CN is ((X * N) + Y).
moveGhost(NewMap, N, X, MY, X, GY, ['r'|Rest]) :- false,
    itemNext(NewMap, CN, Z),
    item(Z),
    moveGhost(NewMap, N, X, MY, X, Y, Rest),
    GY is Y - 1,
    MY > GY,
    CN is ((X * N) + Y).

itemNext([Cell|_], 0, Cell) :-
    item(Cell). 
itemNext([First|Rest], CN, Cell) :-
    anyCell(First),
    itemNext(Rest, N, Cell),
    CN is N + 1.
person false    schedule 03.12.2012