% SU2010 CSE3401- Prolog example % Tic-Tac-Toe Game % Not using minimax! % Please report bugs or suggest improvements to % Vida Movahedi vida@cse.yorku.ca :- consult('showBoard.pl'). % Changing value in a certain position of a board % For example setPosBoard(b(x,e,x, e,e,e, e,e,e), 2, o, b(x,o,x, e,e,e, e,e,e)) setPosBoard(OldB, N, X, NewB) :- OldB =.. [H|L1], setPosition(L1, N, X, L2), NewB =.. [H|L2]. % Changing value in a certain location of a list % For example setPosition([x,e,x, ...], 2, o, [x,o,x, ...]) setPosition([_|L], 1, X, [X|L]). setPosition([H|L1], N, X, [H|L2]):- N > 1, !, N1 is N-1, setPosition(L1, N1, X, L2). % A move by X player nextX(OldB, NewB):- getXPosition(N), % ask user where to play checkPosition(OldB, N),!, % make sure it is an empty position setPosBoard(OldB, N, x, NewB). % set the board position to x nextX(OldB, NewB):- % if not empty, ask for another position write('Not an empty board position!'), nl, nextX(OldB, NewB). % Ask user where to play getXPosition(N):- repeat, write('Enter a position (1-9): '), read(N), integer(N), N > 0, N <10, !. % Make sure the position on board is empty checkPosition(B, N) :- arg(N, B, X), % get position N on board X = e. % check if it is e % A move by O player, let's assume random play nextO(OldB, NewB):- repeat, N is random(10), % choose a random location 1-9 checkPosition(OldB, N),!, % make sure it is empty setPosBoard(OldB, N, o, NewB). % set the board position to o % some predicates to help make the code shorter! next(x, OldB, NewB) :- nextX(OldB, NewB). next(o, OldB, NewB) :- nextO(OldB, NewB). nextPlayer(x,o). nextPlayer(o,x). % Lines on the board line( b(X,Y,Z, _,_,_, _,_,_), X, Y, Z). line( b(_,_,_, X,Y,Z, _,_,_), X, Y, Z). line( b(_,_,_, _,_,_, X,Y,Z), X, Y, Z). line( b(X,_,_, Y,_,_, Z,_,_), X, Y, Z). line( b(_,X,_, _,Y,_, _,Z,_), X, Y, Z). line( b(_,_,X, _,_,Y, _,_,Z), X, Y, Z). line( b(X,_,_, _,Y,_, _,_,Z), X, Y, Z). line( b(_,_,X, _,Y,_, Z,_,_), X, Y, Z). % winning values win(x,x,x). win(o,o,o). % game is over, if there is a line on board with winning values, % otherwise go ahead with next player gameover(B, X):- line(B, X,Y,Z), win(X,Y,Z),!, write('Hooray! '), write(X), write(' wins!!!'), nl, fail. gameover(B, X):- nextPlayer(X,Y), tic(B, Y). % check to see if there are any empty positions on board hasempty(B) :- B=..[_|L], member(e,L). % start the game with an empty board go:- tic(b(e,e,e, e,e,e, e,e,e), x). tic(B, _):- \+hasempty(B), !, write('No winners!'), nl. tic(B, X):- write('Next player: '), write(X), nl, next(X, B, NewB), showBoard(NewB), gameover(NewB, X). % if we want a more intelligent o player :) %forced_move(Board):- line(Board, X,Y,Z), threatening(X,Y,Z), !. %threatening(e,x,x). %threatening(x,e,x). %threatening(x,x,e).