Sokoban (I)
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.
Regles del joc
-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 (a http://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
- Arranquem prement la bandera verda
- Inicialitzem els dos elements que contenen el programa, escenari (inicialitzem les variables, nivell a 1 i condició de victòria per aquest nivell) i ninot (posició inicial Xi, Yi i les variables, passos = 0, comptador = 0)
- El programa resta a l´espera de rebre una pulsació del teclat (fletxes)
- Si rep una pulsació orienta el ninot en la direcció indicada
- Llegeix les dues caselles següents en la direcció indicada (sensors vermell i blanc del ninot)
- Si la lectura indica moviment (veure taula de decisió) mou una casella en la direcció indicada
- Si no hi ha moviment, tornar al pas 3
- Sobreescriure les caselles llegides, segons la taula de decisió i tornar 3
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
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