Robottino Wally – Laboratorio di Programmazione
PROGETTO PROGRAMMAZIONE: codename WALLY
Un robot, situato inizialmente in una posizione di coordinate X,Y di una matrice quadrata, può muoversi di un passo alla volta nelle quattro direzioni cardinali: nord, sud, est e ovest (v. Fig.1).

Fig. 1: Direzioni di moto
In via preliminare impostare il problema nel seguente modo: data una costante T, (che rappresenta la durata della “vita” del robot), scrivere, utilizzando un generatore casuale dei quattro possibili spostamenti elementari del robot, una procedura ricorsiva in cui il robot effettui esattamente T spostamenti sulla matrice.
Prima di procedere agli ulteriori perfezionamenti del programma definire le seguenti strutture dati e schemi di interfaccia utente:
Parametri per il setup della simulazione.
1. Dimensioni della matrice ambiente della simulazione;
2. Posizione iniziale del robot R;
3. Durata T della vita di R;
Individuato il metodo operativo in relazione al quadro generale del problema, arricchire il progetto come segue:
Prima Fase: Definire un punto di partenza e uno o più punti differenti di arrivo: scrivere una procedura che permetta al robot di spostarsi in maniera “intelligente” dal luogo in cui si trova in un luogo prefissato, continuando a decrementare di uno il valore della sua “vita” dopo ogni spostamento elementare.
Seconda Fase: Utilizzare una generazione casuale per introdurre nella matrice un certo numero K1 di ostacoli e potenziare il robot dandogli la capacità di “vedere” gli ostacoli fino a un intorno completo di raggio 2 (v. Fig. 2). Riscrivere le procedure precedenti per questo robot potenziato. NB. La procedura relativa alla Prima Fase non necessariamente deve avere successo. Dopo alcuni tentativi ragionevoli il robot potrebbe rinunciare allo scopo di raggiungere il posto prefissato.

Fig. 2: K1 ostacoli, sensore Z=2
Parametri aggiuntivi per il setup della simulazione.
4. Numero K1 di ostacoli;
Terza fase: si utilizzi ancora una generazione casuale per introdurre in K2 posizioni della matrice dei punti di ricarica per il robot. Il robot inizialmente è predisposto alla ricarica ed ha la capacità di distinguere le ricariche dagli ostacoli; se “vede” dei punti di ricarica allora, e solo allora, tenderà a spostarsi su di essi aumentando la propria autonomia, altrimenti si muoverà secondo la strategia precedentemente fissata evitando gli ostacoli.
N.B. Dopo una ricarica la sua “vita” aumenterà di un valore M prefissato, ma, per un periodo di T passi, continuerà a spostarsi verso l’obiettivo non distinguendo le ricariche dagli ostacoli.

Fig. 3: Sensori di ricarica (K2=3)
Parametri aggiuntivi per il setup della simulazione.
5. Numero K2 di punti di ricarica;
6. Aumento M della vita T di R dovuto al consumo di C;
Il programma termina quando si azzera la “vita” del robot oppure l’obiettivo è stato raggiunto.
Schema di interfaccia: (facoltativo)
L’interfaccia presenterà alcuni tasti di controllo, l’ipotesi minima è la seguente:
START – STOP – PAUSE – CONTINUE – RESET
è possibile ipotizzare anche un cambiamento dei parametri in corso di simulazione, mantenendo lo stato computazionale a cui è arrivata al simulazione dopo N passi.

Fig. 4: Esempio completo
Memoria del robot
Si consideri che il robot possa memorizzare un numero massimo P di posizioni dove è passato o che ha ispezionato; tale memoria può essere simulata attraverso l’utilizzo di una struttura dinamica (ad esempio si potrebbe pensare ad una struttura tipo coda da gestire da parte del robot mediante una lista. L’elemento della lista può essere di tipo record con i seguenti elementi: coordinata X, coordinata Y, e tipologia della casella [O=ostacolo; C=ricarica; R=transitato; .....]. Quando il robot deve spostarsi in una nuova locazione della matrice, controlla nella lista delle ultime P posizioni se già è stato in quella posizione o se già era stata ispezionata. Se decide di spostarsi, per mantenere costante P (max 10), elimina dalla testa un record di memoria e aggiunge quello più recente in coda.
Annotazioni Finali
Il lavoro deve essere fortemente orientato all’astrazione dei dati e dei metodi, quindi gli strumenti più importanti devono essere gestiti attraverso l’uso di una o più unit che devono essere opportunamente documentate indipendentemente dalla documentazione di progetto. La quota di interfaccia con l’utente prevista dal testo sopra descritto deve essere ben progettata in modo che l’utente non abbia necessità di fare ricorso ad un manuale utente. Riassumendo devono essere consegnati su dischetto o via e-mail (evitiamo lo spreco di carta):
a) un eseguibile autoconsistente, cioè che non richieda particolari accorgimenti per essere lanciato in esecuzione (altrimenti devono essere prodotte specifiche istruzioni per l’esecuzione del programma);
b) una documentazione del progetto composta delle seguenti sezioni:
• descrizione del progetto nelle sue linee generali;
• schema p-like delle chiamate di procedura;
• documentazione delle procedure;
SOLUZIONE
Questa esercitazione è fatta in linguaggio PASCAL. Purtroppo ho smarrito laa documentazione originale, posto qui solo i file sorgenti
File: WALLY.PAS
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | Program Wally; Uses Memoria,RobotAdt; Var M:TipoMat; Dim,T,InitX,InitY:Integer; Arrivo:RecArrivi; Passi:TipoMemoria; Begin Writeln('PROGETTO DI PROGRAMMAZIONE 2003'); InitRand; InizializzaGioco(M,InitX,InitY,Dim,T,Arrivo); AttivaMemoria(Passi); PreparaGiro(M,InitX,InitY,Dim,T,Arrivo,Passi); Stampa(Passi); Smemorizza(Passi); Readln; End. |
File: ROBOTADT.PAS
0 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 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 | (**************************************************************************) Unit RobotAdt; (**************************************************************************) Interface Uses Memoria; Const DimMax=20; DimVett=5; Ricarica=20; {Indica il valore di ogni ricarica} TempoCarico=10; {Indica per quanti passi Wally dopo essersi caricato non lo far pi} Type RecArrivi=Record X,Y,Distanza:Integer; NuovaDestinazione:Boolean; NuovaX,NuovaY,NuovaDistanza:Integer; End; TipoMat=Array[1..DimMax,1..DimMax] Of Char; TipoArrivi=Array[1..DimVett] Of RecArrivi; TipoVista=Array[1..5,1..5] Of Char; (**************************************************************************) Procedure InitRand; Procedure InizializzaGioco(Var M:TipoMat;Var InitX,InitY,Dim,T:Integer;Var Arrivo:RecArrivi); Procedure PreparaGiro(Var M:TipoMat;Var InitX,InitY:Integer;Dim,T:Integer;Var Arrivo:RecArrivi;Var Passi:TipoMemoria); (**************************************************************************) Implementation Procedure InitRand; {Inizializza il generatore casuale} Var Dep,I,RanSeed,Temp:Integer; Begin Randomize; Temp:=Random(10000); {Temp il seme} RanSeed:=Trunc(Temp); Temp:=Random(100); For I:=1 To Trunc(Temp) Do Dep:=Random(4); End; Function Casuale:Integer; {Assume valori da 0 a 3} Var Temp:Integer; Begin Temp:=Random(40000); Casuale:=abs(Trunc(Temp/10000)); End; Function CasualeDim(Dim:Integer):Integer; {Assume valori da 1 a Dim-2} Var Temp:Integer; Begin Temp:=Random(40000); CasualeDim:=(Temp MOD Dim-1)+1; End; Procedure InizializzaGioco(Var M:TipoMat;Var InitX,InitY,Dim,T:Integer;Var Arrivo:RecArrivi); Var NumArrivi,I,J,TempX,TempY:Integer; Vett:TipoArrivi; Begin {Setta la dimensione della matrice} Write('Inserisci la dimensione dell''area di gioco (Min. 2-Max. ',DimMax-2,'):'); Readln(Dim); Dim:=Dim+2; {Vanno considerate due dimensioni in pi, usate per la cornice} {Crea la matrice} For I:=2 To Dim-1 Do Begin M[1,I]:=Chr(196); M[Dim,I]:=Chr(196); M[I,1]:=Chr(179); M[I,Dim]:=Chr(179); For J:=2 To Dim-1 Do Begin M[I,J]:=' ' End End; M[1,1]:=Chr(218); M[Dim,1]:=Chr(192); M[1,Dim]:=Chr(191); M[Dim,Dim]:=Chr(217); {Setta la vita del robot} Write('Inserire l''autonomia di Wally:'); Readln(T); {Setta le coordinate iniziali} Write('Inserisci la coordinata x (min. 1, max. ',Dim-2,') di partenza di Wally:'); Readln(InitX); InitX:=InitX+1; {Viene incrementata di 1 perch la prima riga occupata dalla cornice} Write('Inserisci la coordinata y (min. 1, max. ',Dim-2,') di partenza di Wally:'); Readln(InitY); InitY:=InitY+1; {Viene incrementata di 1 perch la prima colonna occupata dalla cornice} {Setta le coordinate degli arrivi e calcola il pi vicino} Write('Quanti punti d''arrivo inserire (max. ',DimVett,')?: '); Readln(NumArrivi); If NumArrivi > 0 Then Begin For I:=1 To NumArrivi Do Begin Write('Inserisci la coord. x (min. 1, max. ',Dim-2,') della destinazione num. ',I,':'); Readln(Vett[I].X); Vett[I].X := Vett[I].X + 1; Write('Inserisci la coord. y (min. 1, max. ',Dim-2,') della destinazione num. ',I,':'); Readln(Vett[I].Y); Vett[I].Y := Vett[I].Y + 1; Vett[I].Distanza:=Abs(InitX-(Vett[I].X))+Abs(InitY-(Vett[I].Y)); M[(Vett[I].X),(Vett[I].Y)]:='D'; End; Arrivo:=Vett[1]; For I:=2 To NumArrivi Do {Trova verso quale punto d'arrivo dirigersi (quello che si raggiunge col minor numero di passi)} Begin If (Arrivo.Distanza)>(Vett[I].Distanza) Then Arrivo:=Vett[I]; End; Arrivo.NuovaDestinazione:=False; Arrivo.NuovaX:=MaxInt; Arrivo.NuovaY:=MaxInt; Arrivo.NuovaDistanza:=MaxInt; End Else Begin Arrivo.Distanza:=MaxInt; Arrivo.X:=MaxInt; Arrivo.Y:=MaxInt; Arrivo.NuovaDestinazione:=False; Arrivo.NuovaX:=MaxInt; Arrivo.NuovaY:=MaxInt; Arrivo.NuovaDistanza:=MaxInt; End; {Setta gli ostacoli} Write('Quanti ostacoli inserire?:'); Readln(J); I:=1; While I<=J Do Begin TempX:=CasualeDim(Dim); TempY:=CasualeDim(Dim); If M[TempX,TempY]=' ' Then Begin I:=I+1; M[TempX,TempY]:='O'; End; End; {Setta le ricariche} Write('Quanti ricariche inserire?:'); Readln(J); I:=1; While I<=J Do Begin TempX:=CasualeDim(Dim); TempY:=CasualeDim(Dim); If M[TempX,TempY]=' ' Then Begin I:=I+1; M[TempX,TempY]:='R'; End; End; End; Procedure Visualizza(M:TipoMat;Dim:Integer); Var I,J:Integer; Begin For I:=1 to Dim Do Begin For J:=1 to Dim Do Write(M[I,J]); Writeln; End; Writeln; End; Function Consentita(Var M:TipoMat;InitX,InitY,Dim,Dir,Carico:Integer):Boolean; Var StatoFunzione:Boolean; Begin StatoFunzione:=False; Case Dir Of {0=Nord;1=Est;2=Sud;3=Ovest} 0:If InitX>2 Then StatoFunzione:=True; 1:If InitY<(Dim-1) Then StatoFunzione:=True; 2:If InitX<(Dim-1) Then StatoFunzione:=True; 3:If InitY>2 Then StatoFunzione:=True; End; {Case} If StatoFunzione Then Begin Case Dir Of 0:InitX:=InitX-1; 1:InitY:=InitY+1; 2:InitX:=InitX+1; 3:InitY:=InitY-1; End; {Case} If (M[InitX,InitY]='O') Or ((M[InitX,InitY]='R') And (Carico>0)) Then StatoFunzione:=False; End; Consentita:=StatoFunzione; End; Procedure MuoviIntelligente(InitX,InitY:Integer;Arrivo:RecArrivi;VAR Dir:Integer); Begin If Arrivo.NuovaDestinazione Then Begin Arrivo.X:=Arrivo.NuovaX; Arrivo.Y:=Arrivo.NuovaY; End; Repeat If (Casuale MOD 2) = 1 Then Begin If InitX<Arrivo.X Then Dir:=2 Else Begin If InitX>Arrivo.X Then Dir:=0 Else Dir:=4; End; End Else Begin If InitY<Arrivo.Y Then Dir:=1 Else Begin If InitY>Arrivo.Y Then Dir:=3 Else Dir:=4; End; End; Until (Dir in [0..3]); End; Function Informazione(Carico:Integer;Visione:TipoVista):Char; Var I,J:Integer; Ostacolo,Ricarica:Boolean; Begin Ostacolo:=False; Ricarica:=False; For I:=1 To 5 Do For J:=1 To 5 Do Begin If Carico>0 Then Begin Case Visione[I,J] Of 'O':Ostacolo:=True; 'R':Ostacolo:=True; End (*Case*) End Else Begin Case Visione[I,J] Of 'O':Ostacolo:=True; 'R':Ricarica:=True; End (*Case*) End End; If Ostacolo And Ricarica Then Informazione:='Z' {Ci sono sia ostacoli che ricariche} Else Begin If Ostacolo Then Informazione:='O' Else Begin If Ricarica Then Informazione:='R' Else Informazione:='N' End End End; Procedure Muovi(Var M:TipoMat;Var InitX,InitY:Integer;Dir:Integer;Var T,Carico:Integer); Begin Case Dir Of 0:InitX:=InitX-1; 1:InitY:=InitY+1; 2:InitX:=InitX+1; 3:InitY:=InitY-1; End; {Case} If (M[InitX,InitY]='R') And (Carico<=0) Then Begin T:=T+Ricarica; Carico:=TempoCarico; End; If Carico>0 Then Writeln('Wally potr ricaricarsi di nuovo tra ',Carico,' passi'); End; Procedure CalcolaDistanza(InitX,InitY:Integer;Var Arrivo:RecArrivi); Begin If Arrivo.NuovaDestinazione Then Arrivo.NuovaDistanza:=Abs(InitX-(Arrivo.NuovaX))+Abs(InitY-(Arrivo.NuovaY)) Else Begin If Arrivo.Distanza<>MaxInt Then Arrivo.Distanza:=Abs(InitX-(Arrivo.X))+Abs(InitY-(Arrivo.Y)) Else Arrivo.Distanza:=MaxInt; End; End; Function ObiettivoRaggiunto(Arrivo:RecArrivi;InitX,InitY:Integer):Boolean; Begin If Arrivo.NuovaDestinazione Then Begin ObiettivoRaggiunto:=((Arrivo.NuovaX=InitX)And(Arrivo.NuovaY=InitY)) End Else ObiettivoRaggiunto:=False End; Procedure ScansaOstacolo(InitX,InitY:Integer;Var Arrivo:RecArrivi;Var Dir:Integer;Visione:TipoVista;Passi:TipoMemoria); Var StoriaX,StoriaY,I,X,Y:Integer; Necessario,SfruttaMemoria:Boolean; Begin MuoviIntelligente(InitX,InitY,Arrivo,Dir); SfruttaMemoria:=False; Necessario:=False; X:=MaxInt; Y:=MaxInt; Case Dir Of 0:If Visione[2,3]='O' Then Necessario:=True; 1:If Visione[3,4]='O' Then Necessario:=True; 2:If Visione[4,3]='O' Then Necessario:=True; 3:If Visione[3,2]='O' Then Necessario:=True; End; (*case*) If Necessario Then Begin Case Dir Of 0:Begin If (Visione[3,2]=' ') And (Visione[2,2]=' ') Then Begin X:=2; Y:=2; End Else Begin If (Visione[3,4]=' ') And (Visione[2,4]=' ') Then Begin X:=2; Y:=4; End Else SfruttaMemoria:=True; End End; 1:Begin If (Visione[2,3]=' ') And (Visione[2,4]=' ') Then Begin X:=2; Y:=4; End Else Begin If (Visione[4,3]=' ') And (Visione[4,4]=' ') Then Begin X:=4; Y:=4; End Else SfruttaMemoria:=True; End End; 2:Begin If (Visione[3,4]=' ') And (Visione[4,4]=' ') Then Begin X:=4; Y:=4; End Else Begin If (Visione[3,2]=' ') And (Visione[4,2]=' ') Then Begin X:=4; Y:=2; End Else SfruttaMemoria:=True; End End; 3:Begin If (Visione[4,3]=' ') And (Visione[4,2]=' ') Then Begin X:=4; Y:=2; End Else Begin If (Visione[2,3]=' ') And (Visione[2,2]=' ') Then Begin X:=2; Y:=2; End Else SfruttaMemoria:=True; End End; End; (*case*) If SfruttaMemoria Then Begin For I:=1 To 5 Do Begin Storia(Passi,I,StoriaX,StoriaY); IF StoriaX=MaxInt Then Begin X:=StoriaX; Y:=StoriaY; End End End; If X<>MaxInt Then Begin Arrivo.NuovaDestinazione:=True; Case X Of 1:Arrivo.NuovaX:=InitX-2; 2:Arrivo.NuovaX:=InitX-1; 3:Arrivo.NuovaX:=InitX; 4:Arrivo.NuovaX:=InitX+1; 5:Arrivo.NuovaX:=InitX+2; end; (*case*) Case Y Of 1:Arrivo.NuovaY:=InitY-2; 2:Arrivo.NuovaY:=InitY-1; 3:Arrivo.NuovaY:=InitY; 4:Arrivo.NuovaY:=InitY+1; 5:Arrivo.NuovaY:=InitY+2; end; (*case*) end; End; MuoviIntelligente(InitX,InitY,Arrivo,Dir); End; Procedure MangiaRicarica(InitX,InitY:Integer;Var Arrivo:RecArrivi;Var Dir:Integer;Visione:TipoVista;Passi:TipoMemoria); Var I,J,X,Y:Integer; Recuperabile,AttenzioneOstacoli:Boolean; Begin Recuperabile:=True; AttenzioneOstacoli:=False; For I:=1 To 5 Do For J:=1 To 5 Do Begin If Visione[I,J]='R' Then Begin X:=I; Y:=J; End; If (Visione[I,J]='O') Then AttenzioneOstacoli:=True; End; If AttenzioneOstacoli Then Begin If (Visione[2,3]='R') Then Begin X:=2; Y:=3; End Else Begin If (Visione[3,4]='R') Then Begin X:=3; Y:=4; End Else Begin If (Visione[4,3]='R') Then Begin X:=4; Y:=3; End Else Begin If (Visione[3,2]='R') Then Begin X:=3; Y:=2; End Else Begin Recuperabile:=False; End End End End End; If Recuperabile Then Begin Arrivo.NuovaDestinazione:=True; Case X Of 1:Arrivo.NuovaX:=InitX-2; 2:Arrivo.NuovaX:=InitX-1; 3:Arrivo.NuovaX:=InitX; 4:Arrivo.NuovaX:=InitX+1; 5:Arrivo.NuovaX:=InitX+2; end; (*case*) Case Y Of 1:Arrivo.NuovaY:=InitY-2; 2:Arrivo.NuovaY:=InitY-1; 3:Arrivo.NuovaY:=InitY; 4:Arrivo.NuovaY:=InitY+1; 5:Arrivo.NuovaY:=InitY+2; end; (*case*) MuoviIntelligente(InitX,InitY,Arrivo,Dir); End Else Begin ScansaOstacolo(InitX,InitY,Arrivo,Dir,Visione,Passi); End End; Procedure TrovaDir(Var M:TipoMat;T,InitX,InitY,Dim,Carico:Integer;Var Arrivo:RecArrivi;Var Dir:Integer; Visione:TipoVista;Passi:TipoMemoria); Var Conto:Integer; Veduto:Char; Begin If Arrivo.NuovaDestinazione Then Begin Conto:=1; Repeat Conto:=Conto+1; If Conto>10 Then Begin Dir:=Casuale End Else Begin MuoviIntelligente(InitX,InitY,Arrivo,Dir); End; Until Consentita(M,InitX,InitY,Dim,Dir,Carico) Or (Conto>30); End Else Begin Conto:=1; Repeat Conto:=Conto+1; If Conto>10 Then Begin Dir:=Casuale End Else Begin If Arrivo.Distanza>T Then Begin If (Informazione(Carico,Visione)='R') Or (Informazione(Carico,Visione)='Z') Then MangiaRicarica(InitX,InitY,Arrivo,Dir,Visione,Passi) Else Begin Dir:=Casuale; End End Else Begin MuoviIntelligente(InitX,InitY,Arrivo,Dir); Veduto := Informazione(Carico,Visione); Case Veduto Of 'O':ScansaOstacolo(InitX,InitY,Arrivo,Dir,Visione,Passi); 'R':MangiaRicarica(InitX,InitY,Arrivo,Dir,Visione,Passi); 'Z':MangiaRicarica(InitX,InitY,Arrivo,Dir,Visione,Passi); End; (*case*) End; End; Until Consentita(M,InitX,InitY,Dim,Dir,Carico) Or (Conto>30); End; {Conto indica il numero di tentativi per trovare la direzione} If Conto>30 Then Begin Writeln('Impossibile Muoversi!!!'); Stampa(Passi); Readln; Smemorizza(Passi); Halt; End; End; Procedure Vista(Var M:TipoMat;Dim,InitX,InitY:Integer;Var Visione:TipoVista); Var I,J:Integer; Begin For I:=1 To 5 Do Begin For J:=1 To 5 Do Begin If ((InitX+(I-3)) In [2..Dim-1]) And ((InitY+(J-3)) In [2..Dim-1]) Then Visione[I,J]:=M[(InitX+(I-3)),(InitY+(J-3))] Else Visione[I,J]:='-'; End; End; End; Procedure Giro(Var M:TipoMat;Var Visione:TipoVista;Var InitX,InitY:Integer; Dim,T:Integer;Var Arrivo:RecArrivi;Var Carico:Integer;Var Passi:TipoMemoria); Var I,J,Dir:Integer; Begin If M[InitX,InitY]<>'D' Then Begin Vista(M,Dim,InitX,InitY,Visione); If M[InitX,InitY]='P' Then Memorizza(Passi,InitX,InitY,'P') Else Memorizza(Passi,InitX,InitY,Informazione(Carico,Visione)); M[InitX,InitY]:=Chr(2); Writeln('Vita di Wally >> ',T); Visualizza(M,Dim); Readln; If T>0 Then Begin TrovaDir(M,T,InitX,InitY,Dim,Carico,Arrivo,Dir,Visione,Passi); M[InitX,InitY]:=' '; Muovi(M,InitX,InitY,Dir,T,Carico); If ObiettivoRaggiunto(Arrivo,InitX,InitY) Then Begin Arrivo.NuovaDestinazione:=False; Arrivo.NuovaX:=MaxInt; Arrivo.NuovaY:=MaxInt; Arrivo.NuovaDistanza:=MaxInt; End; CalcolaDistanza(InitX,InitY,Arrivo); If Carico>0 Then Carico:=Carico-1; Giro(M,Visione,InitX,InitY,Dim,T-1,Arrivo,Carico,Passi); End; End Else Begin Memorizza(Passi,InitX,InitY,'D'); Writeln('Sei Arrivato Al Punto Di Uscita!!!'); M[InitX,InitY]:=Chr(2); Visualizza(M,Dim); Readln; End; End; Procedure PreparaGiro(Var M:TipoMat;Var InitX,InitY:Integer;Dim,T:Integer;Var Arrivo:RecArrivi;Var Passi:TipoMemoria); Var Carico:Integer; Visione:TipoVista; Begin M[InitX,InitY]:='P'; Carico:=0; Giro(M,Visione,InitX,InitY,Dim,T,Arrivo,Carico,Passi); End; {Main} Begin End. |
File: MEMORIA.PAS
0 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 | (**************************************************************************) UNIT Memoria; (**************************************************************************) INTERFACE CONST LungMemoria = 10; (*Numero elementi della memoria*) TYPE TipoElementoMemoria = RECORD X,Y : INTEGER; Informazioni : CHAR end; (*record*) Pnodo = ^TipoNodo; TipoNodo = RECORD elem : TipoElementoMemoria; next : Pnodo end; (*record*) TipoMemoria = RECORD nroelem : INTEGER; testa,fine : Pnodo end; (*record*) (**************************************************************************) PROCEDURE AttivaMemoria(VAR Passi:TipoMemoria); (*OUT: attiva la memoria, adesso puoi usarla!*) PROCEDURE Memorizza(VAR Passi:TipoMemoria;InitX,InitY:INTEGER;Info:CHAR); (*OUT: elemento memorizzato*) PROCEDURE Smemorizza(VAR Passi:TipoMemoria); (*OUT: smemorizza tutta la memoria, e restituisce alla HEAP tutto ci che gli spetta. Questo comando deve essere quindi eseguito per disattivare la memoria*) PROCEDURE Stampa(VAR Passi:TipoMemoria); (*OUT: stampa gli ultimi LungMemoria elementi memorizzati*) PROCEDURE Storia(Passi:TipoMemoria;N:Integer;StoriaX,StoriaY:INTEGER); (*OUT: ultima coordinata x registrata in StoriaX, da MaxInt se non esiste! Ultima coordinata y registrata in StoriaY, da MaxInt se non esiste*) (**************************************************************************) IMPLEMENTATION PROCEDURE Scoda(VAR Passi:TipoMemoria); (*OUT: scoda un elemento*) VAR Temp:Pnodo; BEGIN Temp := Passi.Testa; IF Temp <> NIL THEN WITH Passi DO Begin Testa := Temp^.next; IF Testa = NIL THEN Fine := NIL; dispose(temp); NroElem := NroElem-1 End END; PROCEDURE AttivaMemoria(VAR Passi:TipoMemoria); (*OUT: coda vuota*) BEGIN WITH Passi DO Begin NroElem := 0; testa := NIL; fine := NIL End END; PROCEDURE Memorizza(VAR Passi:TipoMemoria;InitX,InitY:INTEGER;Info:CHAR); (*OUT: elemento accodato*) VAR x:TipoElementoMemoria; Temp:Pnodo; BEGIN IF LungMemoria = Passi.NroElem THEN Scoda(Passi); new(temp); temp^.elem.X := InitX; temp^.elem.Y := InitY; temp^.elem.Informazioni := Info; temp^.next := NIL; WITH Passi DO Begin IF Testa = NIL THEN Testa := Temp ELSE Fine^.next := Temp; Fine := Temp; NroElem := NroElem +1 End END; PROCEDURE Smemorizza(VAR Passi:TipoMemoria); VAR I:INTEGER; BEGIN WHILE Passi.testa <> NIL DO (*se la memoria non vuota esegue l'iterazione*) BEGIN Scoda(Passi) END END; PROCEDURE Stampa(VAR Passi:TipoMemoria); VAR I:INTEGER; Temp:Pnodo; BEGIN Temp := Passi.Testa; IF Passi.testa = NIL THEN Writeln('La memoria Vuota!!!') ELSE Begin I := 0; WHILE Temp <> NIL DO Begin I := I+1; Write(I,') Coordinate X=',(Temp^.elem.X-1),' Y=',(Temp^.elem.Y-1)); Write(' - Info: '); CASE Temp^.elem.Informazioni OF 'N':Writeln('zona libera'); 'O':Writeln('ostacolo'); 'R':Writeln('ricarica'); 'P':Writeln('punto di partenza'); 'D':Writeln('punto di arrivo **'); 'Z':Writeln('ostacolo e ricarica'); end; (*case*) Temp := Temp^.Next End End END; PROCEDURE Storia(Passi:TipoMemoria;N:Integer;StoriaX,StoriaY:INTEGER); VAR Puntatore:Pnodo; I:INTEGER; BEGIN Puntatore:=Passi.Testa; FOR I:=1 TO (Passi.NroElem-N) DO Puntatore := Puntatore^.Next; IF Puntatore<>NIL THEN Begin StoriaX := Puntatore^.elem.X; StoriaY := Puntatore^.elem.Y End ELSE Begin StoriaX := MaxInt; StoriaY := MaxInt End END; BEGIN (*MAIN UNIT*) END. (*MAIN UNIT*) |
