2014-11-11 2 views
0

Я разрабатываю настольную игру, и для завершения я просто не могу получить условие выигрыша.Счетчик сбрасывается после предикатного вызова

Победитель должен быть первым игроком, чтобы закончить 4 стек и представлены эти стеки следующих символами борта:

Player 1 - 's1' , 'S1' 
Player 2 - 's2' , 'S2' 

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

checkWin([],_,_). 
checkWin([Head|Tail], Counter1, Counter2) :- 

     checkStacks(Head, Counter1, Counter2), nl, 
     (Counter1 = 4 -> write('Player 1 is the winner!'); true), 
     (Counter2 = 4 -> write('Player 2 is the winner!'); true), 
     checkWin(Tail,Counter1,Counter2). 

checkStacks([],_,_). 
checkStacks([Head|Tail], Counter1, Counter2) :- 

     Symbol = Head, 
     ((Symbol = 's1'; Symbol = 'S1') -> StackCounter1 is Counter1 + 1; StackCounter1 is Counter1), 
     ((Symbol = 's2'; Symbol = 'S2') -> StackCounter2 is Counter2 + 1; StackCounter2 is Counter2), 

     write('SC1 = '), write(StackCounter1), write(' SC2 = '), write(StackCounter2), nl, 

     checkStacks(Tail, StackCounter1, StackCounter2). 

Хотя код разработан не работает, как ожидалось. Counter1 и Counter2 от checkWin/3 предназначены для инициализации в 0 ?-checkWin([...],0,0). и приращения при совпадении совпадений, но вместо этого он сбрасывается до 0 каждый раз при рекурсии предикатных вызовов.

Выходной ток:

?- checkWin([['b0','b0','b0','S1','s1'], 
       ['b0','b0','b0','b0','B0'], 
       ['b0','b0','b0','s1','S2'], 
       ['b0','b0','b0','b0','s2'], 
       ['b2','b0','b0','b0','b0']], 0, 0). 

SC1 = 0 SC2 = 0 
SC1 = 0 SC2 = 0 
SC1 = 0 SC2 = 0 
SC1 = 1 SC2 = 0 
SC1 = 2 SC2 = 0 % SC1 = 2, 2 matches were found for Player1 in the first row 

SC1 = 0 SC2 = 0 % SC1 resets to 0 instead of having the previous value(2) 
SC1 = 0 SC2 = 0 
SC1 = 0 SC2 = 0 
SC1 = 0 SC2 = 0 
SC1 = 0 SC2 = 0 

SC1 = 0 SC2 = 0 
SC1 = 0 SC2 = 0 
SC1 = 0 SC2 = 0 
SC1 = 1 SC2 = 0 
SC1 = 1 SC2 = 1 

SC1 = 0 SC2 = 0 
SC1 = 0 SC2 = 0 
SC1 = 0 SC2 = 0 
SC1 = 0 SC2 = 0 
SC1 = 0 SC2 = 1 

SC1 = 0 SC2 = 0 
SC1 = 0 SC2 = 0 
SC1 = 0 SC2 = 0 
SC1 = 0 SC2 = 0 
SC1 = 0 SC2 = 0 
yes 
% source_info 

Ожидаемый результат:

SC1 = 0 SC2 = 0 
SC1 = 0 SC2 = 0 
SC1 = 0 SC2 = 0 
SC1 = 1 SC2 = 0 
SC1 = 2 SC2 = 0 

SC1 = 2 SC2 = 0 
SC1 = 2 SC2 = 0 
SC1 = 2 SC2 = 0 
SC1 = 2 SC2 = 0 
SC1 = 2 SC2 = 0 

SC1 = 2 SC2 = 0 
SC1 = 2 SC2 = 0 
SC1 = 2 SC2 = 0 
SC1 = 3 SC2 = 0 
SC1 = 3 SC2 = 1 

SC1 = 3 SC2 = 1 
SC1 = 3 SC2 = 1 
SC1 = 3 SC2 = 1 
SC1 = 3 SC2 = 1 
SC1 = 3 SC2 = 2 % - number of matches for each player 

SC1 = 0 SC2 = 0 
SC1 = 0 SC2 = 0 
SC1 = 0 SC2 = 0 
SC1 = 0 SC2 = 0 
SC1 = 0 SC2 = 0 
yes 
% source_info 

ответ

1

Вы 'задним ходом' поток вычислений. Попробуйте

checkStacks([],0,0). 
checkStacks([Head|Tail], Counter1, Counter2) :- 

     checkStacks(Tail, StackCounter1, StackCounter2), 

     Symbol = Head, 
     ((Symbol = 's1'; Symbol = 'S1') -> Counter1 is StackCounter1 + 1; Counter1 is StackCounter1), 
     ((Symbol = 's2'; Symbol = 'S2') -> Counter2 is StackCounter2 + 1; Counter2 is StackCounter2). 

Если вы хотите, чтобы встроенные функции Пролога»попробовать, вот альтернатива:

checkStacks(L,N1,N2) :- 
    findall(t, (member(s1, L) ; member('S1', L)), L1), length(L1,N1) 
    findall(t, (member(s2, L) ; member('S2', L)), L2), length(L2,N2). 

, которые могут быть сокращены с использованием библиотеки (складочном)

checkStacks(L,N1,N2) :- 
    aggregate_all(count, (member(s1, L) ; member('S1', L)), N1), 
    aggregate_all(count, (member(s2, L) ; member('S2', L)), N2). 

и немного обобщенные, например

occurrences(Symbols, L, N) :- 
    aggregate_all(count, (member(S, Symbols), member(S, L)), N). 

checkStacks(L,N1,N2) :- 
    occurrences([s1,'S1'], L, N1), 
    occurrences([s2,'S2'], L, N2). 

Я думаю checkWin определение/3 не совпадает с описанием, я хотел бы написать вместо

checkWin(Stacks, P) :- 
    member(S, Stacks), 
    (occurrences([s1,'S1'], S, 4) -> P = player1 
    ; occurrences([s2,'S2'], S, 4) -> P = player2 
    ). 
+0

Я попытался реализовать ваше решение, но может возникнуть проблема с 'aggregate_all/3'. Я постоянно получаю ту же ошибку каждый раз, когда я запускаю любой из предикатов: «Ошибка создания в пользователе: aggregate_all/3 ! Цель: aggregate_all (count, user: (member (_197, s1), member (_197, [s1, 'S1', b0, 'S2'])), 0) ' – Khabz

+0

Я тестировал без квалификации' user :() ' – CapelliC

+0

ugh, что я должен был сделать тогда? – Khabz

0

Благодаря CapelliC, и после регулировки предикаты обеспечить, я, наконец, к решению моей проблемы. Вот как это выглядит:

occurrences(Symbol, L, N) :- 
     aggregate_all(count, member(Symbol, L), N). 

checkWin([], C1, C2) :- write('Player 1 Counter = '), write(C1), nl, 
         write('Player 2 Counter = '), write(C2), nl. 
checkWin([Head|Tail], C1, C2) :- 

     occurrences('s1', Head, N), 
     occurrences('S1', Head, N1), 
     occurrences('s2', Head, N2), 
     occurrences('S2', Head, N3), 

     D1 is N + N1 + C1, D2 is N2 + N3 + C2, 
     checkWin(Tail, D1, D2). 
Смежные вопросы