I'm developing a board game in PROLOG and in order to make the interface more enjoyable for the user, I decided to add a grid with the coordinates (0->4) as shown below:
0 1 2 3 4
---------
0 | x x x x x
1 | x o x o o
2 | o x o x x
3 | x x o o o
4 | o x x x o
After developing some code, I came across with an issue regarding the counter for the vertical coordinates. The predicate stops right after I implement the counter Index is Index + 1
, as shown below:
printGrid :- %Only prints the horizontal grid
write('\t'), write(0), write(' '), write(1), write(' '), write(2), write(' '), write(3), write(' '), write(4), nl,
write('\t'), write('------------------'), nl.
printBoard([Head|Tail]) :-
Index = 0,
Index is Index + 1,
% STOPS HERE ------------
write(' '), write(Index), write(' |'), write(' '),
printRow(Head),
printBoard(Tail).
printBoard([]).
printRow([Head|Tail]) :-
write(Head),
write(' '),
printRow(Tail).
printRow([]) :- nl.
I'm aware the counter will reset to 0 every time recursion is called, thus I don't really know how to set the Index to 0 just about once and go from there. Any tips on how to solve both of the issues?
You cannot change the value of a variable that has been already bound. You need to use a new variable, for example, I1 is I + 1
, or maybe succ(I, I1)
.
Another thing you can do if you want to anyway use the side effect (printing in your case), is to put between
in a forall
loop:
?- forall(between(0, 4, X), format('~d~n', [X])).
0
1
2
3
4
true.
You can of course have nested forall
s:
?- forall(between(0, 5, X),
( forall(between(0, 4, Y),
format('~d-~d ', [X,Y])),
format('~n')
)).
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
5-0 5-1 5-2 5-3 5-4
true.
The way to enumerate the members of a list, then, would be to use nth0
, for example,
?- forall(nth0(N, [a,b,c,d], E), format('~d-~a~n', [N,E])).
0-a
1-b
2-c
3-d
true.
Or, if you don't need the element (when you are just marking the columns:
?- length([a,b,c,d], Len),
Last is Len - 1,
forall(between(0, Last, X), format('~d~n', [X])).
0
1
2
3
Len = 4,
Last = 3.
Or ignoring the element when you are using nth0
:
?- forall(nth0(N, [a,b,c,d], _), format('~d~n', [N])).
0
1
2
3
true.
There are other predicates that can offer similar functionality, depending on what exactly your goal is. See findall
and maplist
, for example.
But of course you can do the recursion yourself, if you remember to do the I1 is I + 1
.
I examined the link which @Otrebor provided and I came up with a fine solution. I forgot the "little" detail that when bound, a variable can't be changed, thus I added an extra one. Here's how it looks:
printBoard([], _).
printBoard([Head|Tail], Counter) :-
Index is Counter + 1,
write(' '), write(Index), write(' |'), write(' '),
printRow(Head),
printBoard(Tail, Index).
main :- printBoard(Board, 0).