Reputation: 1425
I am developing a board game and to finalize I'm just missing my win condition.
The winner is supposed to be the 1st player to complete 4 stacks and those stacks are represented by the following board symbols:
Player 1 - 's1' , 'S1'
Player 2 - 's2' , 'S2'
Therefore, in order to determinate the winner,I have to run through the board (list of lists) and count the number of times the symbols are in the same one. When one of the players reaches 4 stacks completed, then he shall be the winner of the game:
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).
Although, the code developed does not work as expected. Counter1
and Counter2
from checkWin/3
are meant to be initialized at 0 ?-checkWin([...],0,0).
and increment as matches are found but, instead, it resets to 0 everytime the predicate calls recursion.
Current Output:
?- 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
Expected Output:
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
Upvotes: 0
Views: 57
Reputation: 1425
Thanks to CapelliC, and after adjusting the predicates provided, I finally got to a solution to my problem. Here's how it looks:
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).
Upvotes: 0
Reputation: 60024
You are 'reversing' the computation flow. Try
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).
If you want to give Prolog' builtins a try, here is an alternative:
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).
which can be shortened using library(aggregate)
checkStacks(L,N1,N2) :-
aggregate_all(count, (member(s1, L) ; member('S1', L)), N1),
aggregate_all(count, (member(s2, L) ; member('S2', L)), N2).
and a bit generalized, like
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).
I think checkWin/3 definition doesn't match your description, I would write instead
checkWin(Stacks, P) :-
member(S, Stacks),
( occurrences([s1,'S1'], S, 4) -> P = player1
; occurrences([s2,'S2'], S, 4) -> P = player2
).
Upvotes: 1