Nuorten koodauskerho 2016 - syksyn 3. kerran tehtävät

Aliohjelmat

Ohjelmat koostuvat aliohjelmista, jotka jokainen hoitavat omaa tehtäväänsä. Aliohjelmat ovat siis ohjelmien rakennuspalikoita.

Ohjelman jakaminen aliohjelmiin helpottaa koodin hallintaa.

Alla on aliohjelma Summa, joka ottaa parametrina luvut a ja b ja laskee niiden summan:

# kk-aliohjelmat1

Aliohjelman rakenne


Aliohjelmat koostuvat esittelyrivistä ja aliohjelman sisällöstä, eli rungosta.

Esittelyrivillä olevat asiat tulevat aina tietyssä järjestyksessä. Näitä asioita ovat

  • Saantimääre: Määrittää voiko muut ohjelmat käyttää aliohjelmaa. Tätä ei ole pakko kirjoittaa, oletuksena se on private, eli ei-julkinen.
  • Paluuarvon tyyppi: Määrittää minkä tyyppisen arvon aliohjelma palauttaa. Jos ei palauta mitään niin tähän tulee void. Paluuarvosta kerrottu lisää alempana.
  • Staattisuus: Tämä selitetään tarkemmin alempana.
  • Aliohjelman nimi: Aliohjelmien nimet kirjoitetaan isolla alkukirjaimella ilman välilyöntejä.
  • Parametrit: Aliohjelmalle tuodut muuttujat. Näitä ei ole pakko olla yhtään. Tämä selitetään tarkemmin alempana.

Aliohjelman runkoon kirjoitetaan aliohjelman toteutus. Runko kirjoitetaan aina aaltosulkujen väliin.

Parametrit ja kutsuminen

Parametreilla aliohjelmalle voidaan kuljettaa tietoa. Tieto on yleensä sellaista, joka määrittää millä tavalla aliohjelman tulee toimia.

Aliohjelman kutsuminen tapahtuu kirjoittamalla aliohjelman nimi ja sen jälkeen sulkuihin parametrit ja lopuksi puolipiste. Kutsumisella tarkoitetaan aliohjelman käyttämistä. Kutsumisen seurauksena aliohjelman rungon sisällä olevat koodirivit suoritetaan.

Esimerkiksi LuoPallo nimistä aliohjelmaa voi käyttää, eli kutsua näin:

LuoPallo();

Jos LuoPallo ottaisi parametrina vaikka kaksi lukua, niin kutsuminen tapahtuisi näin:

LuoPallo(125, 60);

Alla olevassa esimerkissä LuoPallo ei ota yhtäkään parametria ja luo pallon aina keskelle pelimaailmaa, eli origoon. Palloja tulee nyt siis kolme kappaletta päällekkäin. Paluuarvon tyyppinä on void, koska aliohjelma ei palauta mitään.

# kk-aliohjelmat3

Lisätään LuoPallo:lle kaksi parametria, x ja y, jotka määrittävät luotavan pallon sijainnin. Kummatkin ovat desimaalilukuja, joten niiden tyyppi on double.

Aliohjelman kutsuminen tapahtuisi nyt näin:

# kk-aliohjelmat4

Samaa aliohjelmaa käytetään nyt kolme kertaa, mutta joka kerralla se toimii eri tavalla, koska parametrit ovat erilaiset jokaisella kutsukerralla.

Parametrien välitystä on havainnoillistettu alla olevalla animaatiolla:

Paluuarvo

Aliohjelman paluuarvon tyyppi määrittää minkä tyyppistä tietoa aliohjelmasta saadaan ulos.

Arvon palauttaminen tapahtuu return:illa, joka tulee usein aliohjelman loppuun. Returnin voi jättää pois jos aliohjelma ei palauta mitään. Return aiheuttaa aina sen, että aliohjelman suoritus lopetetaan ja aliohjelmasta poistutaan.

Esimerkki aliohjelmasta, joka luo pallon ja palauttaa sen:

PhysicsObject LuoPallo()
{
    PhysicsObject pallo = new PhysicsObject(30, 30);
    pallo.Shape = Shape.Circle;
    return pallo;
}

Esimerkki aliohjelmasta, joka ottaa neljä desimaalilukua ja palauttaa niiden keskiarvon:

double Keskiarvo(double a, double b, double c, double d)
{
    double tulos = (a + b + c + d) / 4.0;
    return tulos;
}

Staattisuus

Staattisten aliohjelmien, eli sellaisten joista sana static löytyy, täytyy pystyä tekemään kaikki toimintonsa pelkästään parametriensa avulla.

Staattiset aliohjelmat ovat luokkakohtaisia aliohjelmia. Aliohjelmat, joista se puuttuu, ovat oliokohtaisia (toiselta nimeltään metodeja). Ei-staattisista aliohjelmista voi käyttää staattisia aliohjelmia, mutta sama ei päde toisinpäin.

Staattisuus on siis olio-ohjelmoinnin käsite, johon tässä vaiheessa ei vielä perehdytä kunnolla, mutta toistaiseksi nyrkkisääntönä voit pitää sitä, että static tulee komentoriviohjelmiin, mutta sen voi jättää pois Jypeli-peleistä, koska niissä on usein tarvetta päästä aliohjelmasta käsiksi pelin ominaisuuksiin.

Taulukot

Taulukko on ohjelmoinnissa käytetty tietorakenne.

C#-ohjelmointikielessä taulukko esitellään kirjoittamalla muuttujatyypin perään hakasulut eli merkit [ ja ], esimerkiksi int[]. Joissain muissa kielissä hakasulut saattaisivat tulla vasta muuttujan nimen perään.

Esimerkki muuttujasta, joka voi sisältää yksittäisen kokonaisluvun, sekä taulukollisesta lukuja:

int lukumaara;
int[] kokonaisluvut;

Tietokoneen täytyy varata muistia muuttujia varten. Kokonaisluvun (eli muuttujatyypin int) tapauksessa varattavan muistin määrä on kiinteä, mutta jotta kokonaislukutaulukkoa (muuttujatyyppiä int[]) varten osataan varata sopiva määrä tilaa, täytyy ohjelmoijan kertoa, kuinka monta lukua taulukkoon aiotaan tallentaa.

Jos taulukkoon halutaan varata muistia kymmenelle luvulle, muuttujan esittely ja alustus voidaan tehdä seuraavalla tavalla new-avainsanan avulla:

int[] kokonaisluvut = new int[10];

Seuraavassa kuvassa on esitelty, miltä taulukko näyttää tietokoneen muistissa:

Kokonaislukutaulukon luominen ja sen sisältö
Kokonaislukutaulukon luominen ja sen sisältö

C#-kielessä int-taulukon jokainen arvo on aluksi oletuksena 0.

Taulukoissa jokaisella tallennuspaikalla eli alkiolla on oma numeronsa. Numerointi alkaa C#-ohjelmointikielessä paikasta [0].

Kymmenpaikkaisessa taulukossa on siis paikat, joiden numeroinnit ovat: [0], [1], [2], [3], [4], [5], [6], [7], [8], [9].

Paikassa numero [10] olisi taulukon yhdestoista alkio, jos sellaiselle olisi varattu tilaa.

Kertotaulu

Tallennetaan seuraavaksi lukuja kokonaislukutaulukkoon. Täytä loputkin taulukon alkiot ja paina sitten Aja-painiketta, niin näet lopputuloksen.

# kk3-taulukot1

Jos haluat harjoitella viime kerralla käsiteltyjen silmukoiden käyttöä, voit muuttaa myös kertotaulun sisältävän taulukon luomisen sellaiseksi, että se tehdään silmukassa!

for (int i = 0; i < 12; i++)
{
    kertotaulu[TÄHÄNJOKIN] = TÄHÄNJOTAINVÄHÄNMUUTA * 2;
}   

Käytä TÄHÄNJOKIN- ja TÄHÄNJOTAINVÄHÄNMUUTA-kohdissa apuna muuttujan i sisältämää arvoa. Jos et keksi mitä muokattavien kohtien tilalle tulee, kysy vinkkiä ohjaajalta.

Jypeli-sijainteja sisältävä taulukko

Luvut eivät ole ainoita asioita, joita voi säilyttää taulukoissa. Mitä tahansa muuttujia voi tallentaa taulukoihin, kunhan tekee sopivaa tyyppiä olevan taulukon.

Tehdään tyyppiä Vector[] oleva taulukko, joka sisältää Jypelistä tuttuja Vector-sijainteja.

Kertauksena: vektori on sellainen muuttuja, joka sisältää kaksi lukua, X:n ja Y:n. Sitä voidaan käyttää viittaamaan koordinaatiston tiettyyn pisteeseen.

Esim. seuraava koordinaatit-niminen taulukko on kolmen paikan mittainen eli se voi sisältää kolme vektoria:

Vector[] koordinaatit = new Vector[3];

Sijoitetaan paikkaan numero [0] eli ensimmäiseen paikkaan uusi koordinaatti (0, 0):

koordinaatit[0] = new Vector(0, 0);

Tallennetaan myös seuraaviin paikkoihin koordinaatit:

koordinaatit[1] = new Vector(120,170);
koordinaatit[2] = new Vector(-120, 170);

Aiemmin tällä sivulla esiteltiin aliohjelma LuoPallo(double x, double y), jolla pystyy tekemään tietynlaisen kiinteän kokoisen ympyrän haluttuun kohtaan. Kyseinen aliohjelma ottaa kaksi parametria, joiden tyyppi on double eli desimaaliluku. Niistä ensimmäinen kertoo x- eli vaakakoordinaatin ja toinen y- eli pystykoordinaatin.

Jotta voisimme kutsua aliohjelmaa LuoPallo, täytyy parametreiksi antaa yksittäisestä Vector-muuttujasta sen sisältämät double-luvut X ja Y erikseen. Taulukossamme koordinaatit oli ensimmäinen alkio paikassa numero [0]. Siispä aliohjelman kutsuminen onnistuu esimerkiksi näin:

LuoPallo(koordinaatit[0].X, koordinaatit[0].Y);

Kaikki ylläoleva lisättynä yhteen ohjelmaan:

# kk-taulukot2

Ohjelmaa voi parannella vielä tekemällä LuoPallo-aliohjelman kutsut silmukassa. Näin toteutettuna sijainteja voi lisätä mielin määrin, eikä koodia tarvitse muuttaa muualta kuin sijaintien määrittelykohdasta.

for (int i = 0; i < koordinaatit.Length; i++)
{
    LuoPallo(koordinaatit[i].X, koordinaatit[i].Y);
}

Tee käsin tämä muutos ohjelmaan. Ei kannata kopioida koodia suoraan, jotta ymmärrät paremmin, mitä pitää muuttaa.

Listat

Taulukoissa on peliohjelmointia ajatellen yksi huono puoli. Niiden maksimikoko on pakko tietää jo siinä vaiheessa, kun taulukon esittelee. Toinen vaihtoehto on käyttää listaa, jonka koko voi vaihdella kesken ohjelman suorituksen.

Lista esitellään ja alustetaan näin:

List<Vector> sijainnit = new List<Vector>();

Listaan voi lisätä alkioita metodilla Add():

sijainnit.Add(new Vector(0, 0));
sijainnit.Add(new Vector(190.8, 185.0);

Listat toimivat alkioiden arvojen lukemisen kannalta samalla tavalla kuin taulukotkin. Alkioiden paikkanumerointi lähtee samoin [0]:sta.

Taulukoiden kohdalla taulukonNimi.Length antoi taulukon pituuden, mutta listoilla on sen sijaan Count-niminen ominaisuus (esim. sijainnit.Count), joka kertoo kuinka monta alkiota listaan on sillä hetkellä lisättynä.

Listojen huono puoli on se, että ne voivat viedä enemmän tilaa, koska niitä varten varataan suorituksen aikana jonkin verran ylimääräistä muistia.

Peleissä listoja voi hyödyntää esimerkiksi erilaisten tarkastuspisteiden (engl. checkpoint) lisäämisessä. Niiden määrä saattaa vaihdella pelikentästä toiseen, joten tietyn taulukon kokoinen tietorakenne ei välttämättä kävisi. Kenttää ladatessa tallennetaan listaan ylös kaikki halutut pisteet, ja pelin aikana niitä voidaan hyödyntää. Myös eri sikiämispisteiden (engl. spawn point) koordinaatit kannattanee tallentaa listaan.

Muokkaa aiempaa palloja piirtänyttä aliohjelmaa sellaiseksi, että se sisältää vektorit List<Vector>-tyyppisessä tietorakenteessa. Huomaa, että sinun ei tarvitse tietää alussa, että koordinaatteja tulee olemaan tasan 3 kappaletta.

# kk-taulukot3

Haastetehtävät

wow

25 Nov 16

1. tehtävä

Kirjoita aliohjelma nimeltään FahrenheitToCelsius, joka palauttaa parametrina viedyn Fahrenheit-lämpötilan Celsius-asteina.

Esimerkkejä kuinka Fahrenheit-asteita muunnetaan Celsius-asteiksi löytyy Fahrenheit-asteikon Wikipedia-sivulta.

Koodilaatikon alareunasta löytyvä Test-painike testaa aliohjelman toimintaa muutamilla eri lämpötiloilla. Jos muunnokset menevät oikein niin saat yhden pisteen tästä tehtävästä.

Jos saat virheilmoituksen, jossa lukee "The name `FahrenheitToCelsius' does not exist in the current context", niin kirjoitit aliohjelman nimen väärin.

Vinkki 1: Lämpötila kannattaa esittää desimaalilukuna, eli double tyyppisenä lukuna.

Vinkki 2: Merkkaa aliohjelma staattiseksi (lisää static sana esittelyriville), koska kyseessä on komentoriviohjelma.

# kk3-haastetehtava1

2. tehtävä

Aiemmin tällä sivulla oli esimerkki keskiarvon laskevasta aliohjelmasta. Toteuta sellainen versio aliohjelmasta Keskiarvo, että sille voidaan viedä 4 double-luvun sijasta taulukollinen lukuja eli yksi tyyppiä double[] oleva muuttuja. Aliohjelman on palautettava (return) yksi double-tyyppinen desimaaliluku.

Esimerkiksi jos käytössä olisi double[]-tyyppinen taulukko, jossa olisi luvut {3.8, 13.2, -5.0}, niin keskiarvo olisi 4.0. Keskiarvo lasketaan niin, että summataan yhteen kaikki taulukossa olevat lämpötilat ja jaetaan saatu tulos lämpötilojen lukumäärällä.

3.8 + 13.2 + -5.0 = 12.0
12.0 / 3 = 4.0

Koodilaatikon alareunasta löytyvä Test-painike testaa aliohjelman toimintaa muutamilla eri taulukollisella lämpötiloja. Jos keskiarvojen laskemiset menevät oikein, saat yhden pisteen tästä tehtävästä.

Jos saat virheilmoituksen

/Lampo2.cs (Csharp) || skipped: no tests
error CS2001: Source file `/Lampo2Test.cs' could not be found

...niin et ole kirjoittanut aliohjelman Keskiarvo esittelyriviä oikein.

Jos saat virheilmoituksen, jossa lukee "The name `Keskiarvo' does not exist in the current context", niin kirjoitit aliohjelman nimen väärin.

Vinkki: Katso alkuperäinen Keskiarvo-aliohjelman toteutus, jossa parametrina vietiin 4 erillistä desimaalilukua, ja muokkaa oma versiosi sen pohjalta.

Vinkki 2: Huomaa, että kirjoitat pääohjelman Main() rungon aaltosulkujen { ja } väliin alkuperäisten vihreiden TODO-kommenttien tilalle! Myös aliohjelman Keskiarvo sisältö tulee erillisten, itse lisäämiesi, aaltosulkujen väliin!

Vinkki 3: Merkitse aliohjelma Keskiarvo staattiseksi (käytä avainsanaa static aliohjelman esittelyrivillä).

Vinkki 4: Esimerkiksi taulukosta double[] lampotilat saa alkioiden määrän näin: lampotilat.Length

# kk3-haastetehtava2

These are the current permissions for this document; please modify if needed. You can always modify these permissions from the manage page.