% % TIC-TAC-TOE % % a | b | c % --+---+--- % d | e | f % --+---+--- % g | h | i % :- dynamic(move/2). human(x). computer(o). win_(a, b, c). win_(d, e, f). win_(g, h, i). win_(a, d, g). win_(b, e, h). win_(c, f, i). win_(a, e, i). win_(c, e, g). win(A, B, C) :- A \= B, A \= C, B \= C, ( win_(A, B, C), !; win_(A, C, B), !; win_(B, A, C), !; win_(B, C, A), !; win_(C, A, B), !; win_(C, B, A), ! ). filled :- move(a, _), move(b, _), move(c, _), move(d, _), move(e, _), move(f, _), move(g, _), move(h, _), move(i, _). winner(Winner) :- move(X, Winner), move(Y, Winner), move(Z, Winner), win(X, Y, Z). loser(Loser) :- winner(Winner), switch_turns(Winner, Loser). switch_turns(Old, New) :- member(Old, [o,x]), member(New, [o,x]), Old \= New. tie :- winner(_),!,fail; filled. game_over :- filled; winner(_). free(Square) :- member(Square, [a,b,c,d,e,f,g,h,i]), \+ move(Square, _). enter(Square, Turn) :- human(Turn), repeat, write('Your move: '), read(Input), ( Input = 'exit', halt ; member(Input, [a,b,c,d,e,f,g,h,i]), free(Square), Square = Input ; move(Input, _), write('This move is already taken'), nl, fail ; \+ member(Input, [a,b,c,d,e,f,g,h,i]), write('Please enter in a square'),nl, fail ). enter(Square, Turn) :- % Prefer a winning move computer(Turn), free(Square), move(X, Turn), move(Y, Turn), win(Square, X, Y), !. enter(Square, Turn) :- % Block a winning move if needed computer(Turn), switch_turns(Turn, Op), move(X, Op), move(Y, Op), win(Square, X, Y), free(Square), !. enter(Square, Turn) :- % But take a two-in-row if I can computer(Turn), move(X, Turn), free(Square), free(Y), win(Square, X, Y), !. enter(Square, Turn) :- % prefer the middle computer(Turn), free(e), Square = e, !. enter(Square, Turn) :- % Just make any move if it doesn't matter. computer(Turn), free(Square), free(X), free(Y), win(Square, X, Y), !. text(Square, Text) :- move(Square, Text),!; Text = ' '. draw :- text(a, A),text(b, B),text(c, C), text(d, D),text(e, E),text(f, F), text(g, G),text(h, H),text(i, I), write(' '),write(A),write(' | '),write(B),write(' | '),write(C),nl, write('---+---+---'),nl, write(' '),write(D),write(' | '),write(E),write(' | '),write(F),nl, write('---+---+---'),nl, write(' '),write(G),write(' | '),write(H),write(' | '),write(I),nl, nl. play :- retractall(move(_, _)), % clear the game so we can play again play(x). play(_) :- % if the game is over, say so and restart. ( tie, draw, write('Cat\'s game'), nl ; winner(Winner), draw, write(Winner), write(' won the game.'), nl ), !. play(Turn) :- (human(Turn), draw; computer(Turn)), enter(Square, Turn), !, assertz(move(Square, Turn)), switch_turns(Turn, New), play(New).