1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373
| :- use_module(library(pce)).
% Pour ce programme j'ai besoin d'une frame avec deux renseignements complémentaires :
% ligne le nombre de lignes restantes dans la tablette
% colonne le nombre de ligne restantes dans la tablette
% la fonction de destructioon est modifiée de manière a effacer
% les données globales qui permettaient de mémoriser les boutons créés
:- pce_begin_class(my_frame, frame).
initialise(W, Label):->
send(W, send_super, initialise, Label).
destroy(W):->
send(W, send_super, free),
retractall(memo_button(_)).
variable(ligne, int, get, "ligne").
variable(colonne, int, get, "colonne").
:- pce_end_class.
% Pour ce programme j'ai besoin d'un box avec trois renseignements complémentaires :
% x sa position horizontale
% y sa position verticale
% l' id de la boîte (qui est différent du nom !)
:- pce_begin_class(my_box, box).
variable(id, any, get, "ID").
variable(x, int, get, "ligne").
variable(y, int, get, "colonne").
:- pce_end_class.
% Pour ce programme j'ai besoin d'un bouton avec deux renseignements
% complémentaires :
% ligne le numero de sa ligne
% colonne le numero de sa colonne
% l' id du bouton
:- pce_begin_class(my_button, button).
variable(id, any, get, "ID").
variable(ligne, int, get, "ligne").
variable(colonne, int, get, "colonne").
:- pce_end_class.
% Pour ce programme j'ai besoin d'une boîte de dialogue
% pour savoir qui commence
:- pce_begin_class(asker, dialog,
"Modal prompter for a response").
initialise(W, Label, Text) :->
"Initialise the window and fill it"::
send(W, send_super, initialise, Label),
send(W, append, text(Text)),
send(W, append, button(oui, message(W, return, 1))),
send(W, append, button(non, message(W, return ,0))),
send(W, default_button, oui).
prompt(W, Value:name) :<-
"Open it, destroy it and return the result"::
get(W, confirm, Value),
free(W).
:- pce_end_class.
:- dynamic
memo_button/1.
% ce prédicat permet de mémoriser les boutons pour pouvoir
% ensuite les retrouver,
% si les dialog_goup permettent de bien les afficher, on ne
% peut pas retrouver les éléments par leur noms ensuite
% d'où la mémorisation !!
memo_button(_).
% création de l'ID, ce doit être un atome et non pas une chaîne
create_ID(X, L, C, Name) :-
sformat(N, "~a~a~a", [X,L,C]),
string_to_atom(N, Name).
% modification de l'état des boutons de la ligne
% on passe le numero de colonne de debut et fin des modifs
modif_ligne_button(Colonne, Max, Active) :-
% on prend la liste des boutons
bagof(X, memo_button(X), Liste_Button),
forall(between(Colonne, Max, C),
( create_ID('l', 0, C, Name),
% ce prédicat permet de retrouver un control par son nom
get_control(Liste_Button, Name, Bouton),
% je modifie l'état du bouton
send(Bouton, active, Active))).
% modification de l'état des boutons de la colonne
% on passe le numero de ligne de debut et fin des modifs
modif_colonne_button(Ligne, Max, Active) :-
bagof(X, memo_button(X), Liste_Button),
forall(between(Ligne, Max, L),
( create_ID('c', L, 0, Name),
get_control(Liste_Button, Name, Bouton),
send(Bouton, active, Active))).
% Creation de la liste des boutons horizontaux
% Li est le nombre de boutons à construire (à partir de 0)
create_ligne_button(Li, D) :-
% pour tous les nombbres entre 0 et Li
forall(between(0, Li, L),
( % je cree l'ID du bouton
create_ID('l', 0, L, ID),
% J'envoie le message de création du bouton
send(D,
append,
new(X1,
% chaque bouton est dote
% d'une méthode ayant sa référence
% sa ligne et sa colonne comme arguments
% le code de la méthode est plus simple
my_button(' ',
message(@prolog,
mess,
@receiver,
@receiver?ligne,
@receiver?colonne)))),
% ce bouton est créé inactif
send(X1, active, @off),
% initialisation des trois "slots" ajoutés
send(X1, slot, id, ID),
send(X1, slot, ligne, 0),
send(X1, slot, colonne, L),
% Je mémorise ce bouton
assert(memo_button(X1)))).
% Creation de la liste des boutons verticaux
% Co est le nombre de boutons à construire (à partir de 0)
create_colonne_button(Co, D) :-
forall(between(0, Co, C),
( create_ID('c', C, 0, ID),
send(D,
append,
new(X1,
my_button(' ',
message(@prolog,
mess,
@receiver,
@receiver?ligne,
@receiver?colonne))),
% l'argument below est ajouté pour que le bouton soit en dessous
% du précédent
below),
send(X1, active, @off),
send(X1, slot, id, ID),
send(X1, slot, ligne, C),
send(X1, slot, colonne, 0),
assert(memo_button(X1)))).
% création d'un carré create_carre(+Ligne, +Colonne, -Carre)
create_carre(Ligne, Colonne, Carre) :-
% on crée l'ID du carre
create_ID('bx', Ligne, Colonne, ID),
% il est physiquement créé
new(Carre, my_box(80, 23)),
% On calcule ses coordonnées d'affichage
X is (Ligne + 1) * 33 + 10,
Y is (Colonne + 1) * 95 + 15,
% on mémorise les différents renseignements
send(Carre, slot, x, X),
send(Carre, slot, y, Y),
send(Carre, slot, id, ID).
% affichaged'un carré
affiche_un_carre(Carre, Couleur, Dialog) :-
% On affecte le carré à la boîte de dialogue
send(Dialog, display, Carre),
% On le remplit avec sa couleur
send(Carre, fill_pattern,colour(Couleur)),
% On va lire ses coordonnées d'affichage
get(Carre, slot, x, Li),
get(Carre, slot, y, Co),
% On le positionne
send(Carre, position, point(Co ,Li)).
% modification de l'affichage (de sa couleur) du carré
modifie_un_carre(Ligne, Colonne, Couleur, Dialog):-
% On créée le nom
create_ID('bx', Ligne, Colonne, Choc),
% On va le chercher dans la liste des carrés
get_un_chocolat(Dialog, Choc, Chocolat),
% On l'affiche
affiche_un_carre(Chocolat, Couleur, Dialog).
% Création du tableau des carrés de chocolats.
% ils sont "jaunes" au départ
create_carres(Li, Co, Dialog) :-
forall(between(0, Li, L),
( forall(between(0, Co, C),
(create_carre(L, C, Carre),
affiche_un_carre(Carre, yellow, Dialog))))),
% le premier carré est rouge
% C'est celui qu'il ne faut pas manger !
modifie_un_carre(0, 0, red, Dialog).
% Prédicat de recherche d'un control par son nom.
% Si la liste est vide on renvoie []
get_control([], _, []).
% Quand il est trouvé on s'arrète
get_control([Choc | _], Name, Choc) :-
get(Choc, slot, id, Name), !.
% Le premeier de la liste n'est pas bon
% on continue avec la suite.
get_control([_ | H], Name, Choc) :-
get_control(H, Name, Choc).
% Obtetion d'un carré de chocolat parmi tous
get_un_chocolat(Dialog, Name, Choc) :-
% On récupère la fenêtre mère de la boîte de dialogue
get(Dialog, frame, Frame),
% On obtient la liste PCE des ses membres
get(Frame, members, XD),
% je transforme cette liste en liste Prolog
chain_list(XD, [YD]),
% On recommence le même processus
get(YD, members, ZD),
% la liste des carrés de chocolats est
% le troisième élément de cette liste
chain_list(ZD, [_, _| Liste]),
% On va chercher le bon chocolat.
get_control(Liste, Name, Choc).
% Début de la partie : on demande qui veut commencer
demande(Button):-
get(asker('Jeu du chocolat','Voulez-vous commencer ?'), prompt, Reponse),
% obtention du nombre de lignes et colonnes
get(Button?frame, slot, ligne, NBL),
get(Button?frame, slot, colonne, NBC),
% on active tous les boutons
modif_ligne_button(0, NBC, @on) ,
modif_colonne_button(0, NBL, @on) ,
% et on inactive le bouton de démarrage de la partie
send(Button, active, @off),
% si on ne veut pas commencer, Reponse vaut 0
Reponse == 0,
% et alors c'est à l'ordianteur de jouer, dommage ...
play(Button, NBL, NBC).
init(NBL, NBC):-
% On nettoie la base de données de tout bouton
retractall(memo_button(_)),
% création de la fenêtre générale de l'appli
new(Frame,my_frame('Chocolat')),
% initialisation des "slots" ajoutés
send(Frame, slot, ligne, NBL),
send(Frame, slot, colonne, NBC),
% on doit insérer une boîte de dialogue dedans.
send(Frame, append, new(Dialog, dialog('D'))),
% J'insère dans le dialog un groupe de boutons horizontaux
send(Dialog, append, new(BTS, dialog_group(buttons, group))),
% je fixe l'écart entre les boutons
send(BTS, gap, size(15, 0)),
% j'insere le premier bouton qui à un code particulier (qui veut commencer ?)
send(BTS, append, button(départ, message(@prolog, demande, @receiver))),
% j'insère les autre boutons
create_ligne_button(NBC, BTS),
% J'insère maintenant dans le dialog un groupe de boutons verticauxtaux
send(Dialog, append, new(BTS1, dialog_group(buttons, group))),
% j'impose le placement relatif du second groupe par rapport au premier
send(BTS, above, BTS1),
send(BTS1, gap, size(0, 10)),
create_colonne_button(NBL, BTS1),
% je dessine les "carrés" de chocolat.
create_carres(NBL, NBC, Dialog),
% j'affiche la fenêtre
send(Frame, open).
% méthode d'affichage d'un message
alert(Label, Mess) :-
% on crée le dialgue avec un titre
new(D, dialog(Label)),
% on ajoute le texte du message
send(D, append, text(Mess)),
% on ajoute un bouton qui ne renvoie "rien"
send(D, append, button(ok, message(D, return, @nil))),
% j'attends le clic
get(D, confirm, _),
% je détruis le bouton
free(D).
% Je clique sur l'un des bouton de coordonnées (0,0)
mess(_, 0, 0) :-
alert('Jeu du chocolat','Désolé, vous avez perdu.').
% Je clique sur le bouton de la ligne situé en
% colonne numérotée Co (donc en Co+1 : numérotation à la C)
mess(B, 0, Co) :-
% je vais chercher le descripteur de la fenêtre principale
get(B, frame, Frame),
% je lis le nombre de lignes restant
get(Frame, slot, ligne, L),
% je lis le nombre de colonnes restant
get(Frame, slot, colonne, C),
% Je mémorise le nombre de colonnes restant
C1 is Co - 1,
send(Frame, slot, colonne, C1),
% J'efface tous les carrés mangés"
efface(B, 0, L, Co, C),
% L'ordinateur joue
play(B, L, C1).
mess(B, Li, 0) :-
get(B, frame, Frame),
get(Frame, slot, ligne, L),
get(Frame, slot, colonne, C),
L1 is Li - 1,
send(Frame, slot, ligne, L1),
efface(B, Li, L, 0, C),
play(B, L1, C).
% Effacement des carrés mangés, ici on a cliqué sur la ligne
efface(Display, 0, LigneMax, Colonne, ColonneMax) :-
% on inactive les boutons situé à droite
modif_ligne_button(Colonne, ColonneMax, @off),
% on va mainteant manger les carrés sous et à gauche de l'endroit cliqué
% on a d'abord besoin d'aller chercher la fenêtre mère
get(Display, frame, Frame),
% je vais chercher la liste des enfants de la fenêtre (un seul, le dialog)
get(Frame, members, XD),
% je transforme cette liste en liste Prolog
chain_list(XD, [YD]),
% J'efface maintenant tous les carrés à droite et sous le bouton cliqué
forall(between(0, LigneMax, L),
(forall(between(Colonne, ColonneMax, C),
modifie_un_carre(L, C, black, YD)))).
efface(Display, Ligne, LigneMax, 0, ColonneMax) :-
modif_colonne_button(Ligne, LigneMax, @off),
get(Display, frame, Frame),
get(Frame, members, XD),
chain_list(XD, [YD]),
% J'efface maintenant tous les carrés à droite et sous le bouton cliqué
forall(between(Ligne, LigneMax, L),
(forall(between(0, ColonneMax, C),
modifie_un_carre(L, C, black, YD)))).
% Si l'ordinateur joue en 0,0 on a gagné !!!
play(_, 0, 0):-
alert('Jeu du chocolat','Bravo, vous avez gagné !!').
% Sinon on est mal parti ...
play(Button, L, C):-
% a toi de tout écrire pour que l'ordinateur gagne
true.
% prédicat de lancement
chocolat :-
% on joue avec 5 lignes de 10 chocolats (numérotation à "la C")
init(4,9). |
Partager