2015-06-05 3 views
0

У меня есть предикат list_moves(Move), который дает все возможные ходы для игры. Тогда у меня есть следующие предикаты:Ждите конца предиката Prolog

find_best_move:- 
    nb_setval(best,0), 
    list_moves(NewMove), 
    nb_getval(best,OldMove), 
    better(OldMove,NewMove). 

better(OldMove, NewMove):- 
    NewMove > OldMove, 
    nb_setval(best,NewMove), !. 
better(_,_). 

get_best_move(Move):- 
    find_best_move, 
    nb_getval(max,Move). 

Я хочу, чтобы получить только один шаг, когда я называю get_best_move(Move): лучший. Проблема в том, что у меня есть лучший ход, но я также получаю много других ходов.

Exemple: Скажем, у меня есть следующие шаги в этом порядке от list_moves(Move) (чем больше значение, тем лучше двигаться):
move1: 0
Move2: 1
move3: 2
move4: 1
move5: 2
move6: 0

я получаю следующий результат, вызвав get_best_move(Move):
move1
Move2
move3
move3
move3
move3

Дело: Я просто хочу, чтобы получить move3 один раз. Меня не волнует ни move1-2, ни 3 других вхождения move3.

Я думаю, что одно решение может быть «ждать», пока find_best_move вызов в get_best_move не закончена, вместо того, чтобы делать nb_getval для каждого ответа дается find_best_move.

Как это сделать? Есть ли другое решение?

+2

Ваша программа использует очень проблемные встроенные вложения, в результате чего код, который не является r eentrant. См. Определение ['call_nth/2'] (http://stackoverflow.com/a/11400256/772868), как это сделать более чистым образом. – false

+0

Рассмотрим 'setof (Nn, Np^(list_moves (Np), Nn - -Np), [Nn | _]), Nmax - -Nn'. – false

ответ

0

Да, конечно, есть решение. Вы получаете список результатов, поэтому вам нужно отфильтровать их по определенному предикату или просто взять последний, потому что вы сортируете их в порядке возрастания.

Пролог генерирует эти решения по одному. Иногда мы хотели бы иметь все решения для запроса, и мы хотели бы, чтобы они были переданы нам в аккуратной, удобной форме. В Prolog есть три встроенных предиката, которые делают это: findall, bagof и setof. Нам нужно сначала получить все перечислить

?- findall(X,get_best_move(Move)) 

список [move1, move2, move3, move3, move3, move3] должен вернуться затем использовать последнюю функцию

%% last(?List, ?Last) 
% 
% Succeeds when Last is the last element of List. This 
% predicate is =semidet= if List is a list and =multi= if List is 
% a partial list. 
% 
% @compat There is no de-facto standard for the argument order of 
%  last/2. Be careful when porting code or use 
%  append(_, [Last], List) as a portable alternative. 

last([X|Xs], Last) :- 
    last_(Xs, X, Last). 

last_([], Last, Last). 
last_([X|Xs], _, Last) :- 
    last_(Xs, X, Last). 

что-то подобное

?- last(findall(X,get_best_move(Move)), Y) 

Я не знаю, реализация которых вы используете, но это может помочь

+0

Не существует предиката 'findall/2'. Что вы подразумеваете под этими обозначениями? – false

Смежные вопросы