简体   繁体   中英

Solving the Numberlink puzzle with prolog

I have an assignment that seems out of scope of my class (I say this because they barely taught us anything about prolog), I have to write a prolog program to solve the game "Flow Free" on android. In the assignment it is called Numberlink. I could solve this in C++ in a hour but because I'm not too familiar with prolog it is giving me trouble. Here's what I would like to do:

  1. Make a list that holds a boolean to indicate whether it has been visited or used.
  2. Recursively search all possible paths from a given starting point to the end point using a breadth first search to find the shortest paths.
  3. Go from there I guess.

My attempt included searching the web on how to make a list. Of course prolog is not documented well at all anywhere so I came up blank and gave up. A friend told me to use maplist which I don't understand how I would use it to make a list including what I need.

Thanks in advance.

EDIT: Thanks for the link, but I was looking to make a 2D list to represent the board being played on. Function would look like this:

makeList(size, list):-

Where size is an integer representing the size of one dimension in the square list ex. (7x7).

Here's an implementation of @CapelliC's solution. The code is self-explanatory. 2 blocks are connected if they are adjacent and have the same color, or adjacent to another connected block of the same color. (I used X and Y instead of row and column, it made writing the conditions at the end a little confusing.)

Solving in SWI-Prolog

在此输入图像描述

https://flowfreesolutions.com/solution/?game=flow&pack=green&set=5&level=1

connected(P1, P2, M, Visited) :-
    adjacent(P1, P2),
    maplist(dif(P2), Visited),
    color(P1, C, M),
    color(P2, C, M).
connected(P1, P2, M, Visited) :-
    adjacent(P1, P3),
    maplist(dif(P3), Visited),
    color(P1, C, M),
    color(P3, C, M),
    connected(P3, P2, M, [P3|Visited]).

adjacent(p(X,Y1), p(X,Y2)) :- Y2 is Y1+1.
adjacent(p(X,Y1), p(X,Y2)) :- Y2 is Y1-1.
adjacent(p(X1,Y), p(X2,Y)) :- X2 is X1+1.
adjacent(p(X1,Y), p(X2,Y)) :- X2 is X1-1.

color(p(X,Y), C, M) :-
    nth1(Y, M, R),
    nth1(X, R, C).

sol(M) :-
    M = [[1,_,_,_,1],
         [2,_,_,_,_],
         [3,4,_,4,_],
         [_,_,_,_,_],
         [3,2,5,_,5]],
    connected(p(1,1), p(5,1), M, [p(1,1)]),
    connected(p(1,2), p(2,5), M, [p(1,2)]),
    connected(p(1,3), p(1,5), M, [p(1,3)]),
    connected(p(2,3), p(4,3), M, [p(2,3)]),
    connected(p(3,5), p(5,5), M, [p(3,5)]).

Sample query:

?- sol(M).
M = [[1, 1, 1, 1, 1],
     [2, 2, 2, 2, 2], 
     [3, 4, 4, 4, 2],
     [3, 2, 2, 2, 2], 
     [3, 2, 5, 5, 5]].

The declarative Prolog 'modus operandi' is based on non determinism, implemented by depth first search. Let's apply to this puzzle: M is the playground, a list of lists of free cells (variables) or integers (colors)

one_step(M) :-
  cell(M, X,Y, C),
  integer(C), % the selected cell is a color
  delta(X,Y,X1,Y1),
  cell(M, X1,Y1, C). % bind adjacent to same color - must be free

cell(M, X,Y, C) :- nth1(Y,M,R), nth1(X,R,C).

% moves
delta(X,Y,X1,Y) :- X1 is X+1. % right
delta(X,Y,X1,Y) :- X1 is X-1. % left
delta(X,Y,X,Y1) :- Y1 is Y-1. % up
delta(X,Y,X,Y1) :- Y1 is Y+1. % down

what this does ? let's try on a 3x3 playground

?- M=[[_,9,_],[_,0,_],[_,_,9]],one_step(M).
M = [[_G1824, 9, 9], [_G1836, 0, _G1842], [_G1848, _G1851, 9]] ;
M = [[9, 9, _G1830], [_G1836, 0, _G1842], [_G1848, _G1851, 9]] ;
M = [[_G1824, 9, _G1830], [_G1836, 0, 0], [_G1848, _G1851, 9]] ;
M = [[_G1824, 9, _G1830], [0, 0, _G1842], [_G1848, _G1851, 9]] ;
M = [[_G1824, 9, _G1830], [_G1836, 0, _G1842], [_G1848, 0, 9]] ;
M = [[_G1824, 9, _G1830], [_G1836, 0, _G1842], [_G1848, 9, 9]] ;
M = [[_G1824, 9, _G1830], [_G1836, 0, 9], [_G1848, _G1851, 9]] ;
false.

No need to declare grid size, check index boundaries, etc... when one_step/1 succeeds it has instantiated a free cell to an adjacent same color...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM