Kurssin viimeisimmän version löydät täältä: O1: 2024
Luku 3.4: Valintoja
Tästä sivusta:
Pääkysymyksiä: Miten saan ohjelman valitsemaan eri vaihtoehtojen välillä? Miten saan suoritettua käskyn vain, jos tietty ehto on voimassa?
Mitä käsitellään? Valintakäsky: if
ja else
. Valintakäsky
lausekkeena; tilaan vaikuttaminen valintakäskyllä. Valintakäskyjen
yhdistely peräkkäin ja sisäkkäin.
Mitä tehdään? Luetaan ja tehdään pieniä tehtäviä.
Suuntaa antava työläysarvio:? Pari tuntia.
Pistearvo: A75.
Oheisprojektit: GoodStuff, FlappyBug, Odds. Vapaaehtoisessa tehtävässä esiintyy myös projekti Miscellaneous (uusi).
Valitsemisen tarve
Mitä erilaisimmissa ohjelmissa on tarpeen tehdä valintoja. Halutaan esimerkiksi valita uudeksi suosikkikokemukseksi kahdesta kokemuksesta (lisätty ja vanha suosikki) parempi. Tai halutaan suorittaa toiminto vain, jos käyttäjä vastaa "kyllä" eikä "ei". Ja niin edelleen.
On siis voitava muodostaa ohjelmaan ehtoja: vastasiko käyttäjä "kyllä"; onko kokemus parempi kuin toinen? Ehtojen muodostaminen meiltä jo onnistuukin totuusarvoja käyttäen.
Lisäksi tarvitsemme tavan, jolla voimme määrätä tietyt käskyt suoritettaviksi vain, jos ehto on voimassa. Kätevää olisi sekin, että samalla voisimme määrätä vaihtoehtoiset käskyt suoritettaviksi siinä tapauksessa, että ehto ei toteudu.
Scala tarjoaa useita eri tapoja käskyjen valinnaiseen suorittamiseen. Tässä luvussa
niistä käsitellään suoraviivaisinta eli if
-valintakäskyä.
if
-käsky
Sanoja if
ja else
käyttäen voi muodostaa lausekkeita, joiden arvo riippuu siitä,
toteutuuko tietty ehto evaluointihetkellä eli onko tietyn Boolean
-tyyppisen lausekkeen
arvo true
vai ei. Perusidea on pseudokoodina tämä:
if (ehto) arvo ehdon toteutuessa else arvo muutoin
Käskyn toimintaa on helppo tutkia REPLissä:
if (10 > 100) "on isompi" else "ei ole isompi"res0: String = ei ole isompi if (100 > 10) "on isompi" else "ei ole isompi"res1: String = on isompi
Boolean
, jolloin sen arvoksi
saadaan evaluoitaessa joko true
tai false
. Tässä ehtolauseke
on muodostettu vertailuoperaattorilla. Kun if
-käsky
suoritetaan, evaluoidaan aluksi tämä ehtolauseke kertaalleen ja
sen perusteella määrittyy, mitä seuraavaksi tapahtuu.false
, suoritetaan else
-sanan
jälkeinen ohjelmakoodi eli ns. "else
-haara". Koko
if
-lausekkeen arvoksi saadaan else
-haaran arvo.true
, suoritetaan heti
ehtolausekkeen perässä oleva ohjelmakoodi eli ns. "then
-haara".
Koko if
-lausekkeen arvoksi saadaan then
-haaran arvo. (Mitään
"then"-sanaahan ei Scala-koodiin kirjoiteta, mutta if
-käsky
voidaan englanniksi lukea if X then A else B.)Esimerkkejä
Ehtolausekkeena voi olla vertailun sijaan mikä vain Boolean
-tyyppinen lauseke, vaikkapa
Boolean
-muuttujan nimi:
val maapalloOnLittea = falsemaapalloOnLittea: Boolean = false if (maapalloOnLittea) "Niin varmaan" else "Ihanko tosi?"res2: String = Ihanko tosi?
Tai totuusarvoliteraali true
tai false
(joskaan tästä ei ole liiemmin hyötyä):
if (true) "Tämä valittiin" else "Tätä ei"res3: String = Tämä valittiin
Äskeiset esimerkit valitsivat kahden merkkijonolausekkeen välillä, mutta then
- ja
else
-haaroina voi toki käyttää myös vaikkapa lukuarvoisia lausekkeita:
val luku = 100luku: Int = 100 if (luku > 0) luku * 2 else 0res4: Int = 200 if (luku < 0) luku * 2 else 0res5: Int = 0
if
-lausekkeen arvon tyyppi määräytyy sen mukaan, mitä
valinnaisiin haaroihin kirjoitetaan.if
-käsky lausekkeena
Valintakäskyä voi käyttää lausekkeena missä tahansa yhteydessä, johon sen tietotyyppi sopii, vaikkapa parametrilausekkeessa toisen käskyn osana, muuttujaan sijoitettaessa tai aritmeettisen laskutoimituksen osana. Esimerkiksi seuraavat käskyt ovat mahdollisia:
println(if (luku > 100) 10 else 20)20 val valinnanTulos = if (luku > 100) 10 else 20valinnanTulos: Int = 20 (if (luku > 100) 10 else 20) * (if (luku <= 100) -luku else luku) + 1res6: Int = -1999
Viimeinen annetuista käskyistä on tosin jo sen verran haarakas, että mieluummin kannattaa
ottaa if
-lausekkeiden arvot tilapäissäilöön muuttujiin ja vasta sitten kertoa ne
keskenään.
Pikkutehtäviä
if
-käskyn rivittämisestä ja sisentämisestä
Mainittakoon tässä välissä, että jos valintakäskystä muodostuisi muuten pitkä ja hankalalukuinen, niin sen voi jakaa usealle riville esimerkiksi näin:
val pidempiKommentti =
if (elain == suosikki)
"Mahtavaa! Se on " + elain + ", joka on oma suosikkini."
else
"Ihan kiva eläinhän se on " + elain + "kin."
if
-käskyssä
tapana sisentää syvemmälle kuin if
- ja else
-alkuiset rivit. Kun tähän
tapaan tottuu, niin if
-käskyn kokonaisuus on näin nopeampi hahmottaa.
Tapaa on syytä noudattaa. Sinänsä näilläkään sisennyksillä ei ole
Scala-ohjelman toimivuuteen vaikutusta.Minitehtävä: kuvan kuvailu, osa 1/2
Kirjoita Miscellaneous-projektin misc.scala
-tiedostoon
vaikutukseton funktio describe
, joka:
- ottaa yhden,
Pic
-tyyppisen parametrin, ja - palauttaa merkkijonon "portrait", jos kuvan korkeus on leveyttä suurempi ja merkkijonon "landscape" muutoin (eli jos kuva on neliön muotoinen tai leveämpi kuin korkea).
REPLissä kokeillessasi anna aluksi käsky import o1.misc._
.
A+ esittää tässä kohdassa tehtävän palautuslomakkeen.
Experience
-luokka valmiiksi
Voimme käyttää if
-valintakäskyä luokan ohjelmakoodissa. Näin mahdollistamme, että oliot
voivat tehdä valintoja niiden metodeita kutsuttaessa.
Valitseva chooseBetter
-metodi
Meillä on jo luvusta 3.3 osittainen toteutus Experience
-luokalle. Luokasta jäi tällöin
toteuttamatta chooseBetter
-metodi, joka vertailee kahta kokemusta ja palauttaa niistä
arvosanaltaan paremman. Kunhan saamme metodin toteutettua, sen pitäisi toimia tähän tapaan:
val wine1 = new Experience("Il Barco 2001", "ookoo", 6.69, 5)wine1: o1.goodstuff.Experience = o1.goodstuff.Experience@1b101ae val wine2 = new Experience("Tollo Rosso", "turhahko", 6.19, 3)wine2: o1.goodstuff.Experience = o1.goodstuff.Experience@233b80 val betterOfTheTwo = wine1.chooseBetter(wine2)betterOfTheTwo: o1.goodstuff.Experience = o1.goodstuff.Experience@1b101ae betterOfTheTwo.nameres7: String = Il Barco 2001
chooseBetter
-metodin ajatus on siis samankaltainen kuin max
-funktion (luku 1.6),
joka palauttaa kahdesta vertailemastaan luvusta suuremman.
Tässä ensin Experience
-toteutus, jossa chooseBetter
on pseudokoodina:
class Experience(val name: String, val description: String, val price: Double, val rating: Int) { def valueForMoney = this.rating / this.price def isBetterThan(another: Experience) = this.rating > another.rating def chooseBetter(another: Experience) = { Selvitä, onko tämä kokemus arvosanaltaan parempi kuin another-kokemus. Jos oli, palauta viittaus this-olioon, muuten palauta another-muuttujan sisältämä viittaus. } }
Ja sitten metodin koodi Scalalla:
def chooseBetter(another: Experience) = {
val thisIsBetter = this.rating > another.rating
if (thisIsBetter) this else another
}
this
-sana yksinään muodostaa lausekkeen, jonka arvo on viittaus
metodia suorittavaan olioon itseensä.chooseBetter
in suoritus päättyy if
-lausekkeeseen; metodi palauttaa
tämän if
-lausekkeen arvon. Se on viittaus metodia suorittavaan olioon,
jos muuttujan thisIsBetter
arvo on true
, tai parametriksi saatu
viittaus, jos thisIsBetter
on false
.Parempi ratkaisu omaa metodia kutsumalla
Äskeinen toteutus toimii. Voisimme kuitenkin haluta poistaa Experience
-luokasta
tarpeettoman toiston: nythän metodeissa isBetterThan
ja chooseBetter
on täsmälleen
sama vertailuoperaatio this.rating > another.rating
. Kokemusten paremmuuden määrittely
on siis tehty kahteen kertaan eri paikoissa.
Tämä ei ole kovin eleganttia ja heikentää ohjelman muokattavuutta. Jos esimerkiksi haluaisimme muuttaa ohjelmaa niin, että vertailu tapahtuukin hinta–laatu-suhteen eikä arvosanan perusteella, niin pitäisi muuttaa kahta kohtaa. Tämä ei ole tässä pienessä ohjelmassa kauheaa, mutta isommissa ohjelmissa toisteisuudesta seuraa pian ylläpidettävyysongelmia.
Koetetaan tehdä vähän paremmin.
Olet jo useasti nähnyt, että olio voi "lähettää itselleen viestin" eli kutsua omaa
metodiaan: this.metodi(parametrit)
. Niinpä voimme muotoilla uuden version
chooseBetter
-metodista:
def chooseBetter(another: Experience) = {
val thisIsBetter = this.isBetterThan(another)
if (thisIsBetter) this else another
}
Experience
-olio ikään kuin kysyy itseltään: "Oletko parempi
kuin tämä toinen kokemus?"Nyt chooseBetter
käyttää juuri sitä tapaa vertailla paremmuutta, joka on määritelty
isBetterThan
-metodissa, eikä toistoa ole.
Tiiviimpi ratkaisu: metodikutsu ehtolausekkeena
Varustaudutaan vielä tiedolla, että if
-käskyssä voi käyttää myös metodikutsua
ehtolausekkeena, kunhan vain metodin palautusarvo on tyyppiä Boolean
. Tämä tulee ilmi
seuraavasta REPL-esimerkistä (jossa oletetaan wine1
ja wine2
määritellyiksi kuin
edellä):
if (wine1.isBetterThan(wine2)) "oli parempi" else "ei ollut parempi"res8: String = "oli parempi" if (wine2.isBetterThan(wine1)) "oli parempi" else "ei ollut parempi"res9: String = "ei ollut parempi" if (wine1.isBetterThan(wine1)) "oli parempi" else "ei ollut parempi"res10: String = "ei ollut parempi"
Ehtolausekkeen evaluointi tarkoittaa tässä tapauksessa metodin kutsumista; lausekkeen arvoksi saadaan metodin palauttama totuusarvo. Tämän jälkeen jatketaan palautusarvon mukaiseen haaraan.
Tältä pohjalta voimme lyhentää chooseBetter
-toteutustamme hieman. Paikallista muuttujaa
thisIsBetter
ei välttämättä tarvita:
def chooseBetter(another: Experience) = if (this.isBetterThan(another)) this else another
Experience
-luokkamme on valmis. GoodStuff-projektin toiseen keskeiseen luokkaan Category
tartumme myöhemmin luvussa 4.2.
Odds-tehtävä (osa 7/9)
Palataan taas hetkeksi edellisistä luvuista tuttuun Odds-hankkeeseemme ja lisätään sinne
metodi, jolla Odds
-olion kuvaama tieto voidaan esittää ns. moneyline-muodossa, jota
erityisesti amerikkalaiset vedonlyöntitoimistot käyttävät. Tämä hieman kummallinen
esitysmuoto toimii seuraavasti:
(Alla P ja Q viittaavat lukuihin, joista todennäköisyyden
fractional
-muotoinen esitys P/Q muodostuu.)Jos tapahtuman on arvioitu tapahtuvan korkeintaan 50 %:n todennäköisyydellä, sen moneyline-luku on positiivinen ja saadaan laskemalla 100 * P / Q. Esimerkiksi tapausta 7/2 vastaa moneyline-luku 350, koska 100 * 7 / 2 = 350. Tämän positiivisen luvun voi tulkita siten, että panostamalla 100 rahaa vedonlyöjä voi tehdä 350 rahaa voittoa sen lisäksi, että saa panoksensa takaisin. Fifty–fifty-tilannetta 1/1 vastaa moneyline-luku 100.
Jos taas todennäköisyydeksi on arvioitu yli 50 %, moneyline-luku on negatiivinen ja saadaan laskemalla -100 * Q / P. Esimerkiksi tapausta 1/5 vastaa moneyline-luku -500, koska -100 * 5 / 1 = -500. Tämän negatiivisen luvun voi tulkita siten, että tehdäkseen 100 rahaa voittoa vedonlyöjän on panostettava 500 rahaa.
Tehtävänanto
Laadi Odds
-luokkaan metodi moneyline
, joka palauttaa Odds
-oliota vastaavan
moneyline-luvun Int
-arvona:
val norwayWin = new Odds(5, 2) norwayWin: Odds = o1.Odds@171c36b norwayWin.moneylineres11: Int = 250
Lisää myös käynnistysolioon OddsTest1
rivi, joka tulostaa moneyline-luvun. Ohjelman
tulosteen on nyt näytettävä tällaiselta:
Please enter the odds of an event as two integers on separate lines.
For instance, to enter the odds 5/1 (one in six chance of happening), write 5 and 1 on separate lines.
11
13
The odds you entered are:
In fractional format: 11/13
In decimal format: 1.8461538461538463
In moneyline format: -118
Event probability: 0.5416666666666666
Reverse odds: 13/11
Odds of happening twice: 407/169
Please enter the size of a bet:
200
If successful, the bettor would claim 369.2307692307692
Please enter the odds of a second event as two integers on separate lines.
10
1
The odds of both events happening are: 251/13
The odds of one or both happening are: 110/154
Ohjeita ja vinkkejä
- Käytä
if
-lauseketta. moneyline
-metodin on tässä palautettava kokonaisluku. Jätä desimaaliosa kokonaan pois eli pyöristä aina kohti nollaa. Kokonaislukujen jakolaskuhan tekee tämän puolestasi (luku 1.3), joten helpoimmalla pääset, kun vain teet laskutoimitukset sopivassa järjestyksessä: kerro ensin, jaa sitten.- Se on yhdyssana, joten
moneyline
eikämoneyLine
.
Palauttaminen
A+ esittää tässä kohdassa tehtävän palautuslomakkeen.
Apokalyptistä ohjelmointia
Suomalaisessa kansanperinteessä Jumala rankaisi pyytä tuomiten sen vähitellen pienenemään maailman loppuun saakka. Lopun tiedetään olevan liki, kun pyy on häviävän pieni. Tätä perua on sanonta "pienenee kuin pyy maailmanlopun edellä".
Simuloidaan tilanne. Tässä on pyiden mallintamiseen sopiva luokka:
class Pyy {
private var koko = 400
private val peruskuva = Pic("bird.png")
def loppuKoitti = this.koko <= 0
def pienene() = {
if (this.koko > 0) {
this.koko = this.koko - 1
}
}
def kuvaksi = this.peruskuva.scaleTo(this.koko)
}
Löydät tuon luokan ja sitä käyttävän käyttöliittymän Pikkusovelluksia-projektista. Käyttöliittymä käyttää luvussa 3.1 opittuja konsteja pienentääkseen valkoista taustaa vasten näkyvää pyytä kunnes se katoaa näkyvistä.
Tehtäväsi on tutustua annettuun koodiin ja muokata käyttöliittymän makePic
-metodia
siten, että se vaihtaa koko kuvan mustaksi lopun koittaessa. Metodin pitää siis
palauttaa:
- linnun kuva valkoista taustaa vasten (kuten annetussa koodissa)
vain silloin, jos pyyn
loppuKoitti
-metodi palauttaafalse
; ja - täysmusta
maailmanlopunKuva
, jos tuo metodi palauttaatrue
.
Käytännössä sinun täytyy vain lisätä metodiin yksi if
-lauseke.
A+ esittää tässä kohdassa tehtävän palautuslomakkeen.
Tilaan vaikuttaminen if
-käskyssä
if
-käskyn haarat voivat sisältää myös käskyjä, joilla on tilaa muuttavia vaikutuksia
(luku 1.6) kuten tulostamista, muuttujien arvon vaihtamista yms. Tässä esimerkki:
if (luku > 0) {
println("Luku on positiivinen.")
println("Tarkemmin sanoen se on: " + luku)
} else {
println("Kyseessä ei ole positiivinen luku.")
}
println("Olen puhunut.")
if
-käskyyn vaan
on sen perässä. Tuo tulostuskäsky suoritetaan siis ehtolausekkeen
arvosta riippumatta, kunhan ensin on suoritettu jompikumpi yllä
olevista "haaroista".Seuraavat animaatiot kuvaavat esimerkkikoodin toiminnan ensin positiivisella ja sitten negatiivisella lukuarvolla.
Huomaa: Aiemmin tässä luvussa käytimme if
-käskyä lausekkeiden eli "ilmaisujen, joilla
on arvo" muodostamiseen. Valitsimme if
-käskyllä kahden arvon välillä. Äskeisessä
animoidussa koodissa puolestaan käytettiin if
-käskyä valitsemaan tiettyjen tilaa
muuttavien vaikutusten välillä. Tässä vielä pseudokoodi, joka kuvaa tuon yleisen
ajatuksen:
if (ehto) { käskyjä, jotka suoritetaan, jos ehtolausekkeen arvo oli tosi } else { käskyjä, jotka suoritetaan, jos ehtolausekkeen arvo oli epätosi }
Kun if
-käskyä käytetään tilan muuttamiseen, käytetään yleensä rivinvaihtoja,
sisennyksiä ja aaltosulkuja kuten äskeisissä esimerkeissä. Näin teemme tälläkin kurssilla,
kuten kurssin tyyliopaskin kertoo.
Jotkut Scala-ohjelmoijat kylläkin...
... jättävät aaltosulut pois myös vaikutuksellisista if
-käskyistä,
jos "haaroissa" on vain yksi käsky, mutta me emme tee niin.
Unit
if
-käskyn arvona
Vaikka seuraava sijoituskäsky ei olekaan kovin fiksu, on sitä hyvä pohtia hetki:
val turhaTulos = if (luku > 1000) { println("Aika iso") } else { println("Ei niin iso") }Ei niin iso turhaTulos: Unit = ()
Tässä sijoituskäskyn osana käytetyllä if
-käskyllä ei ole merkityksellistä arvoa. Koodi
kyllä tulostaa lukumuuttujan arvon perusteella jommankumman tekstin, mutta se ei sijoita
muuttujaan turhaTulos
mitään järkevää (vaan vain sisällöttömän Unit
-arvon; luku 1.6).
Näin tapahtuu siksi, että if
-käskyn haarat päättyvät tulostuskäskyyn, joka ei palauta
merkityksellistä arvoa. Tällaista if
-käskyä on siis turha käyttää muuttujasijoituksessa.
Voi olla sivistävää vielä verrata äskeistä koodia näihin:
val tulos = if (luku > 1000) "Aika iso" else "Ei niin iso"tulos: String = Ei niin iso println(tulos)Ei niin iso
println(if (luku > 1000) "Aika iso" else "Ei niin iso")Ei niin iso
if
ilman else
ä
Kun käytämme if
-käskyä ohjelman tilaan vaikuttamiseen, on yleistä, että else
-haaraa
ei edes tarvita. Usein haluamme suorittaa jonkin käskyn tai käskyt vain ehdon täyttyessä,
mutta muuten ei tehdä mitään.
Tietysti voisimme tehdä jotain tällaista:
if (ehto) { käskyjä, jotka suoritetaan, jos ehto oli tosi } else { }
else
-haara ei tee mitään. Mutta sitä ei edes tarvitse
kirjoittaa; voimme jättää tämän pois.Jos else
-haaraa ei ole ja ehtolausekkeen arvoksi tulee false
, niin loput
if
-käskystä yksinkertaisesti ohitetaan:
if (ehto) { käskyjä, jotka suoritetaan, jos ehto oli tosi, ja ohitetaan muutoin }
Esimerkki:
if (luku != 0) {
println("Osamäärä on: " + 1000 / luku)
}
println("Loppu.")
else
-haara on jätetty pois.if
-käsky on vaikutuksellinen (se tulostaa), ja siksi
käytämme rivitystä ja aaltosulkeita.if
-käskyyn vaan on
sen perässä. Tämä koodinpätkä siis tulostaa lopuksi "Loppu."
riippumatta siitä, oliko luku
-muuttujan arvo nolla vai ei.
Mikäli oli, ei tämä koodi muuta tulostakaan.Voit katsoa tämänkin koodin suorituksesta lyhyen animaation, jos haluat:
Pikkutehtävä
FlappyBug-tehtävä (osa 12/17: hienosäätöä)
Tehtävänanto
Lisää FlappyBug-ohjelmaan kaksi if
-käskyä siten, että:
- Ötökkä ponnahtaa ylöspäin vain, jos painettu näppäin on välilyönti (eikä millä tahansa näppäimellä kuten tähän asti).
- Ötökän nopeus kiihtyy (eli
yVelocity
-ilmentymämuuttujan arvo kasvaa) vain, jos ötökkä on ilmassa (eli maanpinnan yläpuolella).
Ohjeita ja vinkkejä
- Lisäykset tulevat
FlappyBugApp
-ohjelmanonKeyDown
-metodiin jaBug
-luokanfall
-metodiin. Molemmat olivat esillä, kun peliä muokattiin luvussa 3.1. - Tapahtumankäsittelijämetodi
onKeyDown
saa parametriksi tiedon siitä, mitä näppäintä painettiin. Voit verrata tätä arvoa yhtäsuuruusoperaattorilla==
arvoonKey.Space
, joka on välilyöntinäppäintä tarkoittava vakioarvo. - Et tarvitse
else
-haaroja.
Palauttaminen
A+ esittää tässä kohdassa tehtävän palautuslomakkeen.
if
-käskyjen yhdistelemisestä
else if
-ketjutus
Jos haluat valita useammasta kuin kahdesta vaihtoehdosta, voit kirjoittaa if
-käskyn
else
-haaraan toisen if
-käskyn:
val kuvaus = if (luku < 0) "negatiivinen" else if (luku > 0) "positiivinen" else "nolla"
Sulut ehkä selkiyttävät käskyä hieman:
val kuvaus = if (luku < 0) "negatiivinen" else (if (luku > 0) "positiivinen" else "nolla")
Parhaiten monihaaraisuus ehkä näkyy rivittämällä ja sisentämällä esimerkiksi näin:
val kuvaus =
if (luku < 0)
"negatiivinen"
else if (luku > 0)
"positiivinen"
else
"nolla"
Tällainen else if
-ketjuttaminen toki toimii myös, kun valitaan vaikutuksellisten
käskyjen välillä:
if (luku < 0) {
println("Luku on negatiivinen.")
} else if (luku > 0) {
println("Luku on positiivinen.")
} else {
println("Luku on nolla.")
}
Minitehtävä: kuvan kuvailu, osa 2/2
Muokkaa ylemmässä minitehtävässä misc.scala
an laatimaasi
describe
-funktiota siten, että se palauttaa:
- merkkijonon "portrait", jos kuvan korkeus on leveyttä suurempi,
- merkkijonon "landscape", jos kuvan leveys on korkeutta suurempi, ja
- merkkijonon "square", jos kuvan leveys on prikulleen sama kuin sen korkeus.
A+ esittää tässä kohdassa tehtävän palautuslomakkeen.
if
-käskyjä sisäkkäin
if
-käskyjä voi muutenkin laittaa sisäkkäin. Tällöin pitää olla tarkkana sen kanssa,
mihin if
-käskyyn kukin else
-haara liittyy. Tutustu asiaan seuraavan REPL-esimerkin
kautta:
val luku = 100luku: Int = 100 if (luku > 0) { println("On positiivinen.") if (luku > 1000) { println("On yli tuhat.") } else { println("On positiivinen muttei yli tuhat.") } } On positiivinen. On positiivinen muttei yli tuhat.
if
-käskyn ehdollinen osa,
johon sisältyy ensimmäinen tulostuskäsky.if
-käsky. Koska tämän
sisemmän if
-käskyn ehto ei toteudu, päädytään sen else
-osaan.if
-käskyn haarat ovat vielä sisennetymmät.if
-sanan
alku ja ehdollisia haaroja rajaavat aaltosulut ovat pystysuorassa
linjassa keskenään sekä sisemmässä...else
-haaraa
ollenkaan.Äskeisessä esimerkissä siis else
-sana liittyi "lähimpään" if
-käskyyn. Tuo else
-osa
suoritettiin nimenomaan siksi, että ulomman käskyn ehto toteutui mutta sisemmän ei.
Jos haluamme liittää else
n ulompaan if
-käskyyn, aaltosulkujen siirtäminen auttaa:
if (luku > 0) { println("On positiivinen.") if (luku > 1000) { println("On yli tuhat.") } } else { println("On nolla tai negatiivinen.") }On positiivinen.
if
-käskyllä on kaksi haaraa, ja else
-haara
suoritettaisiin vain, jos luku ei olisi positiivinen.else
-haara kytkeytyy lähimpään päättyneeseen "then-haaraan".
Tässä viimeksi on aaltosuljettu ulomman if
-käskyn then-haara.if
-käskyllä ei tässä esimerkissä ole else
-haaraa
lainkaan. Tulosterivejä tulee vain yksi.Sisäkkäisyystehtävä
Odds-tehtävä (osa 8/9)
Tehtävänanto
Luvun 3.3 OddsTest2
-käynnistysolio tulostaa eräitä tietoja kahdesta Odds
-oliosta.
Muuta sitä:
- Poista
isLikely
- jaisLikelierThan
-metodien palautusarvoja tulostavatprintln
-käskyt. (Siis ne, joissa tuloste alkaa The-sanalla.) Tämä siksi, että tarkoitus on nyt raportoidaOdds
-olioiden tietoja hieman toisin kuin ennen. - Nyt laadittavan ohjelman on tutkittava, onko ensimmäinen syötetty
Odds
todennäköisempi kuin toinen ja tulostettava sen perusteella jompikumpi seuraavista lauseista: The first event is likelier than the second. tai The first event is not likelier than the second. - Tämän jälkeen ohjelman on tulostettava Each of the events is odds-on
to happen., mikäli molemmat tapahtumat ovat todennäköisiä. Jos kumpi
tahansa tapahtumista ei ole todennäköinen, ei tässä kohtaa tulosteta
mitään.
- Kuten aiemmin määrittelimme, tapahtuma on
todennäköinen, jos se toteutuu luultavammin
kuin ei toteudu eli jos sen
isLikely
-metodi palauttaatrue
.
- Kuten aiemmin määrittelimme, tapahtuma on
todennäköinen, jos se toteutuu luultavammin
kuin ei toteudu eli jos sen
- Thank you -alkuisen lopputervehdyksen on edelleen tulostuttava kaikissa tapauksissa.
Ohjelman tulosteen pitää siis vastata täsmälleen näitä ajoesimerkkejä:
Please enter the odds of the first event as two integers on separate lines. 5 1 Please enter the odds of the second event as two integers on separate lines. 1 2 The first event is not likelier than the second. Thank you for using OddsTest2. Please come back often. Have a nice day!
Please enter the odds of the first event as two integers on separate lines. 1 1 Please enter the odds of the second event as two integers on separate lines. 2 1 The first event is likelier than the second. Thank you for using OddsTest2. Please come back often. Have a nice day!
Please enter the odds of the first event as two integers on separate lines. 1 2 Please enter the odds of the second event as two integers on separate lines. 2 3 The first event is likelier than the second. Each of the events is odds-on to happen. Thank you for using OddsTest2. Please come back often. Have a nice day!
Ohjeita ja vinkkejä
- Käytä
if
-käskyjä. - Selvittäessäsi, ovatko molemmat tapahtumista todennäköisiä,
voit laittaa kaksi
if
-käskyä sisäkkäin. Vaihtoehtoisesti voit kurkistaa jo lukuun 5.1 ja noukkia sieltä toisen keinon kahden ehdon yhdistämiseen.
Palauttaminen
A+ esittää tässä kohdassa tehtävän palautuslomakkeen.
Yhteenvetoa
if
-valintakäskyllä voi valita kumpi kahdesta käskystä tai käskyjen sarjasta suoritetaan.- Valintakäskyllä voi myös määrätä tiettyjä osia ohjelmakoodista valinnaisiksi. Ne suoritetaan vain, jos tietty ehto on voimassa.
- Mitä tahansa
Boolean
-tyyppistä lauseketta voi käyttää valintakäskyn ehtona. if
-käskyjä voi yhdistellä laittamalla niitä peräkkäin tai sisäkkäin.- Lukuun liittyviä termejä sanastosivulla:
if
; totuusarvo; lauseke; DRY.
Lisätehtävä: tarkkuuspeli
Kirjoita kokonaan uusi ohjelma, jossa käyttäjän pitää yrittää osua hiiren klikkauksella keskelle ikkunaa. Tämä yksinkertainen peli päättyy, jos käyttäjä onnistuu näpäyttämään esim. kolmen pikselin etäisyydelle ikkunan keskikohdasta; tällöin ruudulle ilmestyy jokin valitsemasi kuva merkiksi onnistumisesta.
Voit luoda aihealueen malliksi yksinkertaisen olion, joka pitää
Boolean
-tyyppisessä muuttujassa kirjaa siitä, onko peli päättynyt.
Tarvitset myös käyttöliittymän, joka tekee pelitilanteen näkyväksi.
Tästä vapaamuotoisesta lisätehtävästä ei ole tarjolla automaattista palautetta.
Palaute
Huomaathan, että tämä on henkilökohtainen osio! Vaikka olisit tehnyt lukuun liittyvät tehtävät parin kanssa, täytä palautelomake itse.
Tekijät
Tämän oppimateriaalin kehitystyössä on käytetty apuna tuhansilta opiskelijoilta kerättyä palautetta. Kiitos!
Kierrokset 1–13 ja niihin liittyvät tehtävät ja viikkokoosteet on laatinut Juha Sorva.
Kierrokset 14–20 on laatinut Otto Seppälä. Ne eivät ole julki syksyllä, mutta julkaistaan ennen kuin määräajat lähestyvät.
Liitesivut (sanasto, Scala-kooste, usein kysytyt kysymykset jne.) on kirjoittanut Juha Sorva sikäli kuin sivulla ei ole toisin mainittu.
Tehtävien automaattisen arvioinnin ovat toteuttaneet: (aakkosjärjestyksessä) Riku Autio, Nikolas Drosdek, Joonatan Honkamaa, Jaakko Kantojärvi, Niklas Kröger, Teemu Lehtinen, Strasdosky Otewa, Timi Seppälä, Teemu Sirkiä ja Aleksi Vartiainen.
Lukujen alkuja koristavat kuvat ja muut vastaavat kuvituskuvat on piirtänyt Christina Lassheikki.
Yksityiskohtaiset animaatiot Scala-ohjelmien suorituksen vaiheista ovat suunnitelleet Juha Sorva ja Teemu Sirkiä. Niiden teknisen toteutuksen ovat tehneet Teemu Sirkiä ja Riku Autio käyttäen Teemun toteuttamia Jsvee- ja Kelmu-työkaluja.
Muut diagrammit ja materiaaliin upotetut vuorovaikutteiset esitykset on laatinut Juha Sorva.
O1Library-ohjelmakirjaston ovat kehittäneet Aleksi Lukkarinen ja Juha Sorva. Useat sen keskeisistä osista tukeutuvat Aleksin SMCL-kirjastoon.
Opetustapa, jossa käytämme O1Libraryn työkaluja (kuten Pic
) yksinkertaiseen graafiseen
ohjelmointiin on saanut vaikutteita tekijöiden Flatt, Felleisen, Findler ja Krishnamurthi
oppikirjasta How to Design Programs sekä Stephen Blochin oppikirjasta Picturing Programs.
Oppimisalusta A+ on luotu Aallon LeTech-tutkimusryhmässä pitkälti opiskelijavoimin. Pääkehittäjänä toimii tällä hetkellä Jaakko Kantojärvi, jonka lisäksi järjestelmää kehittävät useat tietotekniikan ja informaatioverkostojen opiskelijat.
Kurssin tämänhetkinen henkilökunta on kerrottu luvussa 1.1.
Joidenkin lukujen lopuissa on lukukohtaisia lisäyksiä tähän tekijäluetteloon.
if
jaelse
. Huomaa myös ehtolauseketta ympäröivät sulut, jotka ovat pakolliset.