Aliohjelmat

Aliohjelmat

Tässä vaiheessa oppimateriaalia olemme käyneet läpi joukon erilaisia ohjelmoinnin työkaluja, joita hyödyntäen miltei minkälaisten tahansa ohjeiden muotoilu tietokoneen ymmärtämään muotoon on mahdollista. Näitä ovat toistorakenteet, ehtolauseet, operaattorit, muuttujat ja tietorakenteet. Silti olisi kätevämpää, jos meillä olisi lisäksi jokin menetelmä jäsennellä ohjeitamme. Etenkin viime luvun soveltavissa tehtävissä koodilla oli taipumus kasvaa paikoitellen jo melko pitkäksi ja epäselväksi kokonaisuudeksi. Asiaa helpottaisikin, jos voisimme jakaa ohjelmiamme pienempiin, helposti ymmärrettäviin paloihin. Jos näitä palasia pystyisi lisäksi uudelleenkäyttämään, välttäisimme myös turhaa toistoa.




Arvattavasti ohjelmoinnissa on olemassa myös työkalut tämän tarpeen täyttämiseksi. Niitä kutsutaanaliohjelmiksi. Aliohjelmat ovat itsenäisiä, yleensä pienimuotoisia, ohjelman osia, jotka suorittavat jonkin yksittäisen toiminnon. Tietyissä konteksteissa aliohjelmista puhutaan myös rutiineina tai funktioina.

Määrittelykysymys

Scratchissa eräs tapa toteuttaa aliohjelmia on luoda omia ohjepalikoita. Luodaan kokeeksi yksinkertainen kokonaan itse määrittelemämme palikka. Avaa Lisää lohkoja -valikko ja klikkaa sieltä Tee palikka -nappia. Eteesi aukeaa seuraavanlainen näkymä:


Tee palikka -ikkunan avulla voimme luoda uuden ohjepalikan.

Kirjoita ikkunassa näkyvän violetin palikan tekstikenttään nimi ”tee voltti” ja paina OK-nappia. Lisää lohkoja -valikkoon ilmestyy uusi tee voltti -ohjepalikka. Lisäksi saamme käyttöömme oikealla näkyvän, ison määrittele ’tee voltti’ -palikan.


Uudet luomamme palikat, joiden avulla voimme toteuttaa aliohjelman.

Määrittele ’tee voltti’ -palikan alle luomme varsinaisen aliohjelmamme. Kokoa sen alle seuraavat ohjeet:


Tämä aliohjelma komentaa kissaa hyppäämään voltin.

Klikkaa nyt tee voltti -ohjepalikkaa. Huomaat, että kissa suorittaa kaikki ohjeet, jotka sisällytimme aliohjelmaamme määrittele ’tee voltti’ -palikan alle.

Tehtävä 1: Kuin tsiljoona volttia

Luo ohjelma, joka käskee kissaa hypäämään ensin viiden voltin verran, kuten Kuin miljoona volttia -tehtävässä. Jokaisen voltin välissä liikutaan eteenpäin 20 pykälää ja naukaistaan. Tämän jälkeen hypätään vielä uudelleen viiden voltin verran, kuten aiemmin, mutta tällä kertaa liikutaan joka voltin välissä 20 pykälää taaksepäin ja naukaistaan. Naukaisut suoritetaan molemmissa tapauksissa loppuun.

Käytä ohjelmassa hyväksesi äsken luomaamme aliohjelmaa sekä tee voltti -ohjepalikkaa. Ohjepalikoiden, jotka kertovat kissalle, miten voltti hypätään, pitäisi esiintyä siis koko koodissa vain kertaalleen. Tee voltti -komentoa pitäisi sitä vastoin käyttää useammin kuin kerran. Voit halutessasi asettaa ohjelmasi käynnistymään vihreän lipun klikkauksesta.

Yleensä aliohjelmille annetaan jonkinlainen nimi, joka kuvastaa niiden sisältämiä ohjeita. Tällä tapaa aliohjelmilla onkin helppo selkeyttää oman koodin sisältämiä ohjeita. Äskeisessä esimerkissä annoimme palikallemme nimeksi ”tee voltti”, josta voi helposti päätellä, minkä toimenpiteen palikka käskee Scratch-hahmoa suorittamaan.

Aliohjelmille tavanomaista on myös uudelleenkäytettävyys eri puolella ohjelmaa. Tämän ansiosta niillä on helppo välttää koodissa turhaa toistoa. Ohjelmoinnissa komentoa, joka käskee suorittamaan aliohjelman sisältämät ohjeet, sanotaan aliohjelman kutsuksi. Äskeisessä Scratch-koodissamme aliohjelmaamme kutsuu tee voltti -palikka. Tämä palikka on ohjelmassamme siis tee voltti -aliohjelman kutsu. Ohjeita, jotka eivät sisälly mihinkään aliohjelmista, sanotaan puolestaan pääohjelmaksi.


Kuvassa havainnollistettuna aliohjelman, pääohjelman ja aliohjelman kutsun käsitteet.

Kaikki ohjeet, jotka muodostavat koodissa selkeän oman kokonaisuutensa, on syytä ryhmitellä omiksi aliohjelmikseen. Kokonaisuudet kannattaa kuitenkin miettiä hyvin tarkkaan, sillä emme halua, että aliohjelmamme tekevät mitään ylimääräistä omaan kokonaisuuteensa kuulumatonta. Olisimme esimerkiksi edellisessä tehtävässä voineet sisällyttää toiston välttämiseksi myös naukumisen voltti-aliohjelmaamme, mutta jätimme sen tekemättä, koska naukuminen ei ole oleellinen osa voltin hyppäämistä. Ilman naukumista voimmekin uudelleenkäyttää voltti-aliohjelmaamme myös sellaisissa tapauksissa, joissa emme tahdo kissan naukuvan volttia hypätessä.

Tehtävä 2: Pingisrutiinit hallussa

Muokkaa edellisen luvun tehtävää 5. Luo uusi ohjepalikka nimeltä ”mene alkuun” ja rakenna sitä vastaava aliohjelma. Aliohjelman tulee käskeä palloa palaamaan takaisin alkupisteeseensä, osoittamaan vasemmalle ja odottamaan kaksi sekuntia. Korvaa pääohjelmasta molemmat tapaukset, joissa nämä kolme ohjepalikkaa esiintyvät, kutsulla uuteen aliohjelmaasi.

Testaa lopuksi ohjelmaasi. Sen pitäisi toimia täsmälleen samalla tavalla kuin ennenkin mutta tällä kertaa ilman turhaa ohjeiden toistoa.

Aliohjelmille ilmaantuu myös tarvetta tosielämässä. Aina kun ohjeita annettaessa tietty osajoukko ohjeita toistuu täysin tai lähes samanlaisina, ne voidaan koota muista ohjeista erilleen. Tämän jälkeen näihin ohjeisiin voidaankin yksinkertaisesti viitata sen sijaan, että ne toistettaisiin joka kerta sellaisinaan.

Munakas neljälle

* Sekoita kulhossa munat, kerma ja suola munakasmassaksi.
* Valmista munakasmassasta neljä munakasta. Katso ohjeet alta.
* Leikkaa makkarat pieniksi viipaleiksi.
* Pilko pekoni kuutioiksi.
* Paista makkarat ja pekonikuutiot pannulla.
* Lisää nokare voita, sipuli ja tomaatit.
* Hauduta viisi minuuttia ja mausta suolalla.
* Levitä neljäsosa täytteestä jokaisen munakkaan päälle.

Yhden munakkaan valmistus paistinpannussa:
* Kuumenna paistinpannussa pieni pala voita
* Kaada neljäsosa munakasmassasta paistinpannuun
* Anna munakkaan hyytyä pienellä lämmöllä. Nostele aika ajoin hieman reunoista.

Tätä reseptiä seuratessa lukijan täytyy poiketa aliohjelmaan ”Yhden munakkaan valmistus paistinpannussa” ymmärtääkseen koko ohjeiden sisällön.

Eräs esimerkki todellisen elämän aliohjelmista on tunnistettavissa jopa tästä opiskelumateriaalista. Voimme ensinnäkin ajatella koko oppimateriaalia kaikkien ohjeidemme runkona eli pääohjelmana. Tällöin puolestaan tutuksi tulleita ohjeita Scratch-ohjelman tallentamiseksi voisi pitää aliohjelmana, jonka sisältöä emme esitä toistuvasti sellaisenaan, vaan viittaamme siihen linkkien muodossa.

Ero tietokoneelle kirjoitetuissa aliohjelmissa ihmisille annettaviin aliohjelmiin on siinä, että ihminen on tietokonetta omapäisempi ohjeiden noudattaja. Toisin kuin tietokone, hän voikin päättää ohittaa aliohjelman suorituksen kokonaan.

Funktionaalinen muotoilu

Pythonissa aliohjelmille on myös oma toteutustapansa. Tätä aliohjelmien alaluokkaa kutsutaan ohjelmoinnissa yleisesti funktioiksi. Alla on esitelty Python-funktiona toteutettu aliohjelma, joka tulostaa näytölle kuvitteellisen ohjelman käyttöohjeet:

def näytä_ohjeet():
    print("Tervetuloa käyttämään maan mainiota ohjelmaa!")
    print("Paina Enter-näppäintä jatkaaksesi.")
    print("Lopettaa voit Esc-näppäimestä.")

Python-funktiona toteutettu aliohjelma nimeltä ”näytä_ohjeet”.

Kuten define-sanaa tarkoittavasta def-lyhenteestä voi jo arvata, ensimmäinen rivi koodia vastaa Scratchin määrittele-palikkaa. Aliohjelmalle täytyy myös Pythonissa antaa nimi. Tämän funktion nimi onkin kuvaavasti ”näytä_ohjeet”. Python-funktioiden nimissä ei voi olla välilyöntejä, joten siksi sanojen välillä käytetään alaviivaa. Loput kolme sisennettyä riviä muodostavat puolestaan varsinaisen aliohjelman. Ne vastaavat Scratchissa määrittele-palikan alle liitettyjä ohjepalikoita.

Aliohjelmakutsun kera koko koodi näyttäisi jotakuinkin tältä:

def näytä_ohjeet():
    print("Tervetuloa käyttämään maan mainiota ohjelmaa!")
    print("Paina Enter-näppäintä jatkaaksesi.")
    print("Lopettaa voit Esc-näppäimestä.")

näytä_ohjeet()
# Tästä jatkuisi varsinaisen pääohjelman koodi
# ...

Aliohjelma ja pääohjelma Python-koodina.

Koodissa näytä_ohjeet()-rivi, joka ei ala def-sanalla, vastaa aiemmin Scratchissa luomaamme tee voltti -ohjepalikkaa. Kyseessä on siis aliohjelman kutsu. Joka kerta, kun tässä Python-ohjelmassa halutaan suorittaa näytä_ohjeet-funktion sisältämät komennot, täytyykin kirjoittaa koodiin teksti ”näytä_ohjeet()”. Kaikki sisentämättömät rivit funktion alapuolella, mukaan lukien näytä_ohjeet()-rivi, muodostavat koodissa varsinaisen pääohjelman. Ohjelmaa suoritettaessa seurataan pääohjelman sisältämiä komentoja poiketen näytä_ohjeet-funktioon aina, kun sitä kutsutaan.

Havainnollistavana esimerkkinä seuraava – kieltämättä järjetön – ohjelma tuottaisi sen alapuolella esitetyn lopputuloksen:

def näytä_ohjeet():
    print("Tervetuloa käyttämään maan mainiota ohjelmaa!")
    print("Paina Enter-näppäintä jatkaaksesi.")
    print("Lopettaa voit Esc-näppäimestä.")

näytä_ohjeet()
näytä_ohjeet()
näytä_ohjeet()

Tässä Python-koodissa aliohjelmaa kutsutaan kolmesti pääohjelmassa.


Aliohjelman ohjeet suoritetaan kolme kertaa, joten tuloksena ohjeteksti tulostetaan näytölle kolme kertaa.

Python-pähkinä 1

Alla on esitetty aiemmin tutuksi tullut Python-kielinen kolikonheittopelimme, mutta tällä kertaa jäsenneltynä aliohjelmiin. Minkä nimiset aliohjelmat löydät koodista?

import random

puolet = ("kruuna", "klaava")

def pyydä_arvaus():
    """Pyydetään pelaajaa 1 arvaamaan."""
    pyyntö = "Pelaaja 1, valitse joko kruuna tai klaava: "
    arvaus = input(pyyntö)
    while arvaus not in puolet:
        print("Arvauksesi ei ole sallittu!")
        arvaus = input(pyyntö)
    return arvaus

def päättele_jäänyt(arvaus):
    """Päätellään pelaajalle 2 jäänyt vaihtoehto."""
    päätelty = 0 if puolet.index(arvaus) == 1 else 1
    puoli = puolet[päätelty]
    return puoli

def arvo_tulos(arvaus):
    """Arvotaan lopputulos ja ilmoitetaan voittaja."""
    tulos = random.choice(puolet)
    print("Arvottiin {tulos}".format(tulos=tulos))
    if tulos == arvaus:
        print("Pelaaja 1 voittaa!")
    else:
        print("Pelaaja 2 voittaa!")

arvaus = pyydä_arvaus()
puoli = päättele_jäänyt(arvaus)
print("Pelaaja 2:lle jää {puoli}".format(puoli=puoli))
arvo_tulos(arvaus)
Luettele koodissa esiintyvien aliohjelmien nimet

Argumentoinnin salat

Olemme tähän mennessä hyödyntäneet aliohjelmiamme välttämään identtisten ohjeiden turhaa toistoa. Ohjelmoinnissa täysin samanlaisena toistuva koodi ei silti ole suinkaan yleisin tapaus, jossa koodin sijoittamisesta omaan aliohjelmaansa on hyötyä.

Tavallisemmin ohjelmissa esiintyykin useaan kertaan jokin yleisemmän tason toimenpide, joka on joka kerta hyvin samanlainen mutta jonka suorittamisen yksityiskohdat saattavat vaihdella. Kissan hyppäämä voltti voisi olla yksi tällainen toimenpide: voltti saatetaan toistaa ohjelmassa monta kertaa, mutta tilanteesta riippuen esimerkiksi voltin nopeutta halutaan mahdollisesti muuttaa.


Nämä kaksi Scratch-koodinpätkää käskevät molemmat kissaa tekemään voltin, mutta toinen hitaammin ja toinen nopeammin. Kokeile niitä itse Scratch-editorissa!

Pohdimme aiemmin, että ohjeet voltin hyppäämiseksi muodostavat selkeän erillisen kokonaisuutensa. Jos haluamme kuitenkin säätää voltin hyppäysnopeutta tarpeen mukaan, meidän pitää tunnistaa kaikki tekijät, jotka vaikuttavat voltin nopeuteen. Tässä tapauksessa tekijöitä on vain yksi, nimittäin asteiden määrä, kuinka paljon yhtä käännöstä kohden käännytään. Mitä suurempi käännyttävän kulman asteiden määrä, sitä nopeampaa kissa pyörähtää voltin. Yhden käännöksen astelukema määrää myös, kuinka monta käännöstä pitää yhteensä suorittaa, jotta ollaan pyörähdetty täydet 360 astetta.

Asteita varten voisimme luoda oman muuttujansa, ja muotoilla koodimme uusiksi. Alla olevassa kuvassa asteet-muuttujan arvon pohjalta lasketaan, montako käännöstä tarvitaan kokonaiseen volttiin:


Tämä koodi saa kissan hyppäämään voltin nopeudella, joka riippuu asteet-muuttujan arvosta. Kokeile sitä editorissa! Muista luoda asteet-muuttuja ja antaa sille jokin arvo.

Kuvan koodimme laskee asteet-muuttujan arvon pohjalta, montako kertaa sen suuruinen käännös täytyy toistaa, jotta kissa hyppäisi kokonaisen voltin. Käydään vaihe vaiheelta läpi, miten koodi toimisi asteet-muuttujan arvon ollessa 57:

  • Jaamme ensin 360 astetta yhden käännöksen asteiden määrällä eli 57:llä. Saamme vastauksen desimaalilukuna.
\dfrac{360^{\circ}}{57^{\circ}} = 6{,}3257360=6,32
  • Vähentämällä tästä luvusta puolikkaan ja käyttämällä pyöristystä saamme pyöristettyä vastauksen alaspäin lähimpään kokonaislukuun. Toistorakenteen toistoja ei voi nimittäin suorittaa kuin kokonaisina silmukan kierroksina.
6{,}32 - 0{,}5 = 5{,}826,320,5=5,82
5{,}82 \approx 65,826
  • Kun tarvittavat käännökset käännökset on käännytty toistorakenteessa, täytyy vielä lopuksi kääntyä kokonaisesta voltista vajaaksi jäävä astemäärä, jos alkuperäinen jakolasku ei mennyt tasan. Tämän viimeisen käännöksen suuruuden laskemme jakojäännöstä hyväksi käyttäen.
\left(\dfrac{360^{\circ}}{57^{\circ}} - 6\right) \cdot 57^{\circ} = 18^{\circ}(573606)57=18

Tämän koodin rakennettuamme voisimme käyttää sitä kaikkialla ohjelmassamme ja muuttaa vain tarpeen tullen asteet-muuttujan arvoa. Vielä elegantimpi ratkaisu on kuitenkin muodostaa koodista aliohjelma. Sen sijaan, että turvaudumme asteet-muuttujaan, on myös helpompaa kertoa aliohjelmalle suoraan aina, kun sitä käytetään, kuinka suuri käännöksen astelukeman pitäisi volttia hypättäessä olla. Tätä varten meidän täytyy kuitenkin välittää tieto tästä jotenkin aliohjemallemme. Katsotaan, miten se tapahtuu. Klikataan Lisää lohkoja -valikon alta Tee palikka -nappia ja laajennetaan aukeavasta ikkunasta Vaihtoehdot-valikko.


Tästä valikosta voimme määrätä, mitä dataa aliohjelmamme voi ottaa vastaan. Data voi olla numero-, teksti- tai totuusarvotyyppistä.

Kirjoita jälleen aliohjelman nimeksi ”tee voltti”. Klikkaa sen jälkeen Lisää numerosyöttö -tekstin rivillä näkyvää ensimmäistä nappia. Kirjoita ilmestyvään tekstikenttään teksti ”asteet”. Näin määrittelemme ”tee voltti” -nimisen aliohjelman, joka voi ottaa vastaan numerotyyppistä dataa. Nimi ”asteet” kuvastaa tämän datan sisältöä.

Liitä nyt yllä luotu pätkä koodia määrittele 'tee voltti' -palikan alle, jotta lopputulos näyttää kuvan mukaiselta. Korvaa aiempi asteet-muuttuja uudella aliohjelmaan ilmestyneellä tummansinisellä asteet-palikalla, kuten alla olevassa animaatiossa on esitetty. Asteet-muuttujan voit poistaa, kuten myös aiemman tee voltti -aliohjelmasi.


Tämä aliohjelma käskee kissaa hyppäämään voltin, jonka pyörähdysnopeus riippuu sille annetusta astelukemasta.

Näin vaihdat asteet-muuttujan tilalle aliohjelmaan ilmestyneen uuden tummansinisen asteet-palikan. Korvaa myös loput oranssit muuttujapalikat koodista.

Määrittele 'tee voltti' -palikkaan ilmestynyt uusi asteet-palikka pitää siis sisällään astelukeman, jonka suuruisia käännöksiä aliohjelma määrää kissan tekemään, kun aliohjelmaa kutsutaan. Tätä tummansinistä asteet-palikkaa kutsutaan ohjelmoinnissa myös aliohjelman parametriksi. Kaikki aliohjelmille välitettävä tieto otetaan tavallisesti talteen nimenomaan erilaisiin parametreihin. Kokeile seuraavaksi käyttää uutta tee voltti -ohjepalikkaa aliohjelmasi kutsumiseksi. Huomaa, että voit nyt valita sille käännöksen astelukeman arvon. Käytä ensin esimerkiksi lukua 1.


Kokeile klikata tätä palikkaa.

Huomaat, että kissa pyörähtää voltin, mutta hitaammin kuin aiemmin. Nyt kissa hyppää siis voltin asteen 1 suuruisin käännöksin. Arvo 1 sijoitetaankin aliohjelmassa asteet-parametrin arvoksi. Toisin sanoen aliohjelma suoritetaan kuin asteet-palikan paikalla olisi arvo 1.

Kokeile ykkösen sijaan myös muita lukuarvoja tee voltti -palikalle. Kissan pyörähdysnopeuden säätäminen pitäisi onnistua mielivaltaisesti.


Näin kissaa käsketään hyppäämään voltteja eri nopeuksilla.

Myös lukuarvolle, jonka annat tee voltti -palikalle, on ohjelmoinnissa oma nimensä. Sitä kutsutaan argumentiksi. Argumentti on siis varsinainen data, joka halutaan välittää aliohjelmalle sitä kutsuttaessa.


Kuvassa lukuarvo 1 välitetään argumenttina aliohjelmalle. Aliohjelma ottaa ykkösen talteen asteet-parametriinsa ja suorittaa sillä laskutoimituksia. Asteet-parametri toimii aliohjelmassa kuten muuttuja.

Tehtävä 3: Kuin U volttia, missä U on tuntematon

Luo ohjelma, joka käskee kissaa hypäämään ensin viiden voltin verran 25 asteen käännöksin. Jokaisen voltin välissä liikutaan eteenpäin 20 pykälää ja naukaistaan. Tämän jälkeen hypätään vielä uudelleen viiden voltin verran. Tällä kertaa käännökset tehdään kuitenkin 60 asteen suuruisina, minkä lisäksi joka voltin välissä liikutaan 20 pykälää taaksepäin ja naukaistaan. Naukaisut suoritetaan loppuun.

Käytä ohjelmassa hyväksesi äsken luomaamme aliohjelmaa sekä tee voltti -ohjepalikkaa. Voit halutessasi asettaa ohjelmasi käynnistymään vihreän lipun klikkauksesta.

Argumenteista ja parametreista on huomioitava, etteivät ne ole pelkästään aliohjelmien ominaispiirre. Joskus koko ohjelman suoritustapa voi nimittäin vaihdella tilanteesta riippuen. Tällöin itse ohjelmalle saatetaan syöttää sen käynnistyksen yhteydessä erilaisia arvoja argumentteina. Ohjelmalla täytyy myös olla tässä tapauksessa vastaavat parametrit, joihin nämä arvot tallennetaan varsinaista käyttöä varten.

Arkipäivän argumentit

Myös ihmisten noudattamien ohjeiden täsmällinen suoritustapa voi vaihdella tilanteesta riippuen. Arkielämästäkin löytyy siis esimerkkejä argumenteista ja parametreista.

Eräs tapaus, jossa tosimaailmassa törmää argumentteihin ja parametreihin, ovat reseptit, joiden ohjeita tulee noudattaa sen mukaisesti, kuinka monelle henkilölle ateria on tarkoitus valmistaa. Tässä tapauksessa henkilöiden lukumäärä on reseptiohjelman parametri. Se lukuarvo, jonka mukaisesti reseptin noudattaja päättää puolestaan valmistaa aterian, on hänen reseptiohjelmalle antamansa argumentti – esimerkiksi viisi henkeä.

Suklaajäätelö

Kerro aineksien määrä herkuttelevien henkilöiden lukumäärällä.
1 dl maitorahkaa
1 rkl tummaa kaakaojauhetta
1/2 tl vaniljauutetta
1 tl hunajaa

Sekoita aineet kulhossa ja pakasta puolitoista tuntia. Tarjoile kuuman suklaakakun kera.

Tämä resepti sisältää muuttuvana arvonaan parametrin ”henkilöiden lukumäärä”. Reseptin noudattaja sijoittaa tämän parametrin paikalle valitsemansa henkilöiden lukumäärän. Tämä lukuarvo on reseptin argumentti.

Esimerkkinä parametreista riippuvaisesta tosielämän aliohjelmasta voi pitää puolestaan tilauksen toimittamista ravintolassa. Jos ajatellaan, että asiakkaiden palvelu ravintolassa muodostaa kokonaisen ohjelman, tilauksen toimittaminen kuuluisi siihen yhtenä toistuvana rutiinina. Tilausfunktio voisi olisi sisällöltään seuraavanlainen:

  • Asiakkaan tilaamat ateriat ja juomat ovat funktion parametrit.
  • Tarjoilija välittää tilauksen sisällön eteenpäin kokille.
  • Tarjoilija tuo tilatut juomat pöytään.
  • Kokki valmistaa ateriat-parametrin sisältämät ateriat.
  • Tarjoilija tuo valmiit ateriat pöytään.

Tätä aliohjelmaa kutsutaan joka kerta, kun asiakas suorittaa uuden tilauksen. Tilanteesta riippuen joko ateriat- tai juomat-parametria vastaava argumentti saatettaisiin myös jättää tyhjäksi. Tällöin osa funktion vaiheista, kuten juomien pöytiin tuominen, myös ohitettaisiin.



Funktioiden paluu

Jos tarkastelemme aiemmin esittämäämme Python-kielistä kolikonheittopelin koodia, jonka jäsentelimme funktioihin, huomaamme sulkujen sisällä jotain, minkä merkitys jäi kenties aiemmin hämärän peittoon. Nämä nimet sulkujen sisällä ovat funktioiden parametrejä. Esitellään uusi Pythonilla toteutettu parametreja sisältävä funktio, joka laskee kahden luvun keskiarvon:

def laske_keskiarvo(luku1, luku2):
    keskiarvo = (luku1 + luku2) / 2
    return keskiarvo

Tämän funktion parametrit ovat luku1 ja luku2.

Funktiota puolestaan kutsuttaisiin koodissa seuraavasti:

laske_keskiarvo(100, 10)

Tämä funktiokutsu laskee keskiarvon luvuille 100 ja 10.

Python-pähkinä 2

Oletetaan, että olet luonut ohjelmaasi yllä esitellyn laske_keskiarvo-funktion. Millaisella koodirivillä voisit laskea lukujen -5 ja 7 keskiarvon?


Funktioille on tyypillistä aliohjelmina, että ne ottavat vastaan dataa ja myös palauttavat takaisin lopputuloksenaan uutta dataa, kuten yllä kahden luvun keskiarvon. Jos siis ihmettelet, mitä jo muutamaan otteeseen Python-koodissa ilmaantunut return-sana tekee, sen tehtävänä on nimenomaan kertoa, että haluamme funktion palauttavan tietyn arvon lopputuloksenaan. Tämän jälkeen palautettua arvoa voidaan käyttää hyödyksi funktiota kutsuneessa ohjelman osassa. Se voidaan esimerkiksi tulostaa näytölle.

print(laske_keskiarvo(100, 10))

Funktion laske_keskiarvo palauttama keskiarvo voidaan tulostaa näytölle tällaisella koodirivillä. Huomaa, että rivillä käytetään myös toista funktiota nimeltä print tekstin tulostamiseen näytölle.

Yllä oleva koodirivi saisi aikaan näytölle tällaisen lopputuloksen.

Funktion palauttama arvo eli tuttavallisemmin paluuarvo voidaan myös tallentaa muuttujaan myöhempää käyttöä varten:

keskiarvo = laske_keskiarvo(10, 100)

Python-pähkinä 3

Oletetaan, että olet luonut ohjelmaasi jo tutuksi tulleen laske_keskiarvo-funktion. Keksitkö, minkä paluuarvon funktio palauttaa, kun sitä kutsutaan alla olevassa koodissa?

pisin_pituus = 251
lyhin_pituus = 54
keskipituus = laske_keskiarvo(pisin_pituus, lyhin_pituus)
print("Maailman pisimmän ja lyhimmän ihmisen keskipituus on {pituus} cm.".format(pituus=keskipituus))


Funktiot, jotka ottavat argumentteja ja tuottavat jonkin paluuarvon, ovat itse asiassa hyvin tuttuja myös ohjelmoinnin ulkopuolelta: nimittäin jälleen kerran matematiikasta! Esimerkiksi koordinaatistojen yhteydessä käsitellään peruskoulumatematiikassa seuraavan kaltaisia yhtälöitä:

y = 2x
y = x / 2 - 3
y = -5x + 1

Nämä merkinnät ilmaisevat matematiikassa y-suureen arvojen suhdetta x-suureeseen. Niiden pohjalta voidaan piirtää x-y-koordinaatistoon kuvaajat eli tässä tapauksessa suorat.

Nämä yhtälöt voidaan muotoilla myös matemaattisiksi funktioiksi yksinkertaisesti korvaamalla niistä y esimerkiksi merkinnällä f(x). Koska näissä yhtälöissä y:n arvot riippuvat x:n arvoista siten, että jokaista x:n arvoa vastaa täsmälleen yksi y:n arvo, sanotaankin, että kaikissa kolmessa tapauksessa y on x:n funktio. Tällainen riippuvuussuhde on itse asiassa matematiikassa funktion määritelmä.

f(x) = 2x
g(x) = x / 2 - 3
h(x) = -5x + 1

Muotoilimme aiemmat yhtälöt x:stä riippuviksi funktioiksi nimeltä f, g ja h. Koska kyseessä on kolme eri funktiota, käytämme niille myös eri nimiä.

Funktioita vastaavat suorat piirrettynä x-y-koordinaatistoon.

Nyt havaitsemme jo selkeitä yhtäläisyyksiä matematiikan ja ohjelmoinnin funktioiden välillä. Yllä funktioilla on muun muassa nimet eli f, g, ja h. Lisäksi funktioilla on parametri nimeltä x, jota käsitellään funktion sisällä. Funktioille voidaan myös antaa argumentteja ja saada vastineeksi paluuarvoja. Annetaan esimerkin vuoksi jokaiselle kolmelle funktiollemme argumenttina arvo 4 ja katsotaan, mitä paluuarvoja saamme:

f(4) = 2 * 4 = 8
g(4) = 4 / 2 - 3 = -1
h(4) = -5 * 3 + 1 = -14

Annamme kolmelle funktiollemme argumentin 4, joka sijoitetaan niiden parametrin x paikalle. Paluuarvona saamme funktioilta arvot 8, -1 ja -14.

Ohjelmoinnissa funktiot eroavat muutamalla tavalla matemaattisista funktioista. Eräänä esimerkkinä mainittakoon, että ohjelmointikielien funktiot voivat yleensä tuottaa yhden sijaan myös nolla paluuarvoa. Lisäksi funktiot voivat ohjelmoinnissa sisältää muitakin kuin matemaattisia operaatioita ja tallentaa muistiin esimerkiksi välituloksia.

Scratchissa paluuarvoja ei varsinaisesti ole olemassa eikä niitä juuri Scratch-ohjelmoinnissa tarvitsekaan, sillä Scratchin aliohjelmat muokkaavat yleensä hahmojen ominaisuuksia ja käyttäytymistä lopputuloksen laskemisen sijaan. Siksi emme syvennykään paluuarvoihin tässä materiaalissa tämän enempää.

Tehtävä 4: Suunta kateissa

Koska aliohjelmat, argumentit ja parametrit ovat kenties haastavin asia, joka tässä materiaalissa opetetaan, harjoitellaan niitä jälleen tehtävän kautta. Opetellaan luomaan Scratchissa aliohjelma, joka ottaa vastaan useamman kuin yhden argumentin.

Muokataan Takapakkia-tehtävän koodiamme siten, että se hyödyntää tällaista aliohjelmaa. Anna aliohjelman nimeksi ”kävele naukuen”. Luo sille parametrit nimeltä ”määrä” ja ”matka”, jotka molemmat ovat numerotyyppiä. Parametrien pitää esiintyä tässä järjestyksessä aliohjelman määrittelyssä.

Aliohjelman kuuluu käskeä kissaa kävelemään tietty matka niin monta kertaa kuin määrä-parametri ilmoittaa. Yhden matkan aikana liikutaan, nau'utaan ja vaihdetaan asentoa. Liikkeen suuruus ja suunta (eteen- tai taaksepäin) riippuu matka-parametrin arvosta. Naukaisu soitetaan loppuun asti.

Kun olet saanut aliohjelmasi rakennettua, muokkaa pääohjelmaasi siten, että se käyttää hyväksi tätä aliohjelmaa kissan kävelyn toteuttamiseen. Toistorakenteiden määrän pitäisi tippua alkuperäisen koodin kahdesta yhteen. Ohjelman toiminnallisuus pitäisi olla lopuksi samanlainen kuin ennenkin värin vaihtamista myöten, mutta määrää tällä kertaa kissa kävelemään taaksepäin kuuden toiston sijaan kahdeksan toistonverran.

Kutsunnat palvelukseen

Kuten aiemmin tässä luvussa kävimme läpi, aliohjelmat ovat itsenäisiä, muusta ohjelmasta erotettuja kokonaisuuksia, jotka suorittavat tietyn toimenpiteen. Ne voivat ottaa vastaan arvoja argumentteina ja tallentaa nuo arvot sisäisiin muuttujiinsa eli parametreihin käsittelyä varten. Pääohjelma on puolestaan se osa ohjelmaa, joka ei kuulu mihinkään aliohjelmista, eli varsinainen ohjelman runko.

Pääohjelmasta voidaan tarvittaessa siirtyä suorittamaan aliohjelman sisältämiä ohjeita. Komentoa, joka käskee suorittamaan aliohjelman, sanotaan aliohjelman kutsuksi. Tähän mennessä olemme kutsuneet aliohjelmiamme aina pääohjelmasta käsin. Paljastettakoon kuitenkin tässä vaiheessa, että aliohjelmia voi kutsua myös aliohjelmista käsin. Tällöin aliohjelman sisällä poiketaan suorittamaan toinen aliohjelma ja jatketaan siitä, mihin jäätiin.

Aliohjelmien sisälläkin voidaan kutsua toisia aliohjelmia suoritettavaksi.

Scratch-pähkinä 1

Tutki alla esitettyä Scratch-koodia, jossa on hyödynnetty kahta aliohjelmaa. Toinen aliohjelmista kutsuu toista suorituksensa aikana.

Ota selvää, mitä tämä koodi tekee.

Ohjelma käyttää hyväksi myös seuraavaa listaa ja muuttujaa:

Ohjelmassa käytetyn koot-listan sisältö ja indeksi-muuttuja.

Oletetaan seuraavaksi, että käyttäjä antaa ohjelmalle järjestyksessä seuraavat kuusi vastausta ja painaa sitten välilyöntiä: valtaisa, jee, pieni, hups, minimaalinen, normaali. Montako kertaa muuta kokoa -aliohjelmaa kutsutaan ohjelman suorituksen aikana?

Anna vastauksesi lukuna

Scratch-pähkinä 2

Montako kertaa edellisen tehtävän ohjelma suorittaa muuta muuttujan indeksi arvoa 1 -komennon, jos käyttäjän vastaukset ohjelmalle säilyvät samana? Mieti kärsivällisesti ja järjestelmällisesti, miten ohjelman suoritus etenee ohjepalikka kerrallaan!

Anna vastauksesi lukuna

Soveltaminen

Tässä luvussa on harjoiteltu paljon ohjelmien jäsentelyä pienempiin, helpommin hallittaviin, selkeämpiin kokonaisuuksiin. Tämä ajattelumalli soveltuu myös erittäin hyvin systemaattiseen ongelmanratkaisuun, kuten olemme edellisissä luvuissa oppineet.

Kaiken kaikkiaan koodin aliohjelmiin jakamisessa voi ajatella koodin jäsentelyn lisäksi olevan kysymys myös itse ongelman jäsentelystä. Koko ohjelmointiongelma paloitellaan tällöin pienempiin osiin, joista jokainen käsittää oman itsenäisen kokonaisuutensa. Nämä osaongelmat voidaan puolestaan ratkaista erikseen toteuttamalla niiden vaatima toiminnallisuus muusta ohjelmasta erillisinä aliohjelmina.

Ohjelmoinnissa perustavanlaatuisin haaste muodostuu kysymyksestä, miten voimme muotoilla ohjeemme tietokoneen ymmärtämään muotoon siten, että kone tekee juuri sen, mitä haluamme sen tekevän. Aliohjelmat puolestaan hahmottavat meille muun muassa seuraavia asioita:

  • Mistä erillisistä kokonaisuuksista ohjeemme muodostuvat?
  • Mitä näillä ohjekokonaisuuksilla on tarkoitus saada aikaan?
  • Mitä esitietoa niiden suorittaminen vaatii?
  • Mitä pienempiä kokonaisuuksia kukin ohjekokonaisuus pitää sisällään?

Nämä näkökulmat onkin syytä pitää mielessä, kun ratkot seuraavia tehtäviä. Omaksuttavaa on paljon, joten jos kaiken asian sisäistäminen alkaa tuntua raskaalta, älä unohda, että...

Tehtävä 5: Kirjaimellista tulkintaa

Tehdään lämmittelyksi yksinkertainen ohjelma, joka hyödyntää aliohjelmaa nimeltä ”laske kirjaimet”. Ohjelma kysyy käyttäjältä pääohjelmassa: ”Mikä on sanasi?” ja välittää vastauksen aliohjelmalle. Mitään muuta pääohjelmassa ei tarvitse tehdä. Voit kuitenkin halutessasi asettaa ohjelman käynnistymään vihreän lipun klikkauksesta.

Aliohjelman tehtävänä on puolestaan kertoa käyttäjälle, kuinka monta kirjainta pitkä on sille annettu sana. Aliohjelmalla on siis vain yksi parametri nimeltä sana, joka on sisällöltään tekstimuotoinen. Laskettu sanan pituus ilmoitetaan kahden sekunnin ajan puhekuplassa, kuten alla olevassa kuvassa on esitetty:

Kun käyttäjä on antanut sanan, kertoo kissa sen pituuden puhekuplassa.

Käytä kissan puhekuplassa sanoman lauseen rakentamiseksi palikoita Toiminnot-valikon alta. Lopullisen lauseen muodostamisessa tarvitset kahta yhdistä-palikkaa. Ole tarkkana, että välilyönnit menevät tekstissä oikein!

Tehtävä 6: Kuin U(t) volttia, missä U riippuu t:stä

Luo ohjelma, joka käskee kissaa hypäämään ensin viiden voltin verran 25 asteen käännöksin. Jokaisen voltin välissä liikutaan eteenpäin 20 pykälää ja naukaistaan. Tämän jälkeen hypätään vielä uudelleen kuuden voltin verran. Tällä kertaa käännökset tehdään kuitenkin 60 asteen suuruisina, minkä lisäksi joka voltin välissä liikutaan 20 pykälää taaksepäin ja naukaistaan. Naukaisu suoritetaan loppuun.

Käytä ohjelmassa hyväksesi aiemmin luomaamme tee voltti -aliohjelmaa. Luo lisäksi aliohjelma nimeltä ”hypi voltteja”, jolla on parametrit ”määrä”, ”matka” ja ”asteet”. Parametrien tulee esiintyä aliohjelman määrittelyssä tässä järjestyksessä. Ensimmäinen parametri pitää sisällään tiedon, kuinka monta volttia halutaan hypätä, toinen, kuinka paljon niiden välissä liikutaan eteen- tai taaksepäin, sekä kolmas, mitä astelukemaa kaikkien volttien käännöksissä käytetään.

Kutsu tätä aliohjelmaa pääohjelmassasi peräkkäisten samanlaisten volttien toteuttamiseen. Pääohjelmasi tulisi sisältää siis ohjeinaan vain kaksi kutsua. Voit halutessasi asettaa ohjelmasi käynnistymään vihreän lipun klikkauksesta.

Tehtävä 7: Maali häämöttää*

Luodaan seuraavaksi yksinkertainen peli, jossa kissamme pitää edetä labyrintin läpi maaliin. Kissaa ohjastetaan pelissä hiirellä. Labyrinttiin piirretään seinät, joita koskiessaan kissa palaa aina labyrintin alkuun. Labyrintin ja maalin voit piirtää ohjelmasi taustakuvaksi. Uuden taustakuvan piirtäminen onnistuu klikkaamalla kuvassa näkyvää pensseli-ikonia ruudun vasemmassa laidassa.

Tätä ikonia klikkaamalla pääset piirtämään uuden taustakuvan.

Taustakuvan piirtäminen onnistuu samoilla välineillä kuin uuden hahmonkin piirtäminen. Piirrettyäsi taustan ja maalin ohjelmasi voisi näyttää esimerkiksi tältä:

Kuvassa punainen ympyrä on labyrintin maali.

Taustakuvan piirtämisestä voit palata ohjeistamaan kissaasi klikkaamalla sen ikonia Hahmot-tekstin alapuolella ja valitsemalla Skriptit-välilehden. Taustakuvan piirtämiseen voit palata puolestaan klikkaamalla sen pienoiskuvaa ja valitsemalla Taustat-välilehden.

Taustakuvan pienoismalli ja kissaikoni.

Itse ohjelman tulee sisältää neljä erilaista aliohjelmaa, joiden nimet ovat ”seuraa hiirtä”, ”mene alkuun”, ”käsittele törmäys” ja ”kuuluta voitto”. Nämä aliohjelmat ovat parametrittomia. Niiden pitää toteuttaa alla luetellut toiminnallisuudet.

  • seuraa hiirtä:
    • Kissa liikkuu kohti hiirtä kolme pykälää. Etsi tätä varten uusi ohjepalikka, jolla kissa käännetään ensin hiirtä kohti.
  • mene alkuun:
    • Kissa menee ruudulla vaakasuunnassa kohtaan -200 ja pystysuunnassa kohtaan 140 kääntyen osoittamaan alaspäin.
  • käsittele törmäys:
    • Kissa naukaisee (äänen soimista loppuun ei tarvitse tällä kertaa odottaa), sanoo ”Auts!” sekunnin ajan puhekuplassa ja palaa alkuun mene alkuun -aliohjelmaa hyödyntäen.
  • kuuluta voitto:
    • Rumpuja 1, 2 ja 4 soitetaan peräkkäin jokaista 0.25 sekunnin ajan, minkä jälkeen kissa sanoo ”Voitit!” puhekuplassa kahden sekunnin ajan.

Pääohjelma etenee siten, että alussa kissan koko asetetaan 50 %:iin sen täydestä koosta ja se komennetaan menemään labyrintin alkuun. Sen jälkeen toistetaan seuraavia ohjeita niin kauan, kunnes kissa koskettaa maalia:

  • Jos hiiren nappi on painettu, seuraa kissa hiiren osoitinta.
  • Jos kosketaan labyrintin seiniä tai reunaa, käsitellään törmäys.

Kun maali on saavutettu, poistutaan silmukasta ja ilmoitetaan pelaajan voittaneen. Voit halutessasi asettaa ohjelman alkamaan vihreän lipun painalluksesta.

Labyrintin seiniin törmäykset ja maalin saavuttamisen voit tarkistaa koskettaako väriä -ehtopalikalla, joka löytyy Tuntoaisti-valikon alta. Väriä, jonka palikka tarkistaa, voit vaihtaa klikkaamalla sen sisältämää värineliötä. Klikkaa sen jälkeen ruudulta uutta väriä, jonka haluat palikan tarkistavan.

Jos haluat vaihtaa palikan tarkkaileman värin siniseksi, klikkaa ensin värineliötä ja sen jälkeen ruudulta sinistä labyrintin seinää. Toimi vastaavasti valitsemasi maalin värin tapauksessa.

Leikki- ja peli-ideoita

Aliohjelmien periaatteita voi opetella yksinkertaisten funktioleikkien kautta. Ensimmäinen funktioleikki toimii seuraavasti:

  • Pelinjohtaja kirjoittaa ylös salaisen funktion säännöt.
  • Tämä salainen funktio ottaa vastaan yhden tai useamman argumentin, jotka voivat olla esimerkiksi numeroita, tekstiä, pelikortteja tai jotain muuta, jolla on selkeä arvo, ja palauttaa niitä vastaavan paluuarvon.
  • Muut pelaajat yrittävät päätellä funktion toimintaperiaatteen testaamalla sitä erilaisin argumentein ja tutkimalla, millaisia paluuarvoja he saavat vastineeksi.
  • Pelaajille voidaan asettaa rajallinen määrä arvauksia, joiden kuluttua loppuun pelinjohtaja voittaa. Muiden pelaajien puolestaan arvatessa oikein he voittavat.

Alla on esitelty, millainen salainen funktio voisi sisällöltään olla:

Salainen funktio:
- ota vastaan kaksi lukua
- lisää ensimmäiseen lukuun 1
- vähennä toisesta luvusta 1
- palauta lukujen tulo

Testaamalla funktiota antamalla sille eri lukuja argumenteiksi voitaisiin saada esimerkiksi tällaisia tuloksia:

argumentit: 1, 2
paluuarvo: 3

argumentit: 10, 4
paluuarvo: 55

argumentit: -3, 0
paluuarvo: -2

Peliä pelattaessa voidaan sopia, että pelinjohtaja saa käyttää salaisen funktion toteuttamiseen vain tietyn määrän eri sääntöjä ja ne pitää valita valmiista sääntöjen joukosta, joka on kaikille pelaajille tiedossa. Argumenteille puolestaan voi asettaa niin ikään leikkiin rajoituksia. Muilla pelaajilla voivat olla käytettävissä arvauksiin esimerkiksi vain kokonaisluvut väliltä -10...10.

Toinen funktioleikki etenee seuraavasti:

  • Pelaajilla on käytössään joukko valmiiksi määriteltyjä yksinkertaisia funktioita, jotka voivat sisältää esimerkiksi matemaattisia operaatioita.
  • Nämä funktiot ottavat vastaan yhden tai useamman argumentin ja tuottavat niiden pohjalta jonkin paluuarvon. Funktiot voivat tuottaa myös useamman kuin yhden paluuarvon.
  • Pelinjohtaja puolestaan päättää argumentin tai argumentit, joista muiden pelaajien pitää lähteä liikkeelle, ja päätyä pelinjohtajan määräämään paluuarvoon.
  • Muiden pelaajien pitää kutsua funktioita peräkkäin siten, että seuraavalle funktiolle syötetään argumentiksi edellisen funktion paluuarvo.
  • Pelaajilla voi olla esimerkiksi rajallinen määrä aikaa käytettävissään, jonka loppuessa he häviävät ja pelinjohtaja voittaa.

Eräs esimerkki pelaajien käytettävissä olevista funktioista on annettu alla:

Funktio 1: ottaa vastaan luvun, vähentää sitä viidellä ja palauttaa lopputuloksen.

Funktio 2: ottaa vastaan luvun, kertoo sen kolmella ja palauttaa lopputuloksen.

Funktio 3: ottaa vastaan luvun ja palauttaa sen itseisarvon.

Jos pelinjohtaja antaisi nyt muille pelaajille argumentiksi luvun 1 ja vaadituksi paluuarvoksi luvun 2, pelaajien pitäisi osata kutsua funktioita tässä järjestyksessä:

1 -> Funktio 2 -> 3
3 -> Funktio 1 -> -2
-2 -> Funktio 3 -> 2

Käsittelemällä funktioita ja niiden sisältöä esimerkiksi matemaattisessa muodossa, voi näiden pelien avulla helposti opetella myös funktioiden käyttöä matematiikassa. Vaihtamalla lukusyötteet tekstisyötteiksi, voidaan puolestaan harrastaa sana- ja lausearvoitusten ratkontaa matematiikan sijaan.

Kuvalähteet

  1. Pile of Lemurs, Gavin Stewart, lisenssi: CC BY 2.0, muokkaus: teksti lisätty, kuvaa rajattu.
  2. man-walking-dog.jpg, r. nial bradshaw, lisenssi: CC BY 2.0, muokkaus: teksti lisätty, kuvaa rajattu.
  3. Yeah... that's the spot... right there..., Ângela Antunes, lisenssi: CC BY 2.0, muokkaus: teksti lisätty.
  4. Amelia on a MacBook Pro, brownpau, lisenssi: CC BY 2.0, muokkaus: teksti lisätty, kuvaa rajattu.