
%999 represent Blank tile.
goal([999,0,1, 2,3,4, 5,6,7]).
%To move left in any row ther are two cases:
%Case_1: Blank tile in the second index.
%Case_2: Blank tile in the third index.
% move left in the top row
move([X0,999,X2, X3,X4,X5, X6,X7,X8],
[999,X0,X2, X3,X4,X5, X6,X7,X8]). %second
move([X0,X1,999, X3,X4,X5, X6,X7,X8],
[X0,999,X1, X3,X4,X5, X6,X7,X8]). %third
% move left in the middle row
move([X0,X1,X2, X3,999,X5, X6,X7,X8],
[X0,X1,X2, 999,X3,X5, X6,X7,X8]). %second
move([X0,X1,X2, X3,X4,999, X6,X7,X8]
,[X0,X1,X2, X3,999,X4, X6,X7,X8]). %third
% move left in the bottom row
move([X0,X1,X2, X3,X4,X5, X6,999,X8],
[X0,X1,X2, X3,X4,X5, 999,X6,X8]). %second
move([X0,X1,X2, X3,X4,X5, X6,X7,999],
[X0,X1,X2, X3,X4,X5, X6,999,X7]). %third
% To move right in any row there are two cases:
% Case_1: 999 tile in the first index.
% Case_2: 999 tile in the second index.
% move right in the top row
move([999,X1,X2, X3,X4,X5, X6,X7,X8],
[X1,999,X2, X3,X4,X5, X6,X7,X8]). %first
move([X0,999,X2, X3,X4,X5, X6,X7,X8],
[X0,X2,999, X3,X4,X5, X6,X7,X8]). %seond
%% move right in the middle row
move([X0,X1,X2, 999,X4,X5, X6,X7,X8],
[X0,X1,X2, X4,999,X5, X6,X7,X8]). %first
move([X0,X1,X2, X3,999,X5, X6,X7,X8],
[X0,X1,X2, X3,X5,999,X6,X7,X8]). %second
%% move right in the bottom row
move([X0,X1,X2, X3,X4,X5, 999,X7,X8],
[X0,X1,X2, X3,X4,X5, X7,999,X8]). %first
move([X0,X1,X2, X3,X4,X5, X6,999,X8],
[X0,X1,X2, X3,X4,X5, X6,X8,999]). %second
%It is not possible to move up when existing in the top row.
% so, moving up will only be possible from bottom and middle rows from
% the three indecies.
%% move up from the middle row
move([X0,X1,X2, 999,X4,X5, X6,X7,X8],
[999,X1,X2, X0,X4,X5, X6,X7,X8]). %first
move([X0,X1,X2, X3,999,X5, X6,X7,X8],
[X0,999,X2, X3,X1,X5, X6,X7,X8]). %second
move([X0,X1,X2, X3,X4,999, X6,X7,X8],
[X0,X1,999, X3,X4,X2, X6,X7,X8]). %third
%% move up from the bottom row
move([X0,X1,X2, X3,X4,X5, 999,X7,X8],
[X0,X1,X2, 999,X4,X5, X3,X7,X8]). %first
move([X0,X1,X2, X3,X4,X5, X6,999,X8],
[X0,X1,X2, X3,999,X5, X6,X4,X8]). %second
move([X0,X1,X2, X3,X4,X5, X6,X7,999],
[X0,X1,X2, X3,X4,999, X6,X7,X5]). %third
% moving down only from the middle and top rows from the three
% indicies.
% move down from the top row
move([999,X1,X2, X3,X4,X5, X6,X7,X8],
[X3,X1,X2, 999,X4,X5, X6,X7,X8]). %first
move([X0,999,X2, X3,X4,X5, X6,X7,X8],
[X0,X4,X2, X3,999,X5, X6,X7,X8]). %second
move([X0,X1,999, X3,X4,X5, X6,X7,X8],
[X0,X1,X5, X3,X4,999, X6,X7,X8]). %third
%% move down from the middle row
move([X0,X1,X2, 999,X4,X5, X6,X7,X8],
[X0,X1,X2, X6,X4,X5, 999,X7,X8]). %first
move([X0,X1,X2, X3,999,X5, X6,X7,X8],
[X0,X1,X2, X3,X7,X5, X6,999,X8]). %second
move([X0,X1,X2, X3,X4,999, X6,X7,X8],
[X0,X1,X2, X3,X4,X8, X6,X7,999]). %third
dfs(S, Path, Path) :-
goal(S),!.
dfs(S, Checked, Path) :-
% try a move
move(S, S2),
% ensure the resulting state is new
\+member(S2, Checked),
% and that this state leads to the goal
dfs(S2, [S2|Checked], Path).
%SS: state start
%SE: state end
%path(SS, Checked, MoveList):-
% move(SS, Snext),
% \+member(Snext, Checked),
% path(Snext,[Snext|Checked], [Snext, SS|MoveList]).
%path(_,_, MoveList):-
%output(MoveList).
% Printing
%output([]) :- nl.
%output([[A,B]|MoveList]) :-
% output(MoveList),
% write(B), write(' -> '), write(A), nl.
find :-
dfs([6,1,3 4,999,5, 7,2,0],_,_).
An alternative approach where the current "state" (representing the state of the board) in the search space is represented by matrix: a list of 3 lists. The positions in this matrix are given by column and row coordinates, each ranging from 0 to 2:
If a matrix position shall represent the "empty cell", we write empty list at that position (because it looks nice), otherwise we write one of the integers 0..7
And so: