Suunnittelu ja opetuksen apuvälineet
Suunnittelu ja opetuksen apuvälineet
Olemme tämän oppimateriaalin edeltävissä luvuissa luoneet paljon omia ohjelmiamme ja perehtyneet niiden rinnalla järjestelmällisen ongelmanratkaisun keinoihin. Tähän mennessä ohjelmointitehtävämme ovat kuitenkin käytännössä tarkoittaneet valmiiksi annettujen, hyvin suoraviivaisten ohjeiden seuraamista ja toteuttamista. Itsenäistä kokonaisuuksien hahmottamista ja laajojen ongelmien pähkäilyä ei ole vielä vaadittu.
Todellisessa ohjelmoinnissa ongelmien hahmottaminen ja jäsentely on kuitenkin tavallisesti merkittävä osa koko työn haastetta. Ohjelmalle asetetut vaatimukset harvoin kertovat suoraan, miten ohjelmaa pitäisi lähteä toteuttamaan. Ennen konkreettista koodaamista ja yksityiskohtiin keskittymistä täytyykin laajojen ongelmien ratkaisemiseksi harrastaa suunnittelua.

Tässä luvussa esittelemme myös, mitä muita apuvälineitä ohjelmoinnin opetuksessa ja oppimisessa voi hyödyntää Scratchin ohella. Scratch ei nimittäin suinkaan ole ainoa tarjolla oleva ja kaiken kattava ympäristö näihin tarkoituksiin. Sen vuoksi on syytä tutustua myös muihin lähestymistapoihin.
Pelisuunnittelun alkeet
Helpoin tapa oppia ohjelmien suunnittelua on esimerkin kautta. Seuraavaksi käydään läpi ajatteluprosessia, miten Python-kielisen kivi-paperi-sakset-pelin toteuttaminen voisi huolellisen ohjelmoijan käsissä edetä. Oletetaan, että pelissä on kaksi pelaajaa, ja pelaajat saavat itse päättää, montako erävoittoa koko pelin voittoon vaaditaan.

Ongelman ratkaisemisessa on syytä lähteä liikkeelle jakamalla se osaongelmiin. Tämä onnistuu tunnistamalla eri toiminnallisuudet, jotka ohjelman on toteutettava. Mietitään ensin, miten peliohjelman kulku etenisi käyttäjän näkökulmasta:
- Peli kysyy pelaajilta, montako erävoittoa koko pelin voittoon vaaditaan.
- Kohtia 3-5 toistetaan, kunnes jompikumpi pelaajista on voittanut vaaditun määrän erävoittoja.
- Kysytään pelaajilta heidän valintansa kolmesta asevaihtoehdosta (kivi, paperi, sakset).
- Päätellään ja ilmoitetaan erävoittaja.
- Näytetään pelaajille kertyneet erävoitot.
- Pelin päättyessä ilmoitetaan voittaja.
Alla on esitetty kuva siitä, miltä ohjelman toiminta voisi lopulta näyttää:

Hetken luomaamme listausta pohtimalla mieleen juolahtaa ainakin seuraavat asiat, jotka peliin tulisi sisältyä:
- koko pelin voittoon vaadittujen erävoittojen kysyminen
- mahdollisuus valita eri aseiden eli kiven, paperin ja saksien välillä
- erätuloksen päättely ja ilmoittaminen
- kertyneiden erävoittojen näyttäminen
- koko pelin voittajan tarkistaminen ja ilmoittaminen
Nämä toiminnot voi ajatella kaikki omina pieninä kokonaisuuksinaan. Selvästi niistä pystyy luomaan siis omat aliohjelmansa! Nimetään ne kuvaavasti. Pythonissa joudumme käyttämään aliohjelmien nimissä alaviivaa sanojen erottimena:
- kysy_erien_lukumäärä
- kysy_ase
- päättele_erätulos
- näytä_voitot
- tarkista_voittaja
Seuraavaksi pohdimme, mitä tietoa nämä aliohjelmat, eli Pythonin tapauksessa funktiot, tarvitsevat toimiakseen. Funktio kysy_erien_lukumäärä ei tarvitse mitään etukäteistietoa, mutta kysy_ase-funktion täytyy tietää, kummalle pelaajalle se esittää kysymyksensä. Funktion päättele_erätulos pitää puolestaan saada tieto siitä, minkä aseen kumpikin pelaaja on valinnut, kun taas näytä_voitot tarvitsee tiedon siitä, kumman pelaajan voitot näytetään ja paljonko niitä on kertynyt. Funktio tarkista_voittaja kaipaa sen sijaan tiedon kummankin pelaajan kertyneistä voitoista.
Näiden mietintöjen jälkeen voimme jo muotoilla ohjelmamme funktiot, joille tässä vaiheessa emme anna vielä sisältöä, vaan korvaamme sen pass-sanalla. Pythonissa pass-sana tarkoittaa, ettei tehdä mitään.
def kysy_erien_lukumäärä():
pass
def kysy_ase(pelaaja):
pass
def päättele_erätulos(ase1, ase2):
pass
def näytä_voitot(pelaaja, voitot):
pass
def tarkista_voittaja(voitot1, voitot2, erät):
pass
Pähkäillään seuraavaksi, mitä pääohjelmaamme pitäisi kuulua. Ohjelman alussa pelaajilta täytyy ainakin kysyä, montako erävoittoa koko pelin voittoon vaaditaan. Koska eriä puolestaan pelataan niin kauan, kunnes jompikumpi pelaajista on voittanut vaaditun määrän kertoja, on koodissa hyödynnettävä toistorakennetta. Käytämme ehtona toistorakenteen silmukasta poistumiseen tarkista_voittaja-aliohjelmalta saatavaa totuusarvoa, joka kertoo, onko pelin voittaja selvinnyt vai ei. Tietysti meidän täytyy vielä kirjoittaa myöhemmin sisältö tälle aliohjelmalle.
Tieto pelaajien erävoitoista sekä vaadittujen erien määrästä täytyy pitää lisäksi tallessa jossain. Käytämme tähän tarkoitukseen muuttujia. Lopputuloksena saamme aikaiseksi seuraavanlaisen pääohjelman alun, jonka sijoitamme koko koodimme loppuun:
voitot1 = 0
voitot2 = 0
erät = kysy_erien_lukumäärä()
while not tarkista_voittaja(voitot1, voitot2, erät):
pass
Pelissä käytettävät aseet eli kivi, paperi ja sakset pitää myös laittaa talteen muistiin. Tehdään siis niitä varten oma tietorakenteensa. Lisäksi pelaajia olisi kätevä kuvastaa ohjelmassa jotenkin, joten luodaan niitä varten muuttujat, joihin sijoitetaan lukuarvot 1 ja 2. Koska sekä tietorakenne että muuttujat pysyvät sisällöltään vakioina koko ohjelman suorituksen ajan, paikoitetaan ne yleisen ohjelmointikäytännön mukaisesti koodin alkuun.
aseet = ("kivi", "paperi", "sakset")
pelaaja1 = 1
pelaaja2 = 2
Kirjoitetaan tässä vaiheessa pääohjelmamme puhtaaksi. Käytännössä tämä tarkoittaa aiemmin esitetyn luettelon kohtien 3–5 kääntämistä koodiksi. Tämä hoituu aliohjelmakutsuilla hyvin suoraviivaisesti: aluksi molemmilta pelaajilta on kysyttävä heidän asevalintansa, tämän jälkeen päätellään niiden pohjalta erän tulos, kasvatetaan pelaajien voittojen määrää sen mukaisesti ja lopuksi näytetään molempien pelaajien kertyneet erävoitot.
voitot1 = 0
voitot2 = 0
erät = kysy_erien_lukumäärä()
while not tarkista_voittaja(voitot1, voitot2, erät):
ase1 = kysy_ase(pelaaja1)
ase2 = kysy_ase(pelaaja2)
tulos = päättele_erätulos(ase1, ase2)
voitot1 += tulos[0]
voitot2 += tulos[1]
näytä_voitot(pelaaja1, voitot1)
näytä_voitot(pelaaja2, voitot2)
Nyt voimme siirtyä ohjelmassamme yleiseltä tasolta yksityiskohtien toteutukseen. Tässä vaiheessa on hyvä tunnistaa, mitä opittuja ohjelmoinnin menetelmiä voimme käyttää hyväksi saadaksemme aikaan halutun toiminnallisuuden. Erätuloksen päätteleminen ja voittajan tarkistaminen ovat esimerkiksi pohjimmiltaan ehtojen tutkimista ja niiden pohjalta toimimista: ”jos pelaaja 1 valitsee kiven ja pelaaja 2 valitsee sakset, päätellään pelaajan 1 olevan erävoittaja”. Niissä tarvitsemme siis selkeästi ehtolauseita.
Vaadittujen erävoittojen määrää ja asevalintoja pelaajilta kysellessä olisi puolestaan hyvä, jos ohjelma virheellisen syötteen saadessaan ilmoittaisi käyttäjälle tämän virheestä ja esittäisi kysymyksensä uudelleen. Jos esimerkiksi käyttäjä syöttää erien lukumääräksi jotain muuta kuin luvun, ohjelma voisi kertoa, että se odottaa nollaa suurempaa lukua vastaukseksi, ja kysyä uudestaan. Tällainen toiminnallisuus voitaisiin saada aikaan toistorakenteella ja ehtolauseella.
Alla on esitetty valmis pelikoodi kokonaisuudessaan. Sen yksityiskohtia ei tarvitse ymmärtää. Tärkeintä on sisäistää tähän mennessä kuvailtu ajattelumalli, jolla suuretkin ongelmat voidaan järjestelmällisesti jäsennellä ja purkaa auki siten, että ratkaisu saadaan lopulta saatettua toimivan ohjelman muotoon.
aseet = ["kivi", "paperi", "sakset"]
pelaaja1 = 1
pelaaja2 = 2
def kysy_erien_lukumäärä():
kehoitus = "Anna nollaa suurempi lukumäärä!"
while True:
erät = input("Montako erää voittoon vaaditaan? ")
try:
erät = int(erät) # Yritetään käsitellä käyttäjän antamaa erämäärää lukuna.
except ValueError:
print(kehoitus)
else:
if erät > 0:
return erät
print(kehoitus)
def kysy_ase(pelaaja):
while True:
ase = input("Pelaaja {p}, valitse aseesi: ".format(p=pelaaja))
if ase in aseet:
return ase
print("Valitse joko kivi, paperi tai sakset!")
def päättele_erätulos(ase1, ase2):
heikkous = aseet[(aseet.index(ase2) + 1) % len(aseet)] # Päätellään, mikä on ase2:n heikkous.
if ase1 == ase2:
print("Tasapeli!")
return 0, 0
elif ase1 == heikkous:
print("Pelaaja 1 voitti erän!")
return 1, 0
else:
print("Pelaaja 2 voitti erän!")
return 0, 1
def näytä_voitot(pelaaja, voitot):
print("Pelaaja {p} on voittanut {n} kertaa".format(p=pelaaja, n=voitot))
def tarkista_voittaja(voitot1, voitot2, erät):
if voitot1 >= erät:
print("Pelaaja 1 voittaa koko pelin!")
return True
elif voitot2 >= erät:
print("Pelaaja 2 voittaa koko pelin!")
return True
else:
return False
voitot1 = 0
voitot2 = 0
erät = kysy_erien_lukumäärä()
while not tarkista_voittaja(voitot1, voitot2, erät):
ase1 = kysy_ase(pelaaja1)
ase2 = kysy_ase(pelaaja2)
tulos = päättele_erätulos(ase1, ase2)
voitot1 += tulos[0]
voitot2 += tulos[1]
näytä_voitot(pelaaja1, voitot1)
näytä_voitot(pelaaja2, voitot2)
Ympäristönvaihdos
Ennen kuin siirrymme tämän opiskelumateriaalin päättävään suunnittelutehtävään, laajennetaan ensin näkökulmiamme astumalla Scratchin ulkopuolelle ja tutustumalla lyhyesti muihin ohjelmoinnin opettelun apuvälineisiin. Loppujen lopuksi Scratch on sellaisena vain yksi tarjolla olevista monista vaihtoehdoista. Kuten myös todettua, Scratchilla ei yksinään saa aikaan mitään järin konkreettista, sillä kyseessä on pohjimmiltaan vain oppimisympäristö eikä todellinen työkalu. Siksi pelkästään sen käyttöön ei pidä rajoittua.
Code.org¶

Code.org-sivustolla voi suorittaa muun muassa Angry Birds -aiheisia ohjelmointitehtäviä.
Eräs tunnetuimmista visuaalisista ohjelmoinnin oppimisympäristöistä Scratchin ohella on code.org, joka tarjoaa useita erilaisia koodausharjoituksia eri-ikäisten oppilaiden sekä opettajien käyttöön. Kuten Scratch, code.org käyttää myös ohjepalikoista muodostuvaa graafista ohjelmointikieltä tehtävissään. Se sisältää lisäksi muun muassa konkreettisia leikkivinkkejä ja oppitunti-ideoita, joiden avulla lapsille voi opettaa ohjelmointia.
TouchDevelop¶

TouchDevelop-ympäristössä koodia on mahdollista kirjoittaa myös tekstimuotoisena ohjepalikoiden sijaan.
TouchDevelop on Microsoftin kehittämä visuaalinen ohjelmointiympäristö, joka on saatavilla niin älypuhelimille, tableteille kuin tietokoneillekin. TouchDevelopissa vaikeustasoa säätämällä pystyy muokkaamaan koodia joko Scratchin kaltaisina ohjepalikoina tai suoraan tekstinä, jolloin myös sitä pystyy hienosäätämään tarkemmin. TouchDevelopin avulla ohjelmoija voi kehittää ja julkaista tuotoksiaan mobiililaitteille peleistä aina sosiaalista mediaa hyödyntäviin sovelluksiin.
Codecademy

Codecademy on interaktiivinen verkko-opiskelualusta, joka tarjoaa kursseja eri ohjelmointikielten, kuten Pythonin, opiskeluun. Lisäksi siellä voi opetella muun muassa HTML-sivujen tekemistä sekä erilaisten ohjelmointikirjastojen ja -rajapintojen käyttöä. Codecademy osaa tarkistaa käyttäjänsä luomia ohjelmia automaattisesti ja raportoimaan niissä ilmenevistä virheistä. Sivusto myös palkitsee ja motivoi käyttäjää palautteella, arvomerkein sekä pitämällä kirjaa hänen edistymisestään. Suoritukset esitetään myös muille käyttäjille, joten omaa oppimistaan pystyy vertailemaan ystävien ja tuntemattomien kesken. Codecademy soveltuu erityisesti yläkouluikäsille sekä ohjelmoinnissa edistyneimmille oppilaille.
Lego Mindstorms

Robotiikan osalta kenties tunnetuin apuväline ohjelmoinnin opiskeluun on Lego Mindstorms -tuotteet. Lego Mindstorms -sarja on laajalti hyödynnetty ohjelmoinnin opetuksessa eri puolilla maailmaa. Opetuskäyttöä varten niistä on myös olemassa Lego Mindstorm for Schools -nimellä kulkeva versio. Se mahdollistaa Lego-robottien ohjelmoimisen visuaalisen ohjelmointiympäristön voimin. Visuaalisen ohjelmointiympäristön voi korvata myös varsinaisilla ohjelmointikielillä. Robotteja pystyy rakentelemaan Lego-palikoita hyödyntäen ja ne voivat aistia ympäröivää maailmaa erilaisten antureiden voimin. Antureilta saatua dataa voidaan puolestaan käsitellä roboteille ohjelmoiduissa ohjelmissa, minkä ansiosta ne pystyvät tekemään ympäristönsä pohjalta erilaisia päätöksiä.
LightBot

Ohjelmoinnin opetteluun on tarjolla myös lukuisia pelejä. Eräs näistä on LightBot-ongelmanratkaisupeli, jossa on tarkoitus läpäistä kenttiä ohjelmoimalla pieni robotti noudattamaan yksinkertaisia komentoja. Peli koostuu vaikeustasoltaan vaihtelevista, eri ikäryhmille suunnatuista logiikkapulmista, jotka monimutkaistuvat pelin edetessä. Lego-robottien tavoin se auttaa pelaajansa ymmärtämään myös tekoälyjen toimintaa. LightBot on saatavilla tunnin mittaisena ilmaisversiona niin mobiililaitteille kuin tietokoneillekin sekä lisäksi laajempana maksullisena versiona mobiililaitteille.
Käärmeen kieli
Olemme käyttäneet tässä opiskelumateriaalissa esimerkkinä todellisesta ohjelmointikielestä Pythonia. Syy valintaan on siinä, että Python on sillä kirjoitetun koodin muodoltaan eli syntaksiltaan hyvin yksinkertainen ja ilmaisuvoimainen, sekä lisäksi erittäin laajalti käytetty, moneen tarkoitukseen soveltuva kieli. Sillä kirjoitettu koodi on todella helppolukuista ja aloittelijaystävällistä, koska se ei sisällä käytännössä mitään ylimääräistä ja muistuttaa paljon ihmisten keskinäiseen viestintään käytettyä kirjoitettua kieltä.
Ohjelmoinnissa uutta kieltä harjoiteltaessa opetellaan usein ensimmäisenä ohjelmana tulostamaan näytölle lause ”Hello world!”. Havainnollistaaksemme Pythonin helposti lähestyttävyyttä alla on esitetty vertailun vuoksi ”Hello world!” -ohjelma toteutettuna sekä Pythonilla että maailman eräällä suosituimmalla ohjelmointikielellä, Javalla.
print("Hello, world!")
Yllä on Pythonilla kirjoitettu ohjelma, joka tulostaa näytölle lauseen ”Hello world!”
public class HelloWorld
{
public static void main(String[] args)
{
System.out.println("Hello world!");
}
}
Yllä on Javalla kirjoitettu ohjelma, joka tulostaa näytölle lauseen ”Hello world!”
Kuten esimerkeistä näkee, Pythonilla kirjoitettu ohjelma vaatii huomattavasti vähemmän koodia saman toiminnallisuuden toteuttamiseen kuin Java-kielinen vastineensa. Ohjelmoijan ei myöskään tarvitse ymmärtää saati olla häkeltynyt siitä, mikä on sanojen ”public”, ”class”, ”static”, ”void”, ”main”, ”args” tai merkintöjen ”String[]” ja ”System.out.println” tarkoitus. Koodin syntaksiin ei myöskään kuulu aaltosulkeita eikä puolipistettä. Python-koodista täytyy käsittää ainoastaan, että print-komennolla näytölle saadaan tulostettua tekstiä, minkä lisäksi teksti on ympäröitävä lainausmerkein ja asetettava print-komennon sulkujen sisään.
Python soveltuu siis kielenä erinomaisesti ohjelmoinnin opetukseen. Se ei itse asiassa ole sen hankalampi omaksua kuin monet nimenomaan opetustarkoitukseen suunnitellut kielet. Jopa lapsi pystyy oppimaan Pythonia vähällä vaivalla.
Eri käyttötarkoituksiin soveltuvia ohjelmointikieliä on kuitenkin olemassa lukemattomia. Maailman suosituinta ohjelmointikieltä, C:tä, käytetään muun muassa erityisesti käyttöjärjestelmien ja sulautettujen järjestelmienohjelmointiin. Toista laajalle levinnyttä kieltä, JavaScriptiä, käytetään puolestaan yleisimmin web-ohjelmoinnissa. Muun muassa kaikki tämän materiaalin animaatiot on toteutettu JavaScriptillä!

Erilaisten ohjelmointikielien kirjo on laaja. Kuvassa muutamia tunnettuja kieliä, jotka kattavat kaikista ohjelmointikielistä murto-osan.
Ohjelmointikielten suosiosta puhuttaessa täytyy kuitenkin muistaa, ettei niiden käytön yleisyys kerro niiden keskinäisestä paremmuudesta. Tärkeintä kieltä päättäessä onkin valita se, joka parhaiten soveltuu senhetkiseen tarkoitukseen – samoin kuin oppimisympäristöjen tapauksessa.
#include <stdio.h>
int main(void) {
printf("Hello world!\n");
return 0;
}
”Hello world!”-ohjelma toteutettuna C-kielellä.
<html>
<head>
<title>JavaScript Example 1 -- Hello World</title>
<script type="text/javascript">
document.write("Hello World!");
</script>
</head>
<body>
...
</body>
</html>
”Hello world!”-ohjelma toteutettuna JavaScript-kielellä ja upotettuna HTML-verkkosivun lähdekoodiin.
Lisää eri kielillä toteutettuja ”Hello world!” -ohjelmia löydät muun muassa Wikipediasta.
Kuvalähteet
- 080415 kitten taxes, Dan4th Nicholas, lisenssi: CC BY 2.0, muokkaus: teksti lisätty, kuvaa rajattu ja osittain sumennettu.
- Rock Paper Scissors, Mark Turnauckas, lisenssi: CC BY 2.0, muokkaus: kuvaa rajattu ja sumennettu.
- Top Programming Languages, Daniel Iversen, lisenssi: CC BY 2.0, muokkaus: kuvaa osittain sumennettu.
- Smart cat and lovely dog, nguyen hoangnam, lisenssi: CC BY 2.0, muokkaus: teksti lisätty.