How to resolve the algorithm Tic-tac-toe step by step in the Prolog programming language
Published on 12 May 2024 09:40 PM
How to resolve the algorithm Tic-tac-toe step by step in the Prolog programming language
Table of Contents
Problem Statement
Play a game of tic-tac-toe. Ensure that legal moves are played and that a winning position is notified.
Tic-tac-toe is also known as:
Let's start with the solution:
Step by Step solution about How to resolve the algorithm Tic-tac-toe step by step in the Prolog programming language
Source code in the prolog programming language
:- use_module('min-max.pl').
:-dynamic box/2.
:- dynamic tic_tac_toe_window/1.
% Computer begins.
tic-tac-toe(computer) :-
V is random(9),
TTT = [_,_,_,_,_,_ ,_,_,_],
nth0(V, TTT, o),
display_tic_tac_toe(TTT).
% Player begins
tic-tac-toe(me) :-
TTT = [_,_,_,_,_,_ ,_,_,_],
display_tic_tac_toe(TTT).
display_tic_tac_toe(TTT) :-
retractall(box(_,_)),
retractall(tic_tac_toe_window(_)),
new(D, window('Tic-tac-Toe')),
send(D, size, size(170,170)),
X = 10, Y = 10,
display(D, X, Y, 0, TTT),
assert(tic_tac_toe_window(D)),
send(D, open).
display(_, _, _, _, []).
display(D, X, Y, N, [A,B,C|R]) :-
display_line(D, X, Y, N, [A,B,C]),
Y1 is Y+50,
N3 is N+3,
display(D, X, Y1, N3, R).
display_line(_, _, _, _, []).
display_line(D, X, Y, N, [C|R]) :-
( nonvar(C)-> C1 = C; C1 = ' '),
new(B, tic_tac_toe_box(C1)),
assertz(box(N, B)),
send(D, display, B, point(X, Y)),
X1 is X + 50,
N1 is N+1,
display_line(D, X1, Y, N1, R).
% class tic_tac_toe_box
% display an 'x' when the player clicks
% display an 'o' when the computer plays
:- pce_begin_class(tic_tac_toe_box, box, "Graphical window with text").
variable(mess, any, both, "text to display").
initialise(P, Lbl) :->
send(P, send_super, initialise),
send(P, slot, mess, Lbl),
WS = 50, HS = 50,
send(P, size, size(WS,HS)),
send(P, recogniser,
handler_group(new(click_gesture(left,
'',
single,
message(@receiver, my_click))))).
% the box is clicked
my_click(B) :->
send(B, set_val, x),
send(@prolog, play).
% only works when the box is "free"
set_val(B, Val) :->
get(B, slot, mess, ' '),
send(B, slot, mess, Val),
send(B, redraw),
send(B, flush).
% redefined method to display custom graphical objects.
'_redraw_area'(P, A:area) :->
send(P, send_super, '_redraw_area', A),
%we display the text
get(P, slot, mess, Lbl),
new(Str1, string(Lbl)),
get_object(P, area, area(X,Y,W,H)),
send(P, draw_box, X, Y, W, H),
send(P, draw_text, Str1,
font(times, normal, 30),
X, Y, W, H, center, center).
:- pce_end_class.
play :-
numlist(0, 8, L),
maplist(init, L, TTT),
finished(x, TTT, Val),
( Val = 2 -> send(@display, inform,'You win !'),
tic_tac_toe_window(D),
send(D, destroy)
; ( Val = 1 -> send(@display, inform,'Draw !'),
tic_tac_toe_window(D),
send(D, destroy)
; next_move(TTT, TT1),
maplist(display, L, TT1),
finished(o, TT1, V),
( V = 2 -> send(@display, inform,'I win !'),
tic_tac_toe_window(D),
send(D, destroy)
; ( V = 1 -> send(@display, inform,'Draw !'),
tic_tac_toe_window(D),
send(D, destroy)
; true)))).
% use minmax to compute the next move
next_move(TTT, TT1) :-
minimax(o, 0, 1024, TTT, _V1- TT1).
% we display the new board
display(I, V) :-
nonvar(V),
box(I, V1),
send(V1, set_val, V).
display(_I, _V).
% we create the board for minmax
init(I, V) :-
box(I, V1),
get(V1, slot, mess, V),
V \= ' '.
init(_I, _V).
% winning position for the player P ?
winned(P, [A1, A2, A3, A4, A5, A6, A7, A8, A9]) :-
(is_winning_line(P, [A1, A2, A3]);
is_winning_line(P, [A4, A5, A6]);
is_winning_line(P, [A7, A8, A9]);
is_winning_line(P, [A1, A4, A7]);
is_winning_line(P, [A2 ,A5, A8]);
is_winning_line(P, [A3, A6, A9]);
is_winning_line(P, [A1, A5, A9]);
is_winning_line(P, [A3, A5, A7])).
is_winning_line(P, [A, B, C]) :-
nonvar(A), A = P,
nonvar(B), B = P,
nonvar(C), C = P.
% Winning position for the player
eval(Player, Deep, TTT, V) :-
winned(Player, TTT),
( Player = o -> V is 1000 - 50 * Deep; V is -1000+ 50 * Deep).
% Loosing position for the player
eval(Player, Deep, TTT, V) :-
select(Player, [o,x], [Player1]),
winned(Player1, TTT),
( Player = x -> V is 1000 - 50 * Deep; V is -1000+ 50 * Deep).
% Draw position
eval(_Player, _Deep, TTT, 0) :-
include(var, TTT, []).
% we fetch the free positions of the board
possible_move(TTT, LMove) :-
new(C, chain),
forall(between(0,8, I),
( nth0(I, TTT, X),
( var(X) -> send(C, append, I); true))),
chain_list(C, LMove).
% we create the new position when the player P clicks
% the box "N"
assign_move(P, TTT, N, TT1) :-
copy_term(TTT, TT1),
nth0(N, TT1, P).
% We fetch all the possible boards obtained from board TTT
% for the player P
get_next(Player, Deep, TTT, Player1, Deep1, L):-
possible_move(TTT, LMove),
select(Player, [o,x], [Player1]),
Deep1 is Deep + 1,
maplist(assign_move(Player, TTT), LMove, L).
% The game is over ?
% Player P wins
finished(P, TTT, 2) :-
winned(P, TTT).
% Draw
finished(_P, TTT, 1) :-
include(var, TTT, []).
% the game is not over
finished(_P, _TTT, 0) .
% minmax must knows when the computer plays
% (o for ordinateur in French)
computer(o).
:- module('min-max.pl', [minimax/5]).
% minimax(Player, Deep, MaxDeep, B, V-B)
% @arg1 : current player at this level
% @arg2 : current level of recursion
% @arg3 : max level of recursion (in this version of the game no use : set to 1024 !)
% @arg4 : current board
% @arg5 : B is the evaluation of the board, the result is V-B to know the new board
% Here we get an evaluation
minimax(Player, Deep, MaxDeep, B, V-B) :-
( eval(Player, Deep, B, V) -> true
; % in this version of the game this second division always fails
( Deep > MaxDeep -> V is random(1000) - 1000)).
% here we must compute all the possible moves to know the evaluation of the board
minimax(Player, Deep, MaxDeep, B, V) :-
get_next(Player, Deep, B, Player1, Deep1, L),
maplist(minimax(Player1, Deep1, MaxDeep), L, LV),
maplist(lie, L, LV, TLV),
sort(TLV, SLVTmp),
( computer(Player) -> reverse(SLVTmp, SLV); SLV = SLVTmp),
SLV = [V | _R].
lie(TTT, V-_, V-TTT).
You may also check:How to resolve the algorithm Count the coins step by step in the REXX programming language
You may also check:How to resolve the algorithm Rhonda numbers step by step in the ALGOL 68 programming language
You may also check:How to resolve the algorithm Playing cards step by step in the Forth programming language
You may also check:How to resolve the algorithm Thue-Morse step by step in the C++ programming language
You may also check:How to resolve the algorithm Word wheel step by step in the Nim programming language