1
votes

I have basic Tick-tack-toe game, where 2 players both make moves on a grid of 9 cells. The problem is that after the frist player makes the last and winnig move, the game doesnt stop and player 2 still can play. And if second player, somehow, makes winning move too, he will be the winner, despite player 1 actually getting the win first. It doesnt make same error if second player wins frist. Draw works fine. Here`s the code:

:- dynamic o/1.
:- dynamic x/1.

/* the various combinations of a successful horizontal, vertical
or diagonal line */

ordered_line(1,2,3).
ordered_line(4,5,6).
ordered_line(7,8,9).
ordered_line(1,4,7).
ordered_line(2,5,8).
ordered_line(3,6,9).
ordered_line(1,5,9).
ordered_line(3,5,7).

/*line predicate to complete lines

line(A,B,C) :- ordered_line(A,B,C).
line(A,B,C) :- ordered_line(A,C,B).
line(A,B,C) :- ordered_line(B,A,C).
line(A,B,C) :- ordered_line(B,C,A).
line(A,B,C) :- ordered_line(C,A,B).
line(A,B,C) :- ordered_line(C,B,A).


full(A) :- x(A).
full(A) :- o(A).

empty(A) :- not(full(A)).

all_full :- full(1),full(2),full(3),full(4),full(5),
full(6),full(7),full(8),full(9).


done :- ordered_line(A,B,C), x(A), x(B), x(C), write('Player 2 win.'),nl.

done :- ordered_line(A,B,C), o(A), o(B), o(C), write('Player 1 win.'),nl.

done :- all_full, write('Draw.'), nl.

move1 :- write('Player 1 (o) enter a move: '), read(X), between(1,9,X),  
empty(X), assert(o(X)).
move1:-all_full.
move2 :-  write('Player 2 (x) enter a move: '), read(X), between(1,9,X),  
empty(X),assert(x(X)).
move2:- all_full.
printsquare(N) :- o(N), write(' o ').
printsquare(N) :- x(N), write(' x ').
printsquare(N) :- empty(N), write('   ').

printboard :- printsquare(1),printsquare(2),printsquare(3),nl,
          printsquare(4),printsquare(5),printsquare(6),nl,
          printsquare(7),printsquare(8),printsquare(9),nl.

clear :- x(A), retract(x(A)), fail.
clear :- o(A), retract(o(A)), fail.

play :- not(clear), repeat, move1, printboard, move2,printboard, done.

And that`s the error I get: Game doesnt stop when player 1 wins

Hope you can help me :) Thanks in advance.

Edit: The "Player 2 wins" shows in "done" predicate. After successfull finishing line of 3 'o' or 'x' game should end with either Player 1 wins or Player 2 wins. I`ll include original code, which might help with understanding the problem I get Original code with comments

1
Can you explain a bit more? - Dieter Meemken
@lurker I made an update, hope it helps! - Mark Parfenov
You have an "open" comment before your line predicates (doesn't end with */). - lurker
The problem is that you only check for done after BOTH players have moved. You need to check it after EACH player moves. It won't be as simple as inserting a done, however (i.e., this won't work: play :- not(clear), repeat, move1, printboard, done, move2, printboard, done.), due to your logic. So you'll have to refactor your play predicate. - lurker
Thank you @lurker for answering and helping! - Mark Parfenov

1 Answers

0
votes

The problem is in the main predicate of the game:

play :- not(clear), repeat, move1, printboard, move2,printboard, done.

You do not check for done after player's 1 move.

In Prolog's syntax, logical "or" is written as ;. So one way to express the play predicate is:

play :- not(clear), repeat, move1, printboard, (done; move2, printboard, done).

Which says "after move1, check if the game is done (i.e., finished); if not, player 2 makes the move, and then the check is repeated.