keskiviikko 2. joulukuuta 2015

Ylöjärven yhtenäiskoulussa koodattiin animaatioita

Olin maanantaina testaamassa Koodausta kouluun materiaalin animaatioharjoitusta Ylöjärven yhtenäiskoulussa. Testiryhmänä toimi puolikas 8.luokan ryhmä, joka oli aikaisemmin jo koodannut 2-3 tuntia Racket:illä (peruslaskuja, lippuja sekä autoja).

Nyt siirryimmekin jo aivan toiselle tasolle eli tutustuimme funktioiden määrittelemiseen, totuusarvoihin, vertailuoperaattoreihin sekä ehtolauseeseen. Aloitimme kertaamalla muuttujan käsitteen. Lippuja koodattaessa olimme käyttäneet jo muuttujia, ja palautimme mieleen miten muuttuja määritellään define:n avulla:

(define a 100)
(define väri "red")

Tämän jälkeen tutkimme miten saisimme tehtyä ympyrän, jonka säde ja väri on ilmoitettu muuttujien  avulla ja päädyimme tähän:

(circle a "solid" väri)

Nyt kokeilimme muuttaa a:n ja väri:n arvoa definessä ja huomasimme, että ympyräkin muuttui samalla. Tästä pääsimme hyvin siihen, että tarvitsemme muuttujia, mutta ne eivät pelkästään riitä, vaan meidän pitää saada nämä arvot jostakin, joten kirjoitimme tuon koodin ympärille funktion määritelmän:

(define (ympyrä a väri)
   (circle a "solid" väri))
  
Tätä testattiin interaktioikkunasta eri arvoilla ja todettiin se toimivaksi.

(ympyrä 100 "yellow")
(ympyrä 50 "blue")

Funktio-testausta
Nyt oppilaat saivat tehtäväksi määritellä jonkin toisen funktion, joka tekisi eri muotoisen kuvan. Tässä vaiheessa palautimme mieleen miten piirtofunktioita etsittiin Koodarin käsikirjasta. Teimme myös funktion, joka saa sisäänsä kuvan, jota se kiertää x astetta vastapäivään. Myös tätä testattiin.

(define (kierrä kuva asteet)
   (rotate asteet kuva))

Yksi pojista oli aikaisemmin koodannut USA:n lipun ja testaili sen pienentämistä ja suurentamista scale - funktion avulla.

Toisella tunnilla aloitimme tutustumaan animaatioihin. Kerroin animation - funktion toiminnasta, kuinka se kutsuu meidän "oma-kuva" - funktiota 28 kertaa sekunnissa luvuilla 0, 1, 2, 3, 4 ... jne. Selitin myös taululla piirtämäni kuvan avulla, miten empty-scene ja place-image toimivat. Sitten latasimme valmiin animaatiopohjan oppilaan tehtävät sivulta.

Kun painoimme "run", totesimme, että animaation punainen ympyrä ei värähdäkään ja pyysin oppilaita korjaamaan asian. Tämä oli yllättävän vaikeaa, vaikka olimme juuri tehneet vastaavan ympyrä - funktion, erot olivat vain pintapuolisia: funktion nimi oli eri (ympyrä vs. oma-kuva) ja muuttujan nimi oli eri (a vs. t). Pienen lypsämisen jälkeen joku ryhmästä keksi sen: muuttujaa pitää käyttää koodissa! Vaihdoimme siis 100:n t:ksi ja animaatio alkoi toimia.
 
(define (oma-kuva t)
  (circle 100 "solid" "red"))


Seuraava oppilaiden ihmettelyn aihe oli se, että miksi se vain jatkaa kasvamistaan. Miksi se ei pienene. Tähän oli helpompi vastata: koska sitä ei ole ohjelmoitu pienenemään. Se on ohjelmoitu vain suurenemaan. Tästä pääsimme hyvin siihen, että jotta se voisi pienentyä tarvitsemme koodiimme kaksi haaraa: "suureneva ympyrä" - haaran ja "pienenevä ympyrä" - haaran.

Lähdimme tutustumaan ehtolauseen käyttöön tutkimalla interaktioikkunassa ensin vertailuoperaattoreita <, > ja =. Kerroin, että nämä palauttavat totuusarvoja: #true ja #false ja että nämä ovat se tapa, jolla koodi saadaan haarautumaan "tosihaaraan" ja "epätosihaaraan".

>  (< 100 150)
#true

Näiden testailujen jälkeen testasimme interaktioikkunassa if-lausetta:

> (if (< 100 150) 
        "totta mooses"
        "väärin meni")

Kun kaikki olivat saaneet sekä "totta mooses" että "väärin meni" toimimaan, jatkoimme animaation kimpussa. Teimme siis ehtolauseen oma-kuva - funktioon.

(define (oma-kuva t)
  (if (< t 300)
      (circle t "solid" "red")

      (circle t "solid" "red")))

Nyt alkoikin sitten kova miettiminen miten ympyrä saadaan pienenemään eli mitä t:lle pitäisi tehdä. Kysyin oppilailta, että mikä laskutoimitus pienentää, ja vastaus löytyi heti: vähennyslasku. Sitten olikin hieman enemmän epäselvää mitä pitää vähentää mistäkin... Kun logiikkaa ei heti löytynyt totesin, että kokeillaan jotain, sitten nähdään mitä tapahtuu ja voidaan korjata sitä. Kokeilimme siis vähentää t:stä ensimmäisen ehdon raja-arvon (300).

(define (oma-kuva t)
  (if (< t 300)
      (circle t "solid" "red")
      (circle (- t 300) "solid" "red")))


Nyt ympyrä ei pienentynyt vaan palasi pieneksi ja lähti uudelleen suurenemaan. No seuraavaksi kokeilimme laittaa t:n ja 300 toisinpäin ehkäpä se auttaisi pienenemisessä?

(define (oma-kuva t)
  (if (< t 300)
      (circle t "solid" "red")
      (circle (- 300 t) "solid" "red")))


Nyt saimme tällaisen virheilmoituksen:
circle: expects a non negative real number as first argument, given -1

Tämän virheilmoituksen tulkinta oli helppoa: ympyrän säde ei voi olla negatiivinen. Ja negatiivinen säteen arvo koodissamme tulee heti kun t menee yli 300, koska:

> (- 300 301)
-1

Totesimme, että ehkä meidän pitää oikeasti miettiä miten tämän pitäisi toimia. Teimme seuraavan taulukon Word:illä:



Saimme tehtyä punaisen rivin perusteella yhtälön:

x - 301 = 299

Ja tämä saataiin ratkaistua:

x = 600

Ja nyt saimme lisättyä oikean arvon koodiimme:

(define (oma-kuva t)
  (if (< t 300)
      (circle t "solid" "red")
      (circle (- 600 t) "solid" "red")))


Ja nyt ympyrämme sekä suureni, että pieneni mutta törmäsimme lopuksi taas samaan ongelmaan:

circle: expects a non negative real number as first argument, given -1

Tämä oli jo helpompi ymmärtää, koska tässä toistui sama ongelma kuin ennenkin, nyt t menee yli 600 ja säde menee taas miinukselle:

> (- 600 601)
-1

Tähän otimme ratkaisuksi jakojäännöksen eli koodauskielellä modulon. Modulon avulla voidaan rajoittaa t:n arvot välille 0-599, jolloin emme joudu koskaan negatiivisiin säteisiin. Jakojäännöksen käsite oli hyvin hallussa oppilailla, koska seuraava päättely ei tuottanut mitään ongelmia:

601 / 600 jakojäännös on 1
602 / 600 jakojäännös on 2
603 / 600 jakojäännös on 3
...

Lisäsimme modulon koodiin ja animaatiomme toimi nyt niinkuin pitääkin.

(define (kuva t)
  (place-image (oma-kuva (modulo t 600)

                250 250 
               (empty-scene 500 500)))
Nyt oppilaat saivat muuttaa ympyrän muodon joksikin toiseksi, muuttaa värit haluamakseen jne. Yksi oppilas keksi kysyä miten animaatioon saisi enemmän haaroja, ja selitin miten valintalause (cond) toimii. Seuraavalla kerralla jatkamme näitä oppilaiden omia animaatioita, ehkäpä cond-lauseella terästettynä.
Yksinkertaisen ympyrä-animaation takana on yllättävän paljon matematiikkaa ja ohjelmointitietämystä

Ei kommentteja:

Lähetä kommentti