Viimeisellä kouluviikolla jatkoimme animaatioiden kanssa Ylöjärven yhtenäiskoulussa. Palautimme mieleen asioita kahden viikon takaa: muuttuja, funktio, ehtolause, vertailuoperaatio sekä animaatiomoottori (animate).
Uutena asiana otimme cond-valintalauseen, että saimme animaation tekemään useampaa kuin kahta juttua. Jatkoimme viimekertaisen ympyräanimaation kehittelyä jokainen omaan suuntaansa.
Aloitimme oman animaation tekemisen ensin vaihtamalla ympyrän johonkin muuhun kuvaan esim. tähteen (star, radial-star) ja vaihtamalla sille värin. Sitten muutimme koodin niin, että if:in tilalle vaihdettiin cond.
(define (oma-kuva t)
(cond [(< t 250)
(star t "solid" "purple")]
[else
(circle t "solid" "red")]))
Kaksi viikkoa oli aika pitkä aika muistaa se, että jos jätti tuon t:n pois ja kirjoitti vaikka 40 niin tähden koko ei muuttunut. Tässä tuli hyvin kerrattua jälleen kerran muuttujan käsite. Animaatiossa se vieläpä konkretisoituu niin hyvin, jos muuttuja ei ole käytössä niin kuva ei todellakaan muutu!
Cond-lause ei sinänsä tuottanut ongelmia mutta ehtojen säätäminen oli uusi asia, joka vaati miettimistä. Esim. moni kopioi ensimmäisen ehdon eikä vaihtanut lukuja, ja sitten ihmetteli miksi kolmas kuva ei koskaan tule esiin... No, miksiköhän ei?
(define (oma-kuva t)
(cond [(< t 250)
(star t "solid" "purple")]
[(< t 250)
(star t "solid" "yellow")]
[else
(circle t "solid" "red")]))
Toinen pohdinnan paikka tuli eteen siinä, kun animaatio piteni, jossain vaiheessa viimeiset kuvat putosivat pois. Tässä vaiheessa olisi pitänyt muistaa, että rajoitimme animaation t:n tietylle välillä. Jos olemme rajoittaneet t:n välille 0-199, tietenkään kuva jonka pitäisi tulla esiin kun t on 300-400 ei ikinä ilmesty. Tämän sai korjattua muokkaamalla modulo:a.
(define (kuva t)
(place-image (oma-kuva (modulo t 400))
250 250
(empty-scene 500 500)))
Viimekerralla tehty "kuha-kääntyy" funktio otetiin nyt käyttöön, kuvat laitettiin pyörimään, vaihtamaan väriä, suurenemaan ja pienenemään. Osa vaihtoi myös place-imageen x:n tilalle muuttujan, jolloin kuva lähti kulkemaan vasemmalta oikealla. Ja modulon avula se saatiin toistamaan samaan (nyt rajoittava arvo saatiin empty-scene:n leveydestä). Muutama oppilas lisäsi myös tekstiä animaatioonsa.
Tässä yksi animaatio, jossa kuva pyörii, liikkuu eteenpäin ja mukana on myös teksti:
torstai 17. joulukuuta 2015
tiistai 8. joulukuuta 2015
Muuttuja, lauseke ja funktio - tunti Tesomalla
Tesoman 8.luokan matematiikan ryhmä aloitti tutustumisen Racket-ohjelmointiin tänään. Esimmäiseksi tutustuimme siihen, että on olemassa lukuja ja merkkijonoja. Testasimme niitä interaktioikkunassa. Muuttujan käsitteeseen törmäsimme kun keksimme kirjoittaa merkkijonon ilman "hipsuja" ja DrRacket ilmoitti "this variable is not defined".
Seuraavaksi määrittelimme muuttujia (sekä merkkijonoja, että lukuja) määrittelyikkunassa definen avulla, ja testasimme miksi luvussa ei saa olla hipsuja (sillä ei voi laskea).
(define a 5)
(define b 10)
Nyt kokeilimme laskea näiden muuttujien avulla esilaisia lausekkeita: yhteen-, vähennys-, kerto- ja jakolaskua (interaktioikkunassa):
> (+ a b)
> (- a b)
> (* a b)
> (/ a b)
Kokeilimme myös desimaalilukuja, negatiivisia lukuja sekä potenssiin korottamista expt:in avulla:
> (expt a b)
Sitten tutustuimme funktion käsitteeseen: sen avulla voidaan kirjoittaa laskusääntö, että jokin toiminto saadaan automatisoitua (esim. lentokoneen autopilotti). Piirsin taululle seuraavan kuvan:
Tämän koodasimme sitten funktioksi:
(define (plus3 a)
(+ a 3))
Lisäsimme vielä lopuksi sille selityksen kommenttiriville:
; plus3 : Luku -> Luku
Lopuksi testasimme mitä tapahtuu kun funktiota kutsutaan eri arvoilla. Osa tajusi heti mitä seuraava rivi palauttaa:
> (plus3 100)
Tämän jälkeen ehdotin, että oppilaat olisivat tehneet jonkun oman funktion, mutta aika loppui kesken (ja olihan tässäkin jo hirveästi asiaa yhdelle oppitunnille). Seuraavalla kerralla jatkamme polynomifunktioiden kirjoittamista ja niiden kuvaajien piirtämistä DrRacket:illä.
Seuraavaksi määrittelimme muuttujia (sekä merkkijonoja, että lukuja) määrittelyikkunassa definen avulla, ja testasimme miksi luvussa ei saa olla hipsuja (sillä ei voi laskea).
(define a 5)
(define b 10)
Nyt kokeilimme laskea näiden muuttujien avulla esilaisia lausekkeita: yhteen-, vähennys-, kerto- ja jakolaskua (interaktioikkunassa):
> (+ a b)
> (- a b)
> (* a b)
> (/ a b)
Kokeilimme myös desimaalilukuja, negatiivisia lukuja sekä potenssiin korottamista expt:in avulla:
> (expt a b)
Sitten tutustuimme funktion käsitteeseen: sen avulla voidaan kirjoittaa laskusääntö, että jokin toiminto saadaan automatisoitua (esim. lentokoneen autopilotti). Piirsin taululle seuraavan kuvan:
![]() |
| Oppilaat saivat keksiä muuttujan nimen ja funktion säännön itse |
(define (plus3 a)
(+ a 3))
Lisäsimme vielä lopuksi sille selityksen kommenttiriville:
; plus3 : Luku -> Luku
Lopuksi testasimme mitä tapahtuu kun funktiota kutsutaan eri arvoilla. Osa tajusi heti mitä seuraava rivi palauttaa:
> (plus3 100)
Tämän jälkeen ehdotin, että oppilaat olisivat tehneet jonkun oman funktion, mutta aika loppui kesken (ja olihan tässäkin jo hirveästi asiaa yhdelle oppitunnille). Seuraavalla kerralla jatkamme polynomifunktioiden kirjoittamista ja niiden kuvaajien piirtämistä DrRacket:illä.
Turtle-testausta Kaukajärvellä
Viime perjantaina joukko 8.luokan oppilaita ohjelmoi Racket Turtlea tekemään erilaisia geometrisia kuvioita. Ensimmäiseksi latasimme DrRacket:in Package Managerin avulla "teachpacks" paketin, jossa myös Racket Turtle - kirjasto on. Sitten latasimme Koodausta kouluun materiaalin sivuilta valmiin koodin, joka piirtää neliön. Tutkimme koodia yhdessä hidastetun piirtotoiminnon (step-by-step) avulla ja kun Turtlen ohjaamislogiikka oli selvillä oppilaat saivat tehtäväksi muuttaa koodi piirtämään kolmion. Osa sai kolmion valmiiksi nopeasti ja he siirtyivät kuusikulmioon ja neljäkkääseen. Kun kaikki olivat saaneet kolmion valmiiksi, näytin miten kuusikulmion sai tehtyä kätevämmin repeat - komennon avulla.
(define sivu
(list (forward 100)
(turn-left 60)))
(define kuusikulmio
(repeat 6 sivu))
(draw kuusikulmio)
Näytin vielä miten repeat:in avulla voi toistaa myös aikaisemmin piirretyn kuvion:
(define neliöt
(repeat 4 neliö))
Kun repeat oli hanskassa ryhdyimme leikkimään sen avulla, ja toistimme jo valmiiksi saatuja peruskuvioita: neliötä, kolmiota, kuusikulmiota tai neljäkästä. Jotta kaikki kuviot eivät olisi vain sinisiä opettelimme vaihtamaan myös väriä change-color:in avulla. Osa oppilaista opetteli myös pen-up, pen-down ja go-to komennot, jotta sai kuvansa nätisti keskelle piirtoaluetta. Lopuksi oppilaat saivat ladata itse piirtämänsä Turtle-kuvan Padlet-seinälle kaikkien ihailtavaksi. Tällaisia niistä sitten tuli:
Tämä ryhmä oli jo aikaisemmin tutustunut DrRacket:iin piirtämällä peruskuvioita sekä yhdistettyjä kuvia ja näiden Turtle kuvien tekemiseen meni yksi kaksoistunti.
(define sivu
(list (forward 100)
(turn-left 60)))
(define kuusikulmio
(repeat 6 sivu))
(draw kuusikulmio)
Näytin vielä miten repeat:in avulla voi toistaa myös aikaisemmin piirretyn kuvion:
(define neliöt
(repeat 4 neliö))
Kun repeat oli hanskassa ryhdyimme leikkimään sen avulla, ja toistimme jo valmiiksi saatuja peruskuvioita: neliötä, kolmiota, kuusikulmiota tai neljäkästä. Jotta kaikki kuviot eivät olisi vain sinisiä opettelimme vaihtamaan myös väriä change-color:in avulla. Osa oppilaista opetteli myös pen-up, pen-down ja go-to komennot, jotta sai kuvansa nätisti keskelle piirtoaluetta. Lopuksi oppilaat saivat ladata itse piirtämänsä Turtle-kuvan Padlet-seinälle kaikkien ihailtavaksi. Tällaisia niistä sitten tuli:
| Kauksun Turtle-Padlet |
keskiviikko 2. joulukuuta 2015
Kämmenniemen koulun 9. luokan piilokuvatestausta
Ennen näitä tunteja Kämmenniemen koulun 9. luokka oli koodannut tänä syksynä Racket:illä jo vaikka mitä: peruskuvia (lippuja ja autoja), pinta-alafunktioita sekä avaruuskappaleiden levityskuvia. Tällä kaksoistunnilla tarkoitus oli tutustua totuusarvoihin, ehtolauseisiin sekä tehdä piilokuvaharjoitus.
Ensimmäisellä tunnilla lähdimme liikkeelle totuusarvoista. Kirjoitimme interaktioikkunaan true ja false totesimme, että ne ovat arvoja kuten luvut ja merkkijonotkin. Sitten kokeilimme vertailuoperattoreita. Annoimme ensin muuttujalle a arvon viisi, ja sitten teimme vertailuja sillä seuraavasti:
> (define a 5)
> (< a 5)
#false
> (= a 5)
#true
Tästä pääsimmekin sitten ehtolauseeseen (if), kokeilimme myös sitä interaktioikkunassa. Tätä testattiin muutaman kerran eri ehdoilla (if - lause palautettiin interaktioikkunaan painamalla Crtl+nuoliylös):
> (if (< a 5)
"pienempi kuin 5"
"suurempi tai yhtäsuuri")
Koska ryhmä oli tehnyt jo funktioita aikaisemmin, lähdimme tekemään funktioita, jotka käyttävät ehtolausetta hyväkseen. Ensimmäiseksi teimme funktion "lämmitin", jonka tehtävänä olisi pitää luokkahuone lämpimänä: aina kun lämpötila laskisi alle 22 astetta, lämmitin menisi päälle. Aivan ensimmäiseksi mietimme mitä muuttujia funktio tarvitsee ja mitä se palauttaa:
;; lämmitin : Luku -> Merkkijono
Sitten kirjoitimme funktiolle rungon eli stub:in:
(define (lämmitin t)
"")
Sitten suunnittelimme funktion toiminnan käyttämällä check-expect - lauseita:
(check-expect (lämmitin 20)
"lämmitin päälle")
(check-expect (lämmitin 25)
"lämmitin pois päältä")
(check-expect (lämmitin 22)
"lämmitin pois päältä")
Nyt tiesimme mitä funktiolta odotetaan, joten pystyimme täydentämään funktion rungon valmiiksi:
(define (lämmitin t)
(if (< t 22)
"lämmitin päälle"
"lämmitin pois päältä"))
Tämän jälkeen oppilaat saivat suunnitella funktion "portsari", jonka piti päästää baariin sisälle vain täysi-ikäiset henkilöt. Tämä sujui hyvin, tosin osa portsareista ei ollut erityisen kohteliaita alaikäisille asiakkailleen. Toimivan portsarin jälkeen teimme vielä bussin "rahastaja":n, jonka piti matkustajan iän perustella palauttaa bussimatkan hinta. Päätimme, että hintaluokkia olisi: lapsi, nuori ja aikuinen (osa oppilaita otti mukaan myös seniorit). Tämäkin funktio tehtiin funktion suunnitteluportaiden avulla.
;; rahastaja : Luku -> Luku
(define (rahastaja ikä)
0)
Sitten check-expect:it:
(check-expect (rahastaja 10)
1)
(check-expect (rahastaja 13)
1.20)
(check-expect (rahastaja 23)
2)
(check-expect (rahastaja 18)
2)
(check-expect (rahastaja 12)
1.2)
Ja lopuksi funktio, jossa käytimme nyt cond - valintalausetta, että saimme useamman ehdon toimimaan kätevästi (perusrakenteen teimme yhdessä, tarkemman säädön jokainen sai tehdä itse):
(define (rahastaja ikä)
(cond [(>= ikä 18) 2]
[(< 11 ikä 18) 1.2]
[else 1]))
Tämä funktio oli jo niin monimutkainen, että check-expectejä todellakin tarvittiin sen testaamiseen ja koodin saamiseksi oikein. Ensimmäisellä yrittämällä moni 18 täyttänyt pääsi nimittäin lastenlipulla (kun = merkki oli unohtunut koodista) eli rajatilanteiden testaaminen todellakin kannatti.
Näiden harjoitusten jälkeen otimme projektiksi piilokuvaharjoituksen. Koodiin tutustumisen jälkeen tehtäväksi tuli muuttaa koodia niin, että se tuottaa Saksan lipun. Tähän menikin sitten kaksoistunnin loppuaika ja lähes kaikki saivat lippunsa toimimaan. Yksi oppilas taisi ehtiä tehdä myös hieman haastavamman Suomen lipunkin.
Ensimmäisellä tunnilla lähdimme liikkeelle totuusarvoista. Kirjoitimme interaktioikkunaan true ja false totesimme, että ne ovat arvoja kuten luvut ja merkkijonotkin. Sitten kokeilimme vertailuoperattoreita. Annoimme ensin muuttujalle a arvon viisi, ja sitten teimme vertailuja sillä seuraavasti:
> (define a 5)
> (< a 5)
#false
> (= a 5)
#true
Tästä pääsimmekin sitten ehtolauseeseen (if), kokeilimme myös sitä interaktioikkunassa. Tätä testattiin muutaman kerran eri ehdoilla (if - lause palautettiin interaktioikkunaan painamalla Crtl+nuoliylös):
> (if (< a 5)
"pienempi kuin 5"
"suurempi tai yhtäsuuri")
Koska ryhmä oli tehnyt jo funktioita aikaisemmin, lähdimme tekemään funktioita, jotka käyttävät ehtolausetta hyväkseen. Ensimmäiseksi teimme funktion "lämmitin", jonka tehtävänä olisi pitää luokkahuone lämpimänä: aina kun lämpötila laskisi alle 22 astetta, lämmitin menisi päälle. Aivan ensimmäiseksi mietimme mitä muuttujia funktio tarvitsee ja mitä se palauttaa:
;; lämmitin : Luku -> Merkkijono
Sitten kirjoitimme funktiolle rungon eli stub:in:
(define (lämmitin t)
"")
Sitten suunnittelimme funktion toiminnan käyttämällä check-expect - lauseita:
(check-expect (lämmitin 20)
"lämmitin päälle")
(check-expect (lämmitin 25)
"lämmitin pois päältä")
(check-expect (lämmitin 22)
"lämmitin pois päältä")
Nyt tiesimme mitä funktiolta odotetaan, joten pystyimme täydentämään funktion rungon valmiiksi:
(define (lämmitin t)
(if (< t 22)
"lämmitin päälle"
"lämmitin pois päältä"))
Tämän jälkeen oppilaat saivat suunnitella funktion "portsari", jonka piti päästää baariin sisälle vain täysi-ikäiset henkilöt. Tämä sujui hyvin, tosin osa portsareista ei ollut erityisen kohteliaita alaikäisille asiakkailleen. Toimivan portsarin jälkeen teimme vielä bussin "rahastaja":n, jonka piti matkustajan iän perustella palauttaa bussimatkan hinta. Päätimme, että hintaluokkia olisi: lapsi, nuori ja aikuinen (osa oppilaita otti mukaan myös seniorit). Tämäkin funktio tehtiin funktion suunnitteluportaiden avulla.
;; rahastaja : Luku -> Luku
(define (rahastaja ikä)
0)
Sitten check-expect:it:
(check-expect (rahastaja 10)
1)
(check-expect (rahastaja 13)
1.20)
(check-expect (rahastaja 23)
2)
(check-expect (rahastaja 18)
2)
(check-expect (rahastaja 12)
1.2)
Ja lopuksi funktio, jossa käytimme nyt cond - valintalausetta, että saimme useamman ehdon toimimaan kätevästi (perusrakenteen teimme yhdessä, tarkemman säädön jokainen sai tehdä itse):
(define (rahastaja ikä)
(cond [(>= ikä 18) 2]
[(< 11 ikä 18) 1.2]
[else 1]))
Tämä funktio oli jo niin monimutkainen, että check-expectejä todellakin tarvittiin sen testaamiseen ja koodin saamiseksi oikein. Ensimmäisellä yrittämällä moni 18 täyttänyt pääsi nimittäin lastenlipulla (kun = merkki oli unohtunut koodista) eli rajatilanteiden testaaminen todellakin kannatti.
Näiden harjoitusten jälkeen otimme projektiksi piilokuvaharjoituksen. Koodiin tutustumisen jälkeen tehtäväksi tuli muuttaa koodia niin, että se tuottaa Saksan lipun. Tähän menikin sitten kaksoistunnin loppuaika ja lähes kaikki saivat lippunsa toimimaan. Yksi oppilas taisi ehtiä tehdä myös hieman haastavamman Suomen lipunkin.
| Saksan lipun avulla opeteltiin valintalausetta ja vertailuoperaattoreita |
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")
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ä.
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 |
(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ä |
tiistai 24. marraskuuta 2015
Racket - iskuryhmän kolmas workshop
Tämän syksyn viimeisessä workshopissa kehittelimme tutustuimme Koodiaapinen MOOC:in Racket osion toteutukseen ja ideoimme tehtäviä todennäköisyyslaskennan, polynomilaskennan sekä suoraan- ja kääntäen verrannollisuuden opiskelemiseen.
1) Suoraan verrallisuuden havainnollistamiseen ideoitiin mopon kulutuksen koodaamista funktioksi, pisteiden laskemista ja plottaamista sekä suoran piirtämistä samaan kuvaan. Tämä vaatii lisäyksiä plot2D-kirjastoon.
2) Todennäköisyyslaskennasta voisi tehdä nopanheittosimulaattorin, eli arpoa 10, 100 ja 1000 nopan silmälukua ja piirtää niistä palkkidiagrammit ja verrata lähenevätkö ne laskettua todennäköisyyttä. Keskustelimme paljon siitä, tuottaako tietokone aidosti satunnaisia lukuja ja päätimme, että tämä täytyy vain testata.
3) Todennäköisyyttä voisi havainnoida myös radioaktiivisten atomien puoliintumisajan simulaation tai "tuplaa-panos"-pelisimulaation avulla (pienillä korteillä 1-6 tai isoilla korteilla 8-13 voittaa, 7 häviää aina).
4) Tutustuimme myös siihen miten Turtlelle saadaan generoitua map:in avulla pitkiä komentolistoja, ja teimmekin "random-Turtlen", joka kulki satunnaisen matkan satunnaiseen suuntaan. Tämä oli hauska eikä ollenkaan vaikea toteuttaa!
5) Lopuksi vielä pohdimme miten polynomilaskentaan voisi tuoda ohjelmointia, ja totesimme että lähdemme liikkeelle lausekkeen arvon laskemisesta ja teemme sitten jonkun oikeaan mittausdataan liittyvän polynomisovitteen kuvaajat.
Uusia ideoita siis syntyy jatkuvasti kun tämä joukko kokoontuu, nyt pitäisi vain työstää nämä tehtävien muotoon...
Tähän asti materiaalista on testattu peruslaskut ja peruskuvat, sekä geometriaan liittyviä funktioita ja ehtolauseista piilokuvat. Ensiviikolla testaukseen siirtyvät animaatiot sekä Turtle. Funktioiden parempi testaus siirrettiin keväälle, koska se tulee 9. matematiikassa esille vasta keväällä.
Random-Turtle kulkua (500 kierrosta):
Koodi:
(require teachpacks/racket-turtle)
(define (kierros i)
(list (turn-left (random 360))
(forward (random 20))))
(define RANDOM-TURTLE (map kierros (range 0 500 1)))
(draw RANDOM-TURTLE)
1) Suoraan verrallisuuden havainnollistamiseen ideoitiin mopon kulutuksen koodaamista funktioksi, pisteiden laskemista ja plottaamista sekä suoran piirtämistä samaan kuvaan. Tämä vaatii lisäyksiä plot2D-kirjastoon.
2) Todennäköisyyslaskennasta voisi tehdä nopanheittosimulaattorin, eli arpoa 10, 100 ja 1000 nopan silmälukua ja piirtää niistä palkkidiagrammit ja verrata lähenevätkö ne laskettua todennäköisyyttä. Keskustelimme paljon siitä, tuottaako tietokone aidosti satunnaisia lukuja ja päätimme, että tämä täytyy vain testata.
3) Todennäköisyyttä voisi havainnoida myös radioaktiivisten atomien puoliintumisajan simulaation tai "tuplaa-panos"-pelisimulaation avulla (pienillä korteillä 1-6 tai isoilla korteilla 8-13 voittaa, 7 häviää aina).
4) Tutustuimme myös siihen miten Turtlelle saadaan generoitua map:in avulla pitkiä komentolistoja, ja teimmekin "random-Turtlen", joka kulki satunnaisen matkan satunnaiseen suuntaan. Tämä oli hauska eikä ollenkaan vaikea toteuttaa!
5) Lopuksi vielä pohdimme miten polynomilaskentaan voisi tuoda ohjelmointia, ja totesimme että lähdemme liikkeelle lausekkeen arvon laskemisesta ja teemme sitten jonkun oikeaan mittausdataan liittyvän polynomisovitteen kuvaajat.
Uusia ideoita siis syntyy jatkuvasti kun tämä joukko kokoontuu, nyt pitäisi vain työstää nämä tehtävien muotoon...
Tähän asti materiaalista on testattu peruslaskut ja peruskuvat, sekä geometriaan liittyviä funktioita ja ehtolauseista piilokuvat. Ensiviikolla testaukseen siirtyvät animaatiot sekä Turtle. Funktioiden parempi testaus siirrettiin keväälle, koska se tulee 9. matematiikassa esille vasta keväällä.
Random-Turtle kulkua (500 kierrosta):
Koodi:
(require teachpacks/racket-turtle)
(define (kierros i)
(list (turn-left (random 360))
(forward (random 20))))
(define RANDOM-TURTLE (map kierros (range 0 500 1)))
(draw RANDOM-TURTLE)
maanantai 23. marraskuuta 2015
Racket - iskuryhmän toinen workshop
Racket - iskuryhmän toisessa workshopissa tutustuimme animaatioihin, joissa muuttujana on aika. Teimme ensin ufon laskeutumisanimaation, sitten laitoimme sen "rullaamaan" käyttämällä moduloa. Sitten käänsimme ufon kulkusuunnan nousuun, ja lopuksi teimme samaan animaatioon molemmat. Tässä harjoituksessa käytettiin ehtolauseita (if), valintalauseita (cond) sekä vertailuoperaattoreita (<, >, <=, >=, =). Kun systeemi oli selvillä iskuryhmän opettajat kokeilivat tehdä omia animaatioita, suurenevia ja pieneneviä palloja, väriä vaihtavia ja pyöriviä propelleja ja syntyi myös yksi pomppiva pallo joka "jousti" pompatessaan (litistyi ellipsiksi).
Animaation tekeminen havaittiin yllättävän matemaattiseksi harjoitukseksi, siinä joutui tekemään kuvan piirtofunktion (joutui miettimään muuttujia ja vakioita), miettimään jakojäännöstä (modulo) ja suunnittelemaan ehdollista suorittamista.
Käytimme tässä harjoituksessa big-bangiä, vaikka animate - funktio olisi toiminut aivan vastaavalla tavalla.
Tässä ufo-esimerkkianimaatio WeScheme:llä:
http://www.wescheme.org/view?publicId=f6lWg5Hmdg
Animaation tekeminen havaittiin yllättävän matemaattiseksi harjoitukseksi, siinä joutui tekemään kuvan piirtofunktion (joutui miettimään muuttujia ja vakioita), miettimään jakojäännöstä (modulo) ja suunnittelemaan ehdollista suorittamista.
Käytimme tässä harjoituksessa big-bangiä, vaikka animate - funktio olisi toiminut aivan vastaavalla tavalla.
Tässä ufo-esimerkkianimaatio WeScheme:llä:
http://www.wescheme.org/view?publicId=f6lWg5Hmdg
![]() |
| Yksinkertainenkin ufon lennättäminen vaatii matematiikkaa! |
Tilaa:
Blogitekstit (Atom)




