En aquest capítol crearem un petit nino a qui donarem un conjunt de comportaments que simulin una certa forma d'"intel·ligència". Això ens servirà per treballar el conjunt de les regles de la lògica.
Dibuixar una quadrícula
Per dibuixar una quadrícula obrim l'editor de dibuix i amb l'eina de fer quadrats i el gruix de pinzell adequat dibuixem un quadrat com el de la imatge següent a l'angle superior esquerre de l'etapa de dibuix.(poseu l'ampliació al màxim).
A continuació disminuïm l'ampliació fins a la meitat.
Ara agafem l'eina tampó i seleccionem el quadrat dibuixat.
Tot seguit l'estampem fent coincidir exactament les vores.
Repetirem el procés fent servir cada vegada seleccions de tampó més grans fins a cobrir tota l'etapa.
Un cop tinguem una quadrícula que, entre el centre de cada quadrat tingui una distància de 20 passos, dibuixarem el ninot de la forma següent
En exercicis anteriors hem aprés a moure el ninot amb les fletxes del teclat. Anem a escriure unes línies de codi perquè, en pressionar la barra espaiadora, el ninot avanci 20 passos.
Si pressionem la tecla espai, el ninot es mourà 20 passos cada vegada fins arribar al límit de la pantalla. Anem a donar-li instruccions perquè pugui detectar obstacles i hi pugui respondre d´alguna manera. Per això, dibuixem un punt vermell davant del ninot, aproximadament en el centre del quadrat següent amb la direcció d´avanç. Aquest punt vermell ens servirà perquè el ninot detecti informació del seu entorn i la faci servir per decidir el que ha de fer; escrivim ara el codi necessari
El primer que veiem és que fem una pregunta; 'el color vermell és a sobre del color blanc?', a això li diem condició. Com veurem més endavant, aquesta condició podria ser més complexa, desprès aprendrem a formular aquestes condicions complexes. Veiem que a la pregunta només podem contestar ¨verdader¨o ¨fals¨. Si o No.
Aquest és el tipus de preguntes a què responen els ordinadors, si la condició es compleix contestarem amb una acció 'moure 20 passos', sinó, 'girarem 90' en el sentit de les agulles del rellotge. Posem el nostre ninot en el circuit de proves, i modifiquem una mica el codi de la següent forma.
El codi és bàsicament el mateix, ara iniciem el programa pressionant la bandera i a continuació situem el ninot en una casella concreta del nostre circuït de proves. Afegim un bucle sense fi perquè les instruccions principals es repeteixin de forma indefinida, també col·loquem una instrucció d' 'esperar' perquè el ninot no corri massa i es pugui observar la seva evolució. Aquesta última instrucció no és necessària i, si volem, podem eliminar-la o fer diferents proves canviant l´interval de temps.
Veiem que quan pressionem la bandera, el ninot es posa en moviment, descriu diferents trajectòries i acaba movent-se en cercle (en aquest cas en quadrat) de forma indefinida. Podem dir que el ninot ja té comportament propi. Seríem capaços de crear un codi que li donés un comportament més complexe, capaç de resoldre laberints senzills i alguns de no tan senzills?. Veiem el que ens fa falta per afrontar el problema. Primer necessitem disposar de més informació de la que tenim. Coneixent només que la següent casella estigui lliure no en tindrem prou per crear comportaments més elaborats, afegim dos sensors més al nostre ninot, un a la dreta i un altre a l´esquerra de la seva posició
Seguint el mateix patró que el dibuix anterior afegim un punt blau a l´esquerra i un de verd a la dreta del nostre ninot, recordem-nos de mantenir el centre de gir a la seva posició. La informació que ens proporcionaran aquests sensors serà del mateix tipus que l´anterior, és a dir, si les caselles sobre les que estan, són lliures. Fixem-nos que la informació que recollim és local i que no l´emmagatzemarem, és a dir, que la llegim, la utilitzem i ens n'oblidem. De fet, l´únic que "recorda" el ninot és on té els sensors (vermell enfront, blau a l´esquerra, verd a la dreta).
Les condicions que utilitzarem són les que es mostren en la figura següent
A les tres preguntes només es pot respondre "verdader" o "fals", Si o No, Com que tenim tres preguntes i cadascuna té dues respostes, tindrem vuit possibles resultats de les lectures dels sensors. Dit d'una altra forma, tindrem una informació de tres bits (bit = unitat bàsica d'informació). Veiem gràficament els vuit possibles resultats:
Per començar només utilitzem dos sensors, el vermell i el blau. Veiem la taula de decisió reduïda a aquest cas. ( Només utilitzem dos bits d'informació)
Què podem fer amb aquesta informació? Serà suficient per resoldre alguns dels problemes plantejats?
Si estem en un laberint que té una entrada i una sortida i les dues són a les vores d'aquest laberint, és fàcil veure que una vegada situats a l´entrada, si seguim sempre la paret situada a la nostra esquerra (o en el cas simètric, la situada a la nostra dreta) tard o d´hora trobarem la sortida, si aquesta existeix, o bé, tornarem a l´entrada. Per tant, per travessar el laberint serà suficient mantenir-nos sempre en contacte amb la paret triada.
Veiem com apliquem aquest coneixement a l´escriptura del codi corresponent. Observem les figures següents que mostren la situació en la que es pot trobar el ninot.
En la primera imatge observem el ninot amb la paret a la seva esquerra i un espai lliure al davant, per tant, el que ha de fer és avançar. Això en el llenguatge dels sensors és vermell SI, blau NO i correspon a l'estat 2 de la taula de decisió reduïda. La segona imatge correspon a vermell SI, blau SI, que correspon a l'estat 1 de la taula. Veiem com utilitzem la lògica per a expressar amb codis aquests fets. Volem que el ninot distingeixi entre els quatre estats possibles i, en cada cas realitzi l´acció corresponent.
En la figura veiem escrites tres condicions; si observem la imatge del ninot que té la paret enganxada al seu costat esquerre hem de respondre SI a la primera condició 'vermell sobre blanc'. Fixem-nos en la segona condició, és una mica diferent; a la pregunta ' blau sobre blanc' referida a la mateixa imatge d´abans hem de respondre NO, però aquesta condició té un no al davant, per tant si neguem el No tindrem un Si, recordem: dos No fan un Si. Anem ara a la tercera condició que hem escrit, es composa de les dues anteriors unides per una I, això significa que la condició conjunta serà certa si, i només, si ho són les dues. En el nostre cas la resposta a la condició és Si, ja que a la primera 'vermell sobre blanc' responem Si i a la segona,'No blau sobre blanc' també responem Si.
Si es compleix la condició el ninot haurà d'avançar 20 passos. Canviem ara el codi perquè reflecteixi el que hem descobert.
Ja hem dit al ninot el que ha de fer en el cas 2 de la taula de decisió, veiem ara el que ha de fer en els altres tres casos. Comencem pel primer que és el representat per la imatge segona del ninot; quan els dos sensors estan sobre el blanc, el que ha de fer per seguir la paret es girar 90 graus en el sentit de les agulles del rellotge i moure´s 20 passos. Quan hagi realitzat aquesta acció ens trobarem en l´estat 2. Tornem al codi i escrivim el que calgui perquè el ninot faci el que li hem dit. Si ens hi fixem, veurem que en l´estructura de control ' Si - Si no', a l´apartat del 'Si' hem donat instruccions pel cas 2 i a l´apartat ' Si no' ens queden els casos 1, 3 i 4. El primer que farem es distingir entre ells i en consultar la taula de decisió veurem que dels 3 casos que ens queden, els casos 1 i 3 compleixen la condició 'blau sobre blanc' i si mirem la imatge veiem que en els dos casos el ninot ha de girar 90 graus en sentit contrari a les agulles del rellotge i desprès moure´s 20 passos. El codi quedarà així.
Ara en l´apartat 'Si no' de la segona estructura només ens quedarà el cas 4. Si observem, ens adonarem que el que ha de fer el ninot en aquest cas és girar 90 graus en el sentit de les agulles del rellotge. Veiem el codi complert.
Provem el codi; volem que el ninot recorri el laberint i trobi la sortida, amb l´única condició de tenir una paret a la seva esquerra en iniciar el recorregut. Si el ninot va molt de pressa podem afegir una instrucció 'esperar 0,1 segons' en l´interior del bucle 'repetir sempre' com a última instrucció. Fent servir només 2 bits d´informació i poques línies de codi hem aconseguit donar-li al ninot un comportament capaç de resoldre un problema en aparença no massa simple.
Nota: És important controlar la posició inicial del ninot, hem d'assegurar-nos que el ninot toqui una paret, modificar la instrucció 'anar a x: y:' perquè això passi. Ens hem d´assegurar que té la paret a l´esquerra del sentit en que es mourà. Si no és així, arrosseguem a la zona de programa una instrucció 'girar' i col·loquem-li valor 90 graus. Aquesta instrucció ha de quedar solta, sense estar lligada a cap altra. Si li fem doble clic a sobre, el ninot anirà girant, fins que el col·loquem en la posició desitjada.
Compliquem una mica el problema, suprimim la condició inicial i fem que el ninot comenci des de qualsevol casella. Quina estratègia seguirem?. Podríem fer que el ninot primer trobés una paret a la seva esquerra i un cop trobada segueixi el comportament anterior?. Anem a escriure el codi perquè ho faci i després l´enllaçarem en l´escrit anteriorment. El primer que hem d'observar és, si a l´inici compleix una de les següents condicions 'No vermell sobre blanc? o 'No blau sobre blanc'. Si es compleix la primera condició estem en els casos 3 i 4 de la taula de decisió i, per tant podem aplicar el codi escrit anteriorment. Si es compleix la segona condició estem en els casos 2 i 4 de la taula i per tant també apliquem el codi anterior. Veiem les condicions i escrivim el codi corresponent.
El primer que farem serà iniciar el programa pel bloc que busca la paret, i quan la trobi enllaçarem amb el següent bloc que és el que segueix la paret esquerra. Vegem com queda el codi.
Amb aquest codi aconseguim que el ninot solventi laberints senzills, és a dir, que tinguin una paret contínua, o laberints amb una entrada i una sortida, que no continguin illes. En la següent pràctica afegirem comportaments al ninot que li permeti solucionar laberints més complexos i reorganitzarem el codi perquè sigui més llegible.
En la pràctica anterior vàrem veure com resoldre laberints simples tot donant-li al nostre ninot dos comportaments, l'un és buscar una paret i posar-la a l'esquerre de la trajectòria del ninot i l'altre caminar sempre amb aquesta paret a la seva esquerra. Anem a veure si podem afegir altres comportaments al ninot perquè pugui resoldre problemes més complexos; laberints que tinguin illes, és a dir, que si seguim una paret determinada podem acabar caminant en cercle. El primer que hem d'aconseguir és que el nostre ninot sigui capaç d'adonar-se del que està passant, prendre consciencia de que està donant voltes sobre el mateix punt. Podem dissenyar diferents estratègies per aconseguir el nostre objectiu, per exemple ensenyar al nostre ninot a dibuixar i a llegir mapes, això és un xic complicat i, de moment ho deixarem i optarem pel mètode "polzet", o sigui deixar marques sobre el terreny i utilitzar-les per a determinar la nostra situació. Simplificarem inclús el mètode de la forma següent; quan arribem a una paret deixarem un senyal, si al cap d'un temps tornem a trobar-nos aquest senyal voldrà dir que ens estem movent en cercles, per tant farem que el ninot funcioni així per solucionar-ho: primer esborrarà la senyal deixada, després buscarà una nova paret amb un mètode que tingui quelcom d'aleatori i tornarà a començar el procés; deixar marca, seguir esquerre, sortir del laberint o trobar de nou una marca. Aquest sistema no garanteix que sempre surti del laberint, però millora les nostres possibilitats de fer-ho.
Tot seguit veurem com fer-ho, afegirem un nou vestit, com es mostra a la imatge següent, que ens servirà per deixar un senyal vermell quan l'hi indiquem nosaltres i, al vestit principal l'hi afegim una marca groga que actuarà de sensor
Abans de començar a escriure el nou codi dibuixarem un laberint com el de la imatge següent, i en el qual dibuixarem també una marca blava que ens indicarà la casella de terminació.
Recuperarem el codi de la pràctica anterior i el modificarem de la següent manera, perquè en tocar una paret deixi una marca nova.
Ara que hem col·locat la marca, hem d'afegir-hi codi, per tal que el ninot el detecti; fixem-nos que el ninot té una marca groga en el seu muscle esquerre que utilitzarem com a sensor per detectar el senyal vermell. També hi haurem d'afegir la detecció de final de laberint. Vegem el codi i després el comentem.
El primer que farem serà crear un bucle que es repetirà fins que aconseguim la condició de fi, taronja sobre blau (és a dir, el ninot sobre la marca blava de final), la primera instrucció del bucle veiem que es 'enviar a tots mou i esperar', el bloc que s'inicia com 'mou' encara no l'hem escrit.
Si observem aquest codi, veiem que és molt semblant al que hem utilitzat en la pràctica 1, però aquí hem esborrat el 'repetir per sempre' i l'esperar 0.1 segons' ja que això ho fa el bloc anterior. Veiem que en el codi també hem utilitzant el missatge "nova"; aquest missatge l'enviarem quan trobem un senyal vermell que ens indica que ja hem passat per aquesta casella, en aquest cas hem de buscar una nova paret i començar altra vegada el procés; vegem el codi del bloc 'nova'.
El primer que fem en codi és esborrar el senyal vermell, per això necessitem crear un altre vestit per al nostre ninot; dibuixem un vestit igual que el vermell però amb el punt blanc, que en estampar-lo esborri el senyal vermell; després generem un número aleatori (que guardem en una variable 's') i repetim el bloc 'mou' les vegades que indiqui el número. Girem 90º per no tenir la paret a l' esquerra i busquem una nova paret, per fer això hem de crear un nou missatge 'buscaP'. Ara modificarem el bloc que vàrem inicia amb la bandera verda, per tal que respongui al missatge 'buscaP'.
Veiem que en aquest darrer codi apareix el missatge 'seguir'. Aquest missatge engegarà el bloc que abans hem deixat sense encapçalament, veiem-ho.
Solament falta escriure un petit bloc per arrencar el programa des de la bandera verda i fixar les condicions d'inici.
Ara, si arrosseguem amb el ratolí el ninot a qualsevol casella del tauler (cal que la quadrícula encaixi exactament) i fem clic en la bandera verda, aquest tornarà sempre (o gairebé sempre) a la posició de sortida del laberint. Recordem que per a poder moure el ninot amb el ratolí en mode pantalla completa és necessari desbloquejar el cadenat del panell del ninot.
En aquesta pràctica, construirem un joc que és un clàssic dels jocs d'ordinador. Ens servirà per veure una sèrie de propietats de la capa del dibuix i la seva utilització per emmagatzemar informació. Vegem en què consisteix el joc
Vista general del joc
Tenim un tauler de joc en el que hi ha unes caselles grises que representen els límits de la zona de joc i els obstacles impenetrables que no poden ser ocupats per altres objectes. Hi ha també unes caselles verdes que representen caixes que han de ser mogudes pel ninot fins a col·locar-les sobre les caselles grogues.
-El ninot només es pot moure sobre caselles blanques i grogues (no pot passar per sobre de les caixes).
-El ninot només pot empènyer les caixes (no pot arrossegar-les)
-El ninot sols té força per empènyer una sola caixa de cop
Objectius del joc
-Col·locar les caixes verdes sobre les caselles grogues (quan una caixa està en posició correcta, canvia de color)
-Com a segon objectiu, hem d'aconseguir el primer amb el nombre mínim de moviments
Anàlisi del Joc
La programació del joc la podem resoldre de diferents formes; potser la més intuïtiva seria dibuixar el tauler de joc sobre la capa escenari, en la que representaríem totes les parts no mòbils (límits de la zona, diferents obstacles, caselles que marquen les posicions finals, caselles) Després crearíem les instruccions associades a cada objecte mòbil. Així, pel ninot escriuríem un bloc de control de moviments amb les fletxes del teclat, com hem vist en capítols anteriors. Podríem fer servir tant coordenades rectangulars com polars, cada sistema presenta els seus avantatges i inconvenients. Un cop el ninot es mou, hem de trobar un mètode per poder determinar si la casella següent està lliure, és a dir, si el moviment és possible. Si la casella a la qual es dirigeix el ninot està ocupada per una caixa haurem que determinar si la següent està lliure (blanca o groga) i si és així, passar a moure la caixa i el ninot
Taula de decisió
En cada caixa haurem d'afegir el codi necessari perquè respongui al contacte del ninot, farem servir instruccions del tipus “ Si tocant el ninot” fer … Si volem fer el joc una mica més interessant, afegirem al ninot un codi perquè conti el passos que fa. També és interessant que el programa pugui detectar quan hem solucionat el problema. Per completar-lo, estaria bé disposar de diferents escenaris de dificultat creixent i poder navegar-hi.
Si enfoquem el problema d'aquesta manera (simulació realista) haurem d'escriure codi per cada objecte. Si creem diferents escenaris ens trobarem que el nombre d'objectes (caixes) de cada escenari serà normalment diferent, la qual cosa comportarà tenir un estoc de caixes disponibles per afegir o treure objectes segons les necessitats. Cada cop que canviem de nivell haurem d'inicialitzar les caixes en les seves posicions d'origen, tant si es fan servir com si no. Es poden presentar altres problemes amb el moviment de les caixes en la inicialització, tots ells solucionables, però compliquen el codi i són de comprensió més difícil (ahttp://scratch.mit.edu/users/joanguell hi ha una solució d´aquesta forma)
Per això anem a abordar el problema des d'un altre punt de vista; en lloc de simular el joc en sí, anem a simular les imatges que produeix el joc. Intentarem explicar això una mica millor; una cosa són els objectes (encara que siguin virtuals) i una altra és la imatge que en percebem. Per això en lloc de manipular els objectes el que farem serà dibuixar la imatge corresponent a cada joc Abans de continuar endavant anem a descriure com estan organitzats en la imatge (pantalla) els diferents elements de Scratch.
Estructura en capes dels Objectes de Scratch
Els objectes en Scratch es disposen en capes que s´apilen l'una sobre l´altra, la capa més baixa es l´escenari; just a sobre es troba una capa que és la superfície del dibuix que inicialment és transparent, en ella van dibuixant els llapis associats als diferents objectes. L´ordre d´aquestes dues capes no es pot modificar. Immediatament es van col·locant a sobre els objectes, cadascun en una capa. L´ordre dels objectes es pot modificar amb les ordres “enviar al front” i “enviar cap al darrere en capes”. Això ens permet que els objectes amaguin els uns als altres També és important quan fem servir instruccions de comparació de colors “¿color A sobre B? i “tocant color A?”
Utilització de la capa de dibuix com a memòria temporal
En la capa de dibuix podem escriure i esborrar (en realitat sobreescriure) informació mitjançant les instruccions del llapis i la instrucció “estampar” que combinada amb diferents disfresses del ninot hi podem llegir aquesta informació, mitjançant les instruccions “¿color A sobre B? i “tocant color A?”
Mecànica del Programa
Nota.- En la implementació que fem d'aquestes instruccions hi ha una variable d´aquest procés que explico a continuació, però, per més claredat, és millor fixar-se en l´anterior. Per tal que el procés funcioni seguint la seqüència descrita, caldria guardar els valors de la lectura dels sensors en una variable temporal, ja que aquests els fem servir per determinar el que s'ha d'escriure i, un cop movem el ninot, que en la seqüència es fa abans d'escriure, la lectura varia. Per evitar crear aquesta variable combinem les instruccions de moviment i escriptura, per la qual cosa el passos 6 i 7 apareixen barrejats en el codi..
Com dibuixar els elements del programa
En aquest cas la forma i el color dels objectes del programa són molt importants, de fet, formen part del mateix codi. Per això és necessari dibuixar-los de forma precisa. Anem a explicar com fer aquest dibuixos.
Diferents vestits del ninot i els seus detalls
Dibuixar una quadrícula
Per dibuixar una quadrícula obrim l'editor de dibuix i amb l'eina de fer quadrats i el gruix de pinzell adequat dibuixem un quadrat com el de la imatge següent a l'angle superior esquerre de l'etapa de dibuix.(poseu l'ampliació al màxim).
A continuació disminuïm l'ampliació fins a la meitat.
Ara agafem l'eina tampó i seleccionem el quadrat dibuixat.
Tot seguit l'estampem fent coincidir exactament les vores.
Repetirem el procés fent servir cada vegada seleccions de tampó més grans fins a cobrir tota l'etapa.
Fes una quadrícula completa i desa l'arxiu com M6QuadrículaNomiCognom.sc
Tauler Inicial
EL primer bloc de codi que escrivim, correspon a les instruccions d'inicialització de la posició i direcció del ninot, així com del bloc de control del mateix mitjançant les fletxes del teclat. Si observem el codi veiem que el ninot respon a les fletxes del teclat canviant de direcció i enviant el missatge “mou” a un altre bloc de codi que s'encarrega d'avaluar si el moviment és possible i realitzar les operacions necessàries per a generar el moviment, en el cas que sigui possible.
Anem a escriure el bloc mou; primer implementem el moviment simple, és a dir, quan s'avança sense tenir obstacles al davant. Primer, anem al vestit que té un punt vermell i un punt blanc, (explorer) en els quadrats següents a la posició frontal del ninot i comprovem si és vermell sobre blanc i avancem. Observem el codi pas a pas. La primera condició que avaluem és si és possible avançar. Si no ho és, ja no avaluem res més (vermell sobre gris)
Si és possible moure's, comprovem si el quadrat següent és blanc o groc, la comprovació de verd clar o verd fosc no cal que la fem, és una condició implícita en el no ser blanc o groc.
Ara, en cas que no sigui ni blanc ni groc el quadrat següent, comprovem que el que ve després estigui lliure (blanc, sobre blanc o groc). Si està lliure avançarem, i si no ho està, tornarem a la posició d'espera
Ara comprovarem si estem en el cas de blanc sobre groc
Si és així comprovem si el quadrat sobre el que hem d'avançar és verd clar (també escrivim el mateix codi pel cas de blanc sobre blanc, que es dóna per sobreentès).
Ara només ens cal escriure els comportaments que ha de tenir el ninot en cada cas. Veiem com es fa.
Només ens caldrà acabar de dibuixar un taulell com el de la figura següent i el joc ja s'haurà acabat
En aquesta pràctica continuarem el joc anterior afegint-hi un comptador de passos i creant diversos nivells. També el deixarem obert perquè l'usuari en pugi crear més. El primer que farem serà modificar l'inici del programa (bandera verda), de la manera següent.
Ara crearem les variables següents:
I també les variables llista que es mostren a continuació.
Comentem aquestes variables, 'level' guardarà el nivell en que estem jugant, 'passos' el passos que portem fets en el nivell actual,'Xi' i 'Yi' les coordenades d'inici del ninot per cada nivell 'i' i 'comptador' el nombre de caixes que tinguem col·locades en el seu lloc (quadre groc) en cada moment.
També hem creat tres variables llista 'X-inici', 'Y-inici' i 'victoria'. Les dues primeres contenen les coordenades x i y, inicials del ninot per a cada nivell del joc, i a la tercera hi posarem el nombre de quadrats grocs que té cada nivell.(condició de victòria).
Creem dos missatges nous 'nivell' i 'avalua' que serviran per comunicar els diferents blocs que escriurem a continuació.
En l'objecte 'etapa', secció programa escrivim el següent bloc.
I modifiquem de nou l'inici dels blocs del ninot de la manera següent.
Ara modificarem el bloc de codi del ninot 'mou' perquè modifiqui les variables 'comptador' i 'passos' cada cop que calgui.
Vegeu que només ens ha fet falta afegir tres instruccions per aconseguir-ho
Ara escriurem un nou bloc en l'objecte 'etapa' que ens permeti detectar la condició de victòria i canvi de nivell.
Només ens fa falta cridar aquest bloc cada vegada que incrementem la variable 'comptador'. Afegim la instrucció corresponent de la forma següent.
Per acabar afegirem un altre bloc que ens permeti navegar pel joc, és a dir, si premem la tecla 'n' avançarem un nivell, si premem la tecla 'p' retrocedirem un nivell i si premem la tecla 'r' reiniciarem el nivell actual.
Fes una quadrícula completa i desa l'arxiu com M6QuadrículaNomiCognom.sc