 


Task

Implement the Fifteen Puzzle Game.



The   15-puzzle   is also known as:

   Fifteen Puzzle
   Gem Puzzle
   Boss Puzzle
   Game of Fifteen
   Mystic Square
   14-15 Puzzle
   and some others.


Related Tasks

   15 Puzzle Solver
   16 Puzzle Game


 
 import util.
 
main =>
    Board = {{1,2,3,4},
             {5,6,7,8},
             {9,10,11,12},
             {13,14,15,0}},
    Goal = copy_term(Board),
    shuffle(Board),
    play(Board,Goal).
 
shuffle(Board) =>
    foreach (_ in 1..1000)
        R1 = random() mod 4 + 1,
        C1 = random() mod 4 + 1,
        R2 = random() mod 4 + 1,
        C2 = random() mod 4 + 1,
        T := Board[R1,C1],
        Board[R1,C1] := Board[R2,C2],
        Board[R2,C2] := T
    end.
 
play(Board,Goal) =>
    while (Board != Goal)
        print_board(Board),
        possible_moves(Board,R0,C0,Moves),
        printf("Possible moves are: %w, 0 to exit. Your move? =>  ", Moves),
        S = read_line().strip(),
        if S == "0" || S == "" then
            halt
        else
            move_hole(Board,R0,C0,to_int(S))
        end
    end,
    print_board(Board),
    println("Puzzle solved.").
 
print_board(Board) =>
    N = len(Board),
    print("+----+----+----+----+\n"),
    foreach (R in 1..N)
        print("|"),
        foreach (C in 1..N)
            printf("%4d|", Board[R,C])
        end,
        nl
    end,
    println("+----+----+----+----+").
 
possible_moves(Board,R0,C0,Moves) =>
    N = len(Board),
    between(1,N,R0),
    between(1,N,C0),
    Board[R0,C0] == 0, !,
    NeibsOfHole = [(R1,C1) : (R1,C1) in [(R0-1,C0), (R0+1,C0), (R0,C0-1), (R0,C0+1)], R1 >= 1, R1 =< N, C1 >= 1, C1 =< N],
    Moves = sort([Board[R,C] : (R,C) in NeibsOfHole]).
 
move_hole(Board,R0,C0,S) =>
    N = len(Board),
    between(1,N,R),
    between(1,N,C),
    Board[R,C] == S, !,
    Board[R0,C0] := S,
    Board[R,C] := 0.
 