Luku 3.6: Valintoja, valintoja
FlappyBug-tehtävä (osa 13/17: toistuva este)
Alkusanat
FlappyBug-pelissämme maiseman poikki kulkee toistaiseksi este vain kerran. Se ei oikein tyydytä. Tyydyttävämpää olisi, jos ötökälle tulisi toistuvasti uusia esteitä ohitettavaksi.
Voimme lähestyä ongelmaa kahdella eri tavalla:
Kun este on liikkunut pois näkyvistä maiseman vasemmasta reunasta eli ei ole enää "aktiivinen", luodaan uusi esteolio, joka sijaitsee oikealla. Korvataan peliin aiemmin liitetty esteolio tällä uudella esteellä. Vanha esteolio jää ilman käyttöä.
Kun este on liikkunut pois näkyvistä maiseman vasemmasta reunasta eli ei ole enää "aktiivinen", siirretään se oikealle yksinkertaisesti vaihtamalla sen koordinaatteja. Teknisessä mielessä ötökkä siis kohtaa saman esteolion aina vain uudelleen, mutta käytännössä näyttää siltä kuin oikealta saapuisi toistuvasti uusia esteitä.
Kumpikaan vaihtoehdoista ei ole yksiselitteisesti parempi kuin toinen. Valitsemme nyt jälkimmäisen tavan, joka on helppo toteuttaa.
Tehtävänanto
Lisää ensin Obstacle
-luokkaan vaikutukseton ja parametriton metodi isActive
, joka
palauttaa true
, jos esteen oikea reuna on ruudun vasemmassa laidassa tai sen oikealla
puolella, ja false
muuten. Esimerkiksi jos 50-säteisen esteen keskipisteen x-koordinaatti
on -50, niin este juuri ja juuri luetaan vielä aktiiviseksi, mutta yhtään pienemmällä
koordinaatilla ei luettaisi.
Muokkaa sitten estettä liikuttavaa approach
-metodia. Obstacle
-luokassa on siitä
ennestään tällainen versio:
def approach() =
this.currentPos = this.currentPos.addX(-ObstacleSpeed)
Muuta metodi sellaiseksi, että se tilanteesta riippuen joko liikuttaa estettä vasemmalle tai siirtää sen takaisin oikealle. Tarkemmin sanoen:
Mikäli este oli kutsuhetkellä aktiivinen, niin se liikkuu kuten ennenkin.
Mikäli este ei ollut aktiivinen, niin sen uudeksi x-koordinaatiksi tulee näkyvän pelimaailman leveys plus 250 (käytännössä 1250) ja y-koordinaatiksi puolet pelimaailman korkeudesta (käytännössä 200). Este lähtee siis uudelleen liikkeelle jonkin verran pelialueen oikean reunan takaa, pystysuunnassa keskeltä.
A+ esittää tässä kohdassa tehtävän palautuslomakkeen.
Loppusanat
Maiseman poikki kulkee nyt este useasti mutta ilmestyen aina samaan kohtaan. Se ei oikein tyydytä. Tyydyttävämpää olisi, jos esteet ilmestyisivät arvaamattomampiin paikkoihin.
Miten saisimme esteen koordinaatit valittua satunnaisesti?
Tämä onkin ihan oma ongelmansa. Käsitellään satunnaisuutta ensin vähän yleisemmin.
Satunnaisluvuista
Random
-luokka
Hyviä uutisia: Scalassa on luokka nimeltä Random
, jolla voi helposti tuottaa
satunnaislukuja:
import scala.util.Randomval generaattori = Random(74534161)generaattori: scala.util.Random = scala.util.Random@1413cb7 generaattori.nextInt(10)res0: Int = 3 generaattori.nextInt(10)res1: Int = 8 generaattori.nextInt(10)res2: Int = 7 generaattori.nextInt(10)res3: Int = 2 generaattori.nextInt(10)res4: Int = 3 generaattori.nextInt(10)res5: Int = 2
Random
-olioilla on erilaisia arvojen arpomiseen sopivia
metodeita. Usein hyödyllinen on metodi nextInt(n: Int)
, joka
arpoo luvun nollan ja n-1
:n väliltä.
Esimerkiksi kun kutsutaan metodia parametrilla 10, saadaan lukuja väliltä 0–9.
Mikä tuo tuolla sulkeissa on? Palataan siihen hetken päästä.
Voit itse kokeilla antaa samat käskyt REPLissä. Jos kokeilet, saat täsmälleen saman
luettelon satunnaislukuja nextInt
-metodin paluuarvoina: 3, 8, 7, 2, 3, 2 jne.
Mitä ihmettä? Lukujenhan piti olla satunnaisia.
Näennäissatunnaisluvut
The generation of random numbers is too important to be left to chance.
—Robert Coveyou
"Tuota 30 täysin satunnaista lukua väliltä 0–9" on ihmiselle paha pala purtavaksi. Yksi mahdollisuus on käyttää jotain "riittävän hyvää" matemaattista algoritmia, jolla muodostetaan lukujen sarja. Esimerkiksi:
Valitse jokin luku N, esim. N=20
Ota N:s piin desimaali. Se olkoon ensimmäinen "satunnaisluku".
Määritä seuraava "satunnaisluku" ottamalla piin desimaali kohdasta 2*N.
Sitten 3*N, 4*N ja niin edelleen
Myös tietokoneelle satunnaislukujen generointi on hankala ongelma. Aitoa satunnaisuutta se ei osaa nyhjäistä tyhjästä.
Tällaisen algoritmin tuottamia lukuja sanotaan näennäissatunnaisluvuiksi (pseudorandom numbers). Samalla "aloitusluvulla" eli satunnaislukujen siemenellä (seed) saadaan aina sama näennäissatunnaislukujen sarja. Esimerkiksi yllä hahmotellussa algoritmissa N oli siemen, ja algoritmi tuotti N:n arvolla 20 aina samat luvut.
On kehitelty erilaisia algoritmeja näennäissatunnaislukujen generointiin. Esimerkiksi
Scalan luokka Random
käyttää erästä tällaista algoritmia (johon ei tällä kurssilla
perehdytä tarkemmin). Algoritmin siemenenä toimii luku, joka annetaan oliolle
luontiparametriksi (esim. yllä luku 74534161).
Se, että algoritmi tuottaa tietyllä siemenluvulla aina saman näennäissatunnaislukujen sarjan, voi olla joko etu (jos on tarpeen pystyä toistamaan tietty alun perin satunnaisesti valittu tapahtumasarja) tai haaste (jos halutaan joka kerta täysin erillinen satunnaislukusarja).
Siemenluku kellonajasta
On erilaisia tapoja valita siemenluku. Joskus voi olla perusteltua pyytää siemenluku käyttäjältä. Voidaan myös käyttää apuna jotakin ympäristön "riittävän satunnaista" piirrettä; perinteinen konsti on käyttää siemenenä tietokoneen ajohetkistä päiväystä ja kellonaikaa esimerkiksi nanosekunnin tarkkuudella.
Monissa tilanteissa ei ole väliä, mitä nimenomaista siemenlukua käytetään. Siksi
scala.util
-pakkaukseenkin on määritelty Random
-luokan lisäksi myös Random
-niminen
yksittäisolio, jolta voi pyytää kellonajan pohjalta "arvottuja" satunnaislukuja luomatta
erikseen Random
-oliota lainkaan:
import scala.util.RandomRandom.nextInt(10)res6: Int = 8 Random.nextInt(10)res7: Int = 6 Random.nextInt(10)res8: Int = 2
Jos kokeilet näitä käskyjä itse, saat eri paluuarvot. Tai ainakin erittäin todennäköisesti saat.
FlappyBug-tehtävä (osa 14/17: arvaamattomampi este)
Pohjustus: randomLaunchPosition
-metodi
Laaditaan Obstacle
-luokkaan uusi metodi, jonka tehtävänä on arpoa lähtösijainti ruudun
oikealta puolelta lähtevälle esteelle. Tässä alku:
private def randomLaunchPosition() = val launchX = Laske yhteen ruudun leveys (1000), esteen säde ja satunnainen kokonaisluku väliltä 0—499. val launchY = Arvo satunnainen kokonaisluku, joka on vähintään 0 ja pienempi kuin ruudun korkeus (400). Pos(launchX, launchY)
Pari lauseketta on jätetty täydennettäväksesi.
Tämä metodi on yksityinen. Se on tarkoitettu vain
Obstacle
-luokan sisäiseen käyttöön eikä kuulu julkiseen
rajapintaan. (Vrt. yksityiset muuttujat; luku 3.2.)
Tehtävänanto
Toteuta
randomLaunchPosition
. Käytä yllä annettua koodia pohjana ja täydennä se puuttuvin osin.Muokkaa
approach
-metodia niin, ettei se aseta vasemman laidan ohittanutta estettä vakiopaikkaan vaan kutsuurandomLaunchPosition
-metodia saadakseen sille uuden sijainnin.Muokkaa
Obstacle
-luokkaa niin, ettei estettä luodessa enää anneta luontiparametriksi lähtösijaintia vaan vain säde. Sen sijaan luotava esteolio käyttäärandomLaunchPosition
-metodiaan arpoakseen itselleen lähtösijainnin.Tee pieni muutos
Game
-luokkaan, jotta se on yhteensopiva uusitunObstacle
n kanssa: kun luot uudenObstacle
-olion anna sille vain yksi luontiparametri (koko), ei sijaintia.
Ohjeita ja vinkkejä
Käytä arpomiseen
Random
-yksittäisolion metodia, niin saat eri pelikerroilla erilaisia tuloksia.Voit myös kokeilla siemenluvun kirjaamista koodiin ja havaita, että tällöin este ilmestyy joka pelikerralla samoihin paikkoihin.
randomLaunchPosition
on parametriton, vaikutuksellinen metodi, joten kirjoitamme sen määrittelyyn tyhjät sulkeet()
luvun 2.6 mukaisesti. (Metodi luetaan vaikutukselliseksi, koska se muuttaa käyttämänsä satunnaislukugeneraattorin tilaa.)
A+ esittää tässä kohdassa tehtävän palautuslomakkeen.
Pelottavampaa grafiikkaa peliin
Hylkää makeRockPic
-funktio, jota FlappyBug on toistaiseksi käyttänyt.
Vaihda esteen kuvaksi Pic("obstacle.png")
, jonka skaalaat oikean
kokoiseksi metodikutsulla scaleTo(esteenHalkaisija)
. Pelaa jos
uskallat.
Lisää tehtäviä
Odds-tehtävä (osa 9/9)
Lisää Odds-moduulin samannimiseen luokkaan metodi eventHappens
, joka arpoo,
toteutuuko tapahtuma, jolla on Odds
-olion kuvaama todennäköisyys tapahtua:
val nopallaKuutonen = Odds(5, 1)nopallaKuutonen: Odds = 5/1 nopallaKuutonen.eventHappens()res9: Boolean = false nopallaKuutonen.eventHappens()res10: Boolean = false nopallaKuutonen.eventHappens()res11: Boolean = true
Metodia kutsuessa saadaan satunnaisesti joko true
tai false
.
Tässä nopanheittoa kuvaavassa tapauksessa false
tulee koko lailla
viisi kertaa niin usein kuin true
.
Metodi on vaikutuksellinen, koska se kutsuu vaikutuksellista nextInt
-metodia.
Käytä siksi määrittelyssä tyhjiä kaarisulkeita parametriluettelona (luku 2.6).
Metodi nextInt
lasketaan vaikutukselliseksi, koska se vaikuttaa
satunnaislukugeneraattorin sisäiseen tilaan.
Muista, että Random
pitää ottaa käyttöön pakkauksesta scala.util
. Ja muista
että Random.nextInt(n)
palauttaa luvun nollan ja n-1
:n väliltä.
A+ esittää tässä kohdassa tehtävän palautuslomakkeen.
Ohjastusta näppäimistöllä
MoreApps-moduulin pakkauksessa o1.trotter
on pieni sovellus, jossa
voi juoksuttaa virtuaalista heppaa ruudukkotaustaa vasten. Heppa
liikkuu ruudusta toiseen kellon tikittäessä. Sen suunta vaihtuu
nuolinäppäimillä, tai ainakin on tarkoitus vaihtua.
Pakkauksesta löytyy luokka TrotterGame
, jota käytämme aihealueen
mallina. Voit tutustua sen koodiin muiltakin osin, mutta tämän
tehtävän kannalta keskeiset asiat on selitetty tässä:
val game = TrotterGame(5, 40)game: o1.trotter.TrotterGame = a 5-by-5 grid game.horseHeadingres12: o1.Direction = Direction.Right game.horseHeading = Direction.Up
Tässä esimerkissä luodaan pieni maailma hepan temmellyskentäksi. Siinä on viisi kertaa viisi ruutua, ja heppa askeltaa 40 koordinaattiyksikköä eli yhden ruudun kerrallaan (ks. kuva).
Muuttujan horseHeading
arvo on O1Libraryyn
kuuluvaa tyyppiä
Direction
. Direction
kuvaa suuntia sellaisissa
kaksiulotteisissa koordinaatistoissa, joiden
sijainteja kuvaamme Pos
-olioilla.
Kyseessä on var
-muuttuja, joten voimme sijoittaa
sille uuden arvon. Mielekkäitä arvoja ovat tässä
Direction.Up
, Direction.Down
, Direction.Right
ja Direction.Left
.
Samasta pakkauksesta löytyy myös TrotterApp.scala
, joka luo isomman
ruudukon. Kokeile ajaa se. Heppa liikkuu. Voit painella nuolinäppäimiä,
mutta huomaat, että hepan saa käännettyä niillä vain ylös.
Annetussa käyttöliittymässä on valmiina grafiikan tuottava koodi ja
onTick
-metodi. Lisäksi siellä on alku onKeyDown
-metodille, jonka
tehtävänä on tulkita näppäinten (Key
) painallukset ja valita hepalle
näppäintä vastaava suunta (Direction
). Annettu koodi on tällainen:
override def onKeyDown(key: Key) =
if key == Key.Up then
game.horseHeading = Direction.Up
Koodissa esiintyy kaksi eri Up
-käsitettä:
Key.Up
on vakio, joka tarkoittaa ylöspäin
osoittavaa nuolinäppäintä. Direction.Up
on suunta suoraan ylös, kohti pienempiä
y-koordinaatteja.
Virallinen tehtäväsi on vain täydentää tämä metodi sellaiseksi, että
se ohjaa heppaa myös muihin kolmeen pääsuuntaan (Right
, Down
,
Left
). Voit tehdä tämän lisäämällä metodiin vastaavia if
-käskyjä
(vaikka koodista näin konstein tuleekin toisteista).
Voit myös kehitellä ohjelmaa pidemmälle haluamallasi tavalla.
A+ esittää tässä kohdassa tehtävän palautuslomakkeen.
Kiihdytystä näppäimistöllä
MoreApps-moduulin pakkauksessa o1.charger
on edellistä muistuttava
sovellus, jossa kappaletta liikutetaan koordinaatistossa. Tässä
sovelluksessa näppäimet antavat “ryntääjälle” vauhtia, joka kasvaa
näppäintä pohjassa pidettäessä.
Annettu koodi ei saa ryntääjää liikkeelle. Korjaa asia:
Täydennä
onKeyDown
-metodi vastaavaksi kuin aiemmassa tehtävässä: käyttöliittymän on havaittava neljän nuolinäppäimen painallukset ja kutsuttava niitä vastaavillaDirection
-parametreilla ryntääjänaccelerate
-metodia.Tutustu
Charger
-luokan koodiin. Luokan haluttu toiminta on kuvattu koodin kommenteissa. Suuri osa toiminnasta on jo toteutettu, mutta huomaat, että osia puuttuu.Täydennä
if
-käskyn haarat metodiinaccelerate
niin, että ne säätävät ryntääjän vauhtia ja kulkusuuntaa halutusti.Täydennä
move
-metodi niin, että se muuttaa ryntääjän sijaintia vauhdin ja suunnan perusteella.Annetussa koodissa on esimerkki
Direction
-oliondx
-muuttujasta, joka kertoo, paljonko x-koordinaatti muuttuu, jos liikutaan yksi yksikkö kyseiseen suuntaan.Direction.Right
indx
on siis +1,Left
in -1, ja ylä- ja alasuuntien nolla. Vastaavasti on olemassady
.Tuota tietoa hyödyntämällä on
move
yksinkertaisempi toteuttaa. (Voit myös palata etsimään vinkkiä edellisen tehtävänTrotterGame
-luokasta.)
Kokeile ohjelmaa.
Ryntääjän kuvan soisi vastaavan sen suuntaa. Muutos on helppo. Tiedämme jo, että
Pic
-luokassa on pyörittämiseen sopivat metoditclockwise
jacounterclockwise
(luku 2.3). Lisäksi jokaisellaDirection
-oliolla on metoditoDegrees
, jota voi käyttää näin:Direction.Up.toDegreesres13: Double = 90.0 Direction.Left.toDegreesres14: Double = 180.0
Vapaasti muotoillen: metodi kertoo, montako astetta kyseinen suunta poikkeaa oikealle osoittavasta suunnasta. Esimerkiksi
Direction.Up
on 90 astetta (vastapäivään)Direction.Right
ista.Muokkaa käyttöliittymän
makePic
-metodia niin, että se pyöräyttää kuvan osoittamaan kohti menosuuntaa.
A+ esittää tässä kohdassa tehtävän palautuslomakkeen.
Nopeuden mallintaminen Velocity
-luokalla
Äsken kuvasimme erikseen ryntääjän vauhtia (sijainnin muutosten suuruutta) ja suuntaa. Yhdessä vauhti ja suunta muodostavat nopeuden (velocity).
On luontevaa ja kätevää määritellä nopeuden käsitettä kuvaamaan oma luokkansa. Eikä sinun nyt tarvitse määritellä sitä itse: nopeus on monessa ohjelmassa hyödyllinen käsite, jota vastaava luokka löytyy kurssin ohjelmakirjastosta.
val test = Velocity(Direction.Up, 12.3)testVelocity: o1.world.Velocity = Velocity(Direction.Up,12.3) test.directionres15: o1.world.Direction = Direction.Up test.speedres16: Double = 12.3
Nopeus koostuu suunnasta ja vauhdista.
Velocity
-luokassa on paljon metodeita, joista osasta on hyötyä myöhemmin
ja osa sopii käytettäväksi juuri nyt:
Silmäile
Velocity
-luokan dokumentaatiota. Katso erityisesti metoditfaster
,noFasterThan
janextFrom
.Refaktoroi
Charger
-luokkaa (eli muokkaa koodia sen toiminnallisuutta muuttamatta): Korvaa erillisetangle
- jaspeed
- muuttujat yhdelläVelocity
-tyyppisellä muuttujalla. Käytä tätä muuttujaa metodienheading
,accelerate
jamove
uusituissa versioissa.Älä koske luokan julkiseen rajapintaan. Metodien tulee edelleen tehdä samat asiat kuin ennenkin.
A+ esittää tässä kohdassa tehtävän palautuslomakkeen.
Sulavaa liitoa näppäimistöllä
Äskeisessä ohjelmassamme on monia vajavaisuuksia. Härkä kääntyy kovin jähmeästi. Lisäksi tapa, jolla näppäimenpainalluksiin reagoidaan, ei ole teknisesti tyydyttävä:
Ohjelmaa ajava ympäristö kutsuu
onKeyDown
-metodia, kun näppäin painuu alas. Lisäksi tuo metodi tulee kutsutuksi silloin tällöin niin kauan kuin näppäin pysyy alhaalla. Näiden myöhempienonKeyDown
-kutsujen määrä ei kuitenkaan ole standardi ja riippuu osin ympäristöstä, jossa ohjelmaa ajetaan. Ohjelmamme käyttäytyminen ei siksi ole luotettavalla pohjalla.Saman
onKeyDown
-metodin luonteesta johtuen usean näppäimen käyttö yhdistelmänä ei toimi niin kuin voisi toivoa: jos näpäytät yhtä nuolinäppäintä toisen ollessa pohjassa, niin ohjelma "unohtaa" pohjassa olleen suunnan. (Kokeile.) Tämä ei tunnu luonnolliselta eikä lupaa hyvää, jos vaikka haluaisimme liikuttaa härkää vinoon kahden näppäimen yhdistelmällä.
Käsitellään pohjaan painetut näppäimet toisin. Tämä toinen tapa on aavistuksen mutkikkaampi mutta toisaalta helpottaa sulavampien liikkeiden ohjelmointia.
Pakkauksessa o1.glider
on pohjakoodi "liituria" ohjaavalle ohjelmalle.
Se muistuttaa äskeistä ohjelmaa monin osin.
Tutustu
GliderApp.scala
an. Huomaa ainakin nämä:onTick
-tapahtumankäsittelijä yksinkertaisesti komentaa liituria liitämään kullakin kellonlyömällä.Keskeinen uudistus verrattuna edelliseen ohjelmaan löytyy metodista
onKeyDown
: se ei varsinaisesti kasvata liiturin nopeutta vaan vain asettaa tiedon siitä, että "kaasu on pohjassa", kun ylänuolinäppäintä painetaan.Vastaava
onKeyUp
käsittelee näppäimen irtipäästötapahtumia.
Tutki
Glider
-luokkaa. Huomaa ainakin nämä:Liiturin nopeus on kuvattu
Velocity
-oliolla.Lisäksi liiturilla on kolme
Boolean
-tyyppistä ominaisuutta, jotka kertovat, onko kaasu pohjassa sekä onko "rattia" käännetty vasempaan tai oikeaan.Liikkeestä huolehtii
glide
-metodi apumetodeineen. Se säätää nopeutta ohjaimien perusteella ja liikuttaa liituria säädetyn nopeuden mukaan.Liiturissa ei ole jarruja mutta "kitka" hidastaa liituria hieman joka liikahduksen lopuksi, joten ilman kaasutusta liituri pysähtyy aikanaan itsekseen.
Varsinainen liiturin siirtäminen ja kitkan huomiointi ovat valmiina. Toteuta nopeuden ja suunnan säätö; tavoite on selitetty
glide
-metodin kuvauksessa.Huomaat, että
glide
delegoi tämän osatehtävän yksityiselle apumetodilleadjustVelocity
. Voit tehdä tarvittavat muutokset sinne.
Voit jo tässä vaiheessa koeajaa sovelluksen. Liiturin pitäisi lähteä ylänuolta painaessa eteenpäin ja vähitellen hidastua itsestään. Se ei vielä käänny.
Täydennä tapahtumankäsittelijät niin, että ne välittävät tiedon sivunuolten painalluksista
Glider
-oliolle.
A+ esittää tässä kohdassa tehtävän palautuslomakkeen.
Toinenkin liituri?
Jos haluat, voit kokeilla lisätä näkymään toisenkin liiturin, joka liikkuu esimerkiksi W-, A-, ja D-näppäimillä.
Jos tuloksena syntyi toimivaa mutta toisteista koodia, voit miettiä, miksi niin kävi. Kurssin edetessä löydämme lisää keinoja toiston kitkemiseen.
Lisänäppäimiä
Miten olisi helppo reagoida esimerkiksi Shift-painallukseen hiirellä? Tai selvittää, onko Shift-, Ctrl-, tai Alt-erikoisnäppäin pohjassa, kun toista näppäintä painetaan?
Luvun 3.1 lisätehtävässä käsittelijämetodin parametrina oli
hiirenklikkausta kuvaava MouseClicked
-olio eikä pelkkä klikkauksen
sijainti. Tapahtumankäsittelijoitä voi muutenkin määritellä niin,
että käsittelijämetodi saa parametrikseen viittauksen kyseistä
tapahtumaa yleisesti kuvaavaan olioon. Tällaiselta tapahtumaa
kuvaavalta oliolta voi pyytää tiedon esimerkiksi siitä, onko tietty
erikoisnäppäin painettuna tapahtumahetkellä. Tässä pari esimerkkiä:
override def onClick(mouseEvent: MouseClicked) =
println(mouseEvent.isControlDown)
override def onKeyDown(keyPressEvent: KeyPressed) =
println(keyPressEvent.isAltDown)
Huomaa parametrimuuttujien tyypit.
Voit kokeilla lisätä johonkin aiemmista ohjelmista tällaiset metodit.
Voit myös etsiä muita vastaavia tapahtumankäsittelijöitä View
-luokan
dokumentaatiosta. Ehkä kehität myös
jonkin sovelluksen, jossa erikoisnäppäimillä on vaikutus ohjelman
toimintaan?
Lisälukemista satunnaisuudesta
Satunnaisuuden sovelluksia
Ylempänä jo mainittiinkin johdantoartikkeli Introduction to Randomness and Random Numbers.
Satunnaisuus tuottaa aina harmaita hiuksia, kun ei sitä oikeasti ole. Tavallaan.
Missä tarvitaan satunnaisempaa satunnaisuutta kuin mitä vaikka tietokoneella voidaan tuottaa?
Vaikkapa nettipokerissa.
Isot simulaatiot, jollaisia käytetään esimerkiksi sään ennustamiseen, voivat toimia huonosti, jos tuotettujen satunnaislukujen jakauma on vähänkin pielessä.
Tietyissä yhteyksissä heikko satunnaisuus aiheuttaa tietoturvaongelmia. Jos satunnaislukugeneraattori on ennustettavissa, sitä voidaan hyödyntää hyökkäyksissä.
Lisätietoja löytyy esimerkiksi englanninkielisen Wikipedian artikkelista Applications of Randomness.
Yhteenvetoa
Satunnaisten lukujen arpominen ei ole ongelmatonta.
Muun muassa Scala-peruskirjastossa on välineitä näennäisen satunnaisuuden tuottamiseen.
Luokan sisäiseen käyttöön voi laatia yksityisiä apumetodeita.
Lukuun liittyviä termejä sanastosivulla: if; näennäissatunnaisluku, satunnaislukujen siemen; yksityinen.
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!
Materiaalin luvut tehtävineen ja viikkokoosteineen on laatinut Juha Sorva.
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, Kaisa Ek, Joonatan Honkamaa, Antti Immonen, Jaakko Kantojärvi, Onni Komulainen, Niklas Kröger, Kalle Laitinen, Teemu Lehtinen, Mikael Lenander, Ilona Ma, Jaakko Nakaza, Strasdosky Otewa, Timi Seppälä, Teemu Sirkiä, Joel Toppinen, Anna Valldeoriola Cardó ja Aleksi Vartiainen.
Lukujen alkuja koristavat kuvat ja muut vastaavat kuvituskuvat on piirtänyt Christina Lassheikki.
Yksityiskohtaiset animaatiot Scala-ohjelmien suorituksen vaiheista suunnittelivat Juha Sorva ja Teemu Sirkiä. Teemu Sirkiä ja Riku Autio toteuttivat ne apunaan Teemun aiemmin rakentamat työkalut Jsvee ja Kelmu.
Muut diagrammit ja materiaaliin upotetut vuorovaikutteiset esitykset laati Juha Sorva.
O1Library-ohjelmakirjaston ovat kehittäneet Aleksi Lukkarinen, Juha Sorva ja Jaakko Nakaza. Useat sen keskeisistä osista tukeutuvat Aleksin SMCL-kirjastoon.
Tapa, jolla 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+ luotiin alun perin Aallon LeTech-tutkimusryhmässä pitkälti opiskelijavoimin. Nykyään tätä avoimen lähdekoodin projektia kehittää Tietotekniikan laitoksen opetusteknologiatiimi ja tarjoaa palveluna laitoksen IT-tuki; sitä ovat kehittäneet kymmenet Aallon opiskelijat ja muut.
A+ Courses -lisäosa, joka tukee A+:aa ja O1-kurssia IntelliJ-ohjelmointiympäristössä, on toinen avoin projekti. Sen suunnitteluun ja toteutukseen on osallistunut useita opiskelijoita yhteistyössä O1-kurssin opettajien kanssa.
Kurssin tämänhetkinen henkilökunta löytyy luvusta 1.1.
Joidenkin lukujen lopuissa on lukukohtaisia lisäyksiä tähän tekijäluetteloon.
Random
-oliot ovat "satunnaislukugeneraattoreita". Niitä kuvaava luokka löytyy pakkauksestascala.util
. (Tämä Scala APIn pakkaus sisältää sekalaisia työkaluja. Sen nimi tulee sanasta utilities.)