The Knight’s Tour

Written by

in

One of my favorite problems when I try new programming languages is the Knight’s Tour. The goal is to move a knight on a chess board in a way that each square of the chess board is visited exactly once. The naive approach is to use simple backtracing, but a better way was found in the 19th century by H. C. Warnsdorff. This is an implementation of his algorithm. I hope the Lisp code is not too embarassing.

(defun start-tour (position)
(let ((board (make-array '(8 8))))
(move position board 1)))

(defun move (position board n)
(setf (aref board (car position) (cadr position)) n)
;;  (print-board board)
;;  (print (evaluate-possible-moves position board))
;;  (format t "~%")
(cond ((= n 64) (print-board board))
((null (possible-moves position board)) 'failed-dead-end)
((< n 64) (move (best-move position board) board (+ n 1)))))

(defun best-move (position board)
(car (evaluate-possible-moves position board)))

(defun evaluate-possible-moves (position board)
;;  (print position)
;;  (format t "~%")
(sort (mapcar #'(lambda (x) (append x (list (length (possible-moves x board)))))
(possible-moves position board))
#'(lambda (triple-a triple-b) (< (caddr triple-a) (caddr triple-b)))))

(defun print-board (board)
(do ((x 0 (+ x 1)))
((= x 8))
(do ((y 0 (+ y 1)))
((= y 8))
(format t "~2D " (aref board x y)))
(format t "~%"))
(format t "~%"))

(defun on-board-p (position)
(and (>= (car position) 0)
(<= (car position) 7)
(>= (cadr position) 0)
(<= (cadr position) 7)))

(defun visited-p (position board)
(> (aref board (car position) (cadr position)) 0))

(defun possible-moves (position board)
(remove-if #'(lambda (x) (visited-p x board)) (moves position)))

(defun moves (position)
(let ((x (car position))
(y (cadr position)))
(remove-if-not #'on-board-p
`((,(+ x 1) ,(+ y 2))
(,(+ x 1) ,(- y 2))
(,(- x 1) ,(+ y 2))
(,(- x 1) ,(- y 2))
(,(+ x 2) ,(+ y 1))
(,(+ x 2) ,(- y 1))
(,(- x 2) ,(+ y 1))
(,(- x 2) ,(- y 1))))))

Comments

62 responses to “The Knight’s Tour”

  1. mokona Avatar
    mokona

    Hi Neingeist!
    I’m really hope you can explain to me this code…this is my first time seeing knight tour in lisp…

  2. neingeist Avatar

    what would you like to know about it?

    +++ neingeist

  3. Mokona Avatar
    Mokona

    Did u use Warndorff’s heuristic when u built up this code? Sorry i’m really new in lisp

  4. maxis Avatar
    maxis

    how do i run the lisp?

  5. guuya Avatar
    guuya

    Your code is good Neingeist. I’ve complied n load it but then i got some problem when i run it. i typed (start-tour ‘(1 5)). can you please explain how to run it.

  6. chooyee Avatar
    chooyee

    hey friend, nice job there. btw, i am having the same problem when i typed (start-tour ‘(1 5)). Can you help me out on this?

  7. alesi Avatar
    alesi

    hi there, i have a prob of to run d program, i already compile and load the file but when i typed (start-tour ‘(3 4)) i can’t executed it. Please guide me anyone

  8. neingeist Avatar

    my code seems to have problems with clisp. which lisp compiler are you using?

    +++ neingeist

  9. guuya Avatar
    guuya

    i’m using allegro cl ver 7.0

  10. neingeist Avatar

    try replacing (make-array ‘(8 8)) with (make-array ‘(8 8) :initial-element 0)!

    at least that fixes problems with clisp due to the uninitialised board.

    +++ neingeist

  11. alesi Avatar
    alesi

    its work !! Thanks a lot for the changes. I have another doubts for the code, u declare 2 move function , can u plz explain bit specifiy coz i need to know all about the code flow btw

  12. neingeist Avatar

    2 move functions? there are somewhat different functions here:

    move: moves to the best-possible position (using best-move)
    best-move: gives the best-possible position (using evaluate-possible-moves)
    evaluate-possible-moves: evaluates the possible moves using Warndorff’s heuristic (using possible-moves)

    and finally:

    moves: gives all moves for a knight from the position
    possible-moves: gives all moves that lead to a position not visited before (using visited-p)

  13. dave o'neal Avatar
    dave o’neal

    hi there, i have a prob of to run d program, i already compile and load the file but when i try to run it by gvn a value for start-tour ‘ x y then it didn’t execute instead promted me an error mesage saying that move undefine .Please guide me anyone

  14. neingeist Avatar

    @dave:

    what error _exactly_ in which compiler?

    +++ neingeist

  15. Mokona Avatar
    Mokona

    Thanks neingeist!!
    Your work is really awsome & marvellous. Way to go ^^

  16. john Avatar
    john

    I m using using allegro cl ver 7.0 oso but when i run with typing (start-tour ‘(3 4)) it oso can’t work. can you plz tell me why? thanks

  17. kelvin Avatar
    kelvin

    hi,neingeist.
    i using allegro cl ver 6.2.
    when i compiler, i got a error said that >. Actually the error is under “defun move” function.

    thanks for help.

  18. kelvin Avatar
    kelvin

    hi,neingeist.
    i using allegro cl ver 6.2.
    when i compiler, i got a error said that (comma not inside a backquote. [file position = 1436]). Actually the error is under “defun move” function.

    thanks for help.

  19. Tom Pyros, Jr. Avatar
    Tom Pyros, Jr.

    Tom Pyros is a student from MMU.

  20. neingeist Avatar

    @kelvin:
    did you copy the code exactly? there is a backquote in the “moves”-function:

    `((,(+ x 1) ,(+ y 2))

    +++ neingeist

  21. Grant Palmer Avatar
    Grant Palmer

    Dave , kelvin , Sau Pei la…so easy oso wan to aask…MMu got this kind of student , really embarassing oh!!!~~ walao…nya sing…

  22. Fred Avatar
    Fred

    Hi Neingeist!

    What do triple-a and triple-b represent in the lambda function ?

    Thanks

  23. Jasper Avatar
    Jasper

    what about is the different btw on-board-p and visited-p ?

  24. Fred Avatar
    Fred

    The difference between on-board-p and visited-p:

    [1] on-board-p checks for the range of the rows and columns of the board. Note the 0 – 7 for both rows and columns.

    [2] visited-p is a straigtforward function to checks if a particular cell has been visited once and only once.

  25. Jasper Avatar
    Jasper

    Thx for explaining Fred. i also wondering about the triple-a and triple-b variables

  26. neingeist Avatar

    @fred+jasper:

    the mapcar in evaluate-possible-moves appends the number of possible moves to a position (that’s basically warndorff’s heuristic).

    (mapcar #'(lambda (x) (append x (list (length (possible-moves x board)))))
    (possible-moves position board))

    so if we had a position on the board, let’s say ‘(4 5) and we could move to 3 other positions from that position, this triple gets ‘(4 5 3).

    the sort sorts by this third number (= caddr). that’s how we find out where to move next: we just move the knight to the position where we have the smallest possibility to getting back to again (best-move).

    +++ neingeist

  27. baby Avatar
    baby

    Where to download the code?

  28. Fred Avatar
    Fred

    @baby:

    You do not have the option to download the code since there is no link to it.All you need to do is, if your are desperate enough to submit your assignment in few days time, just copy the whole code listing and submit it as your own work for your AI assignment.(only if you do not observe the academic integrity) LOL

    cheers 🙂

  29. fms Avatar
    fms

    i have problem on excuting this code. The code seemed fine but i cant excute it. Can u help me on this since i am desperate to learn this code. Thank u

  30. neingeist Avatar

    @fms:

    what exactly is your problem? did it load and compile? did a

    (start-tour ‘(3 4))

    work?

    +++ neingeist

  31. Ray Avatar
    Ray

    What do the commas represent in the moves function ? Anybody care to explain ?

  32. neingeist Avatar

    @ray:

    it’s part of a backquote form:

    http://www.lisp.org/HyperSpec/Body/sec_2-4-6.html

    +++ neingeist

  33. fms Avatar
    fms

    (start-tour ‘(3 4)) doesnt work..

    CG-USER(5): (start-tour ‘(3 4))
    Error: attempt to call `MOVE’ which is an undefined function.

    this is what the compiler said..

    so what is the problem here? pls help.. thank u

  34. neingeist Avatar

    @fms:

    well, you should really try to load+compile the whole code first, before running it. maybe get used to lisp a little bit?

    +++ neingeist

  35. Ray Avatar
    Ray

    It is most likely that those who are complaining the program is not running properly, don’t even know how to complie the LISP code.

  36. fms Avatar
    fms

    allrite..thank u anyway

  37. papejerk Avatar
    papejerk

    >

    ermm… then why u didn’t teach us how to compile it…

  38. hizperion Avatar
    hizperion

    O_o

    just (load “c:/tehpwnagedirectory/filename.lisp”) in allegro.

    but..i have this
    Error: :INITIAL-ELEMENT is an illegal dimension
    [condition type: SIMPLE-ERROR]
    error after initializing zero and i still can’t run the code. can you help? :p

  39. hizperion Avatar
    hizperion

    oh, you have to put :element-type ‘integer in too. great job and thanks ! ^_^

  40. somnuk Avatar

    dear mmu students,

    i know this is a good resource, use it strictly as reference, thank you.
    Neingeist, good work!

  41. angel Avatar
    angel

    Nice job..i did try to run the program but i get this Error: `NIL’ is not of the expected type `REAL’

    Can you help me to fix it..thankz

  42. neingeist Avatar

    @angel:

    please see my previous comment about “make-array”.

    +++ neingeist

  43. craper Avatar
    craper

    hey Grant Palmer, wats wrong wit u pal…
    u think ur one big head issit!!
    first of all try learn sum basic manners plz..a.h.
    i gues u r stupid enuf to expose ur ppl identity!

  44. angel Avatar
    angel

    Thankz neingeist but it still shows me error after i change the (make array).The error is Error: Attempt to take the value of the unbound variable `BOARD’

  45. redrose Avatar

    how to change the above code to hueristic function?

  46. crashdude Avatar

    suddently this is the best site of the semester! LOL! Thanks mr. neingeist ! Youre our savior! 😛

  47. Angel Avatar
    Angel

    After change the make array still got error.
    CG-USER(2): (START-TOUR ‘(X Y))
    Error: attempt to call `MOVE’ which is an undefined function.
    [condition type: UNDEFINED-FUNCTION]

    How to fix this. Thank you for your kindness.

  48. Angel Avatar
    Angel

    I using allegro 6.2.

  49. vilimili Avatar

    i have another code

    go:-go(5).

    go(N):-
    time(_),
    make_board(N,Board,NbMoves),
    knight(NbMoves,1,1,N,Board),!,
    time(T),
    nl,write(‘BMARK_fknight’=[time(T),’N’=N]
    ),nl,
    statistics,show(N,Board).

    make_board(N,Board,M):-
    M is N*N,
    functor(Line,line,N),
    findall(Line,range(_,1,N),LBoard),

    go:-go(5).

    go(N):-
    time(_),
    make_board(N,Board,NbMoves),
    knight(NbMoves,1,1,N,Board),!,
    time(T),
    nl,write(‘BMARK_fknight’=[time(T),’N’=N]
    ),nl,
    statistics,show(N,Board).

    make_board(N,Board,M):-
    M is N*N,
    functor(Line,line,N),
    findall(Line,range(_,1,N),LBoard),
    Board=..[board|LBoard].

    val(I,J,Val,N,Board):-
    I>0,I=0,J=nl;true),
    fail.
    show(_,_):-nl.

    move( 2, 1).
    move( 2,-1).
    move(-2, 1).
    move(-2,-1).
    move( 1, 2).
    move(-1, 2).
    move( 1,-2).
    move(-1,-2).

    time(T) :- statistics(runtime,[_,T]).

  50. simson_yeoh Avatar

    i have another version as well 🙂

    (defun valid-coord (c)
    (and (>= c 1) (

Leave a Reply

Your email address will not be published. Required fields are marked *