; .EnTete "Le-Lisp (c) version 15.2" " " "Les Tours de Hanoi" ; .EnPied " " "%" " " ; .Chapitre 10 "Les Tours de Hanoi Anime'es" ; ; .Centre "*****************************************************************" ; .Centre " Ce fichier est en lecture seule hors du projet ALE de l'INRIA. " ; .Centre " Il est maintenu par ILOG SA, 2 Avenue Gallie'ni, 94250 Gentilly " ; .Centre " (c) Le-Lisp est une marque de'pose'e de l'INRIA " ; .Centre "*****************************************************************" ; .Centre "$Header: whanoi.ll,v 4.1 88/01/13 12:25:18 kuczynsk Rel $" (unless (>= (version) 15.2) (error 'load 'erricf 'whanoi)) ; Tous les symboles pre'ce'de's de : seront cre'e's ; dans le package WHANOI. (defvar #:sys-package:colon 'whanoi) ; Ce programme, qui simule e'galement une tour de Hanoi, ; utilise les possibilite's d'affichage asynchrone ; du syste`me Le←Lisp (redisplayscreen). ;---- De'finition des objets globaux (defvar :nsdpy 0) ; pour les statistiques sur "redisplayscreen" ;---- Fonctions auxiliaires (dmd :coord (x y) ; calcule les :coordonne'es du point <x> <y> `(+ (* (1+ (tyxmax)) ,y) ,x)) (de :redisplay () ; re:affiche le nouvel e'cran (redisplayscreen nscreen oscreen (1+ (tyxmax)) (1+ (tyymax))) (tyflush)) (dmd :fillxy (x y string) ; remplit <nscreen> a` partir de <x> <y> avec <string> `(bltstring nscreen (:coord ,x ,y) ,string)) (de :nieme-disque (n) ; retourne la chai↑ne du <n>ie`me disque (vref #[" | " " *|* " " **|** " " ***|*** " " ****|**** " " *****|***** " " ******|****** " " *******|******* " " ********|******** " " *********|********* " "=====================" " "] n)) ;---- Les fonctions principales (de whanoi n ; pour mesurer la rapidite' du "redisplayscreen" (let ((rt (runtime)) (:nsdpy 0)) (:hanoi n) (print "Nb de redisplayscreen : " :nsdpy) (print "temps total : " (setq rt (differ (runtime) rt))) (print "temps moyen : " (/ rt :nsdpy)))))))) (de :hanoi (n) (if (consp n) (setq n (car n)) (print "Combien de disque ") (setq n (read))) (unless (and (numberp n) (> n 0) (< n 10)) (error 'whanoi 'erroob n)) (let ((oscreen (makestring (:coord 0 (1+ (tyymax))) #\sp)) (nscreen (makestring (:coord 0 (1+ (tyymax))) #\sp))) (typrologue) (tycls) (let ((a1 '(10)) ; contenu de la 1e`re aiguille (a2 '(10)) ; contenu de la 2e`me aiguille (a3 '(10)) ; contenu de la 3e`me aiguille (nmv 0)) ; nombre de mouvements (putprop 'a1 2 'pos) (putprop 'a2 27 'pos) (putprop 'a3 52 'pos) (let ((n n)) (repeat n (newl a1 n) (decr n))) (let ((s "Les Tours de Hanoi")) (for (i 0 1 (sub1 (slen s))) (sset s i (logor #$80 (sref s i)))) (:fillxy 28 1 s)) (:affiche 'a1) (:affiche 'a2) (:affiche 'a3) (:redisplay) (incr :nsdpy) (:moteur n 'a1 'a3 'a2) (tycursor 0 (tyymax)) (tyflush) ':hanoi))) (de :moteur (n dep arr int) (when (> n 0) (:moteur (1- n) dep int arr) (:bouge n dep arr) (:moteur (1- n) int arr dep)))) (de :bouge (n dep arr) (:fillxy 18 4 (incr nmv)) (:fillxy 20 4 " : je bouge le disque ") (:fillxy 42 4 n) (:fillxy 44 4 " de ") (:fillxy 48 4 dep) (:fillxy 50 4 " vers ") (:fillxy 56 4 arr) (:monte n (getprop dep 'pos) (- 10 (length (eval dep)))) (:avance n (getprop dep 'pos) (getprop arr 'pos)) (:descend n (getprop arr 'pos) (- 10 (length (eval arr)))) (set dep (cdr (eval dep))) (set arr (cons n (eval arr)))))) ;----- La fonction d'affichage (de :affiche (a) ; :affiche toute l'aiguille "a" (let ((y 21) (l (reverse (eval a))) (x (getprop a 'pos))) (repeat 10 (:fillxy x (decr y) (:nieme-disque (or (nextl l) 0)))) (:fillxy (+ x 10) 21 a))) ;----- Les fonctions de mouvement de disque (de :monte (n x nb) ; disque "n" en "x" "nb" fois (let ((y (+ nb 10))) (repeat (1+ nb) (:fillxy x y (:nieme-disque n)) (:fillxy x (1+ y) (:nieme-disque 0)) (:redisplay) (incr :nsdpy) (decr y)))))))))) (de :descend (n x nb) ; disque "n" en "x" "nb" fois (let ((y 11)) (:fillxy x 10 (:nieme-disque 11)) (repeat (1- nb) (:fillxy x y (:nieme-disque 0)) (:fillxy x (incr y) (:nieme-disque n)) (:redisplay) (incr :nsdpy)))))) (de :avance (n x1 x2) ; :avance horizontalement le disque "n" de "x1" vers "x2" (if (> x1 x2) (repeat (- x1 x2) (:fillxy (decr x1) 10 (:nieme-disque n)) (:redisplay) (incr :nsdpy))) (repeat (- x2 x1) (:fillxy (incr x1) 10 (:nieme-disque n)) (:redisplay) (incr :nsdpy)))))) ;----- Pour re'cuperer la place occupe'e par WHANOI (de whanoiend () (mapc 'remob (oblist '#.#:sys-package:colon)) (libautoload whanoi whanoi) 'whanoiend)