Reputation: 6181
I am trying to write a simple Noughts-and-Crosses (Tic-tac-Toe) evaluator in Prolog. The first thing I am trying to do is to have the program calculate all possible winning boards. The logic isn't complete yet - it doesn't check for valid boards that could result from the actual playing of the game - it is simply looking for any 'lines-of-3'.
The problem is, the program 'stops-short' : it correctly detects lines-of-3 and unifies the variables that make up the line-of-3 - but doesn't show the combinations of the other variables. (The cells which do not lie on the winning-line that is).
Here's my program and an example output:
/*
Attempting to create a program that will output 'x' ,'o' or 'none'
given a (filled-in) tic-tac-toe board.
'x' - 'x' has won. (Literally there is a line of x's)
'o' - 'o' as above
'none' : no winners on the given board.
This does NOT check whether the board is in a valid state for tic-tac-toe!
*/
/* Define board states as facts */
cell(none).
cell(x).
cell(o).
/* Define winning line of 3 */
win_line(C1, C2, C3, Winner) :-
cell(C1),
cell(C2),
cell(C3),
C1 \== none,
C1==C2,
C2==C3,
Winner=C1.
/* define the board rule: variables are 'encoded' for each cell by a coordinate (col,row) */
board( C11, C12, C13,
C21, C22, C23,
C31, C32, C34, Winner) :-
win_line(C11, C12, C13, Winner); /* Test the three rows */
win_line(C21, C22, C23, Winner);
win_line(C31, C32, C33, Winner);
win_line(C11, C21, C31, Winner); /* Test the three columns */
win_line(C12, C22, C32, Winner);
win_line(C13, C23, C34, Winner);
win_line(C13, C23, C34, Winner); /* Test the two diaganols */
win_line(C11, C22, C34, Winner);
win_line(C13, C22, C31, Winner).
My query , with the output follows:
| ?- board(C11,C12,C13, C21,C22,C23, C31,C32,C33, o).
C11 = o
C12 = o
C13 = o ? a
C21 = o
C22 = o
C23 = o
C31 = o
C32 = o
C11 = o
C21 = o
C31 = o
C12 = o
C22 = o
C32 = o
C13 = o
C23 = o
C33 = o
C13 = o
C23 = o
C33 = o
C11 = o
C22 = o
C33 = o
C13 = o
C22 = o
C31 = o
(4 ms) yes
Version information:
GNU Prolog 1.3.0
By Daniel Diaz
Copyright (C) 1999-2007 Daniel Diaz
| ?-
Upvotes: 1
Views: 136
Reputation: 9644
I see you've fixed your first problem.
One way to get all possible results to a query is using findall/3
:
?- findall([A,B,C,D,E,F,G,H,I], board(A,B,C,D,E,F,G,H,I,o), Results).
Results = [[o,o,o,_,_,_,_,_,_],
[_,_,_,o,o,o,_,_,_],
[_,_,_,_,_,_,o,o,o],
[o,_,_,o,_,_,o,_,_],
[_,o,_,_,o,_,_,o,_],
[_,_,o,_,_,o,_,_,o],
[_,_,o,_,_,o,_,_,o],
[o,_,_,_,o,_,_,_,o],
[_,_,o,_,o,_,o,_,_]]
Note that it only takes into account the values that actually matter in this case, leaving the other values alone.
If you need to have the other values locked to actual atoms, there are ways to do that, though it involves writing another couple of predicates to find all possible combinations of values to get you that result, for each result in Results
.
Upvotes: 1
Reputation: 6181
Got it, I think - I have altered the board rule like this:
/* define the board rule: variables are 'encoded' for each cell by a coordinate (col,row) */
board( C11, C12, C13,
C21, C22, C23,
C31, C32, C34, Winner) :-
cell(C11), cell(C12), cell(C13),
cell(C21), cell(C22), cell(C23),
cell(C31), cell(C32), cell(C33),
win_line(C11, C12, C13, Winner); /* Test the three rows */
[...]as before
So add in the further clauses that every variable unifies with a cell fact...Not 100% sure why I needed to do that...but it seems to work...
Upvotes: 0