```

Demotilanne:

  • Pisteet päivittyvät pienellä viiveellä.
  • Värit: Punainen - puutteellinen. Vihreä - hyväksytty (vähintään 6p, joista 2p tähtiä)
# aikajana

Error in expanding macros: 'luentoaiheet' is undefined

# fields

Ohjelmointi 1, k 2024 / Demo 10

Tehtävät perustuvat luentoihin: 19 ja 20.

OPPIMISTAVOITTEET

Täytä sitä mukaa, kun koet oppineesi uusia asioita. Työkirja-sivulla näet yhteenvedon kaikkien demojen osalta.

# Oppimistavoitteet

Demoista

Ville 1

Tee Ville-tehtävät: 8.1-8.5. Tästä Villeen Muista: Villen käyttöohje.

# villev1
# tauno2p

Tauno* (max 2p)

Tämä oli syksyn 2015 tenttitehtävä. Vaikka tästä saakin tähtitehtäviin vaadittavat 2 pistettä, on kaveriksi tehtävä minimeihin joku toinenkin ohjelmatehtävä.

Katso Demo 2:n ATK-tehtävä. Tee aliohjelma ja testit, jotka toteuttavat tuon määrityksen. Testejä kirjoitettava vähintään saman verran kuin Demossa 2 oli "testitapauksia". Muista katsoa ko. tehtävän käsittely demosta 2.

Ajovirheiden tulkinta

# tauno

Tehtävä 1*. Toisto rekursiolla I

Lue ensin: 16. Silmukat ja 22. Rekursio.

Tähän mennessä kaikki toisto on tehty demoissa silmukoita käyttäen. Hyvin usein toisto voidaan kuitenkin tehdä silmukoiden lisäksi myös rekursiolla. Joissakin tilanteissa silmukat ovat parempi ratkaisu, kun taas toisissa rekursio. Kummankaan ei voida yksiselitteisesti sanoa olevan toinen toistaan parempi vaihtoehto.

Tehtävässä on tarkoituksena toteuttaa aliohjelma Kertoma sekä silmukalla että rekursiolla.

a) Silmukalla

Tee funktio Kertoma(luku), joka laskee ja palauttaa tietyn luvun kertoman. Käytä toteutuksessa haluamaasi silmukkaa.

Huom! Matemaattisten sääntöjen mukaan nollan (0) kertoma on 1.

# kertoma1

b) Rekursiolla

Muokkaa nyt a-kohdan funktio Kertoma(luku), toimimaan rekursiolla silmukan sijaan.

# kertoma2

Tehtävä 2. Toisto rekursiolla II

Lue ensin: 16. Silmukat ja 22. Rekursio.

Samanlainen kuin tehtävä 1. Tarkoituksena toteuttaa nyt aliohjelma Potenssi, edelleen sekä silmukalla että rekursiolla.

a) Silmukalla

Tee funktio Potenssi(luku, potenssi), joka laskee ja palauttaa tietyn luvun tietyn potenssin arvon. Tee lisäksi niin, että jos potenssin arvo on negatiivinen, ohjelma palauttaa aina long.MinValue(). Käytä toteutuksessa haluamaasi silmukkaa.

Huom! Matemaattisten sääntöjen mukaan silloin, kun potenssina on nolla (0), on arvo aina 1.

# potenssi1

b) Rekursiolla

Muokkaa a-kohdan funktio Potenssi(luku, potensi) toimimaan rekursiolla silmukan sijaan.

# potenssi2

Tehtävä 3. Merkkien lisäily

Lue ensin: 16. Silmukat, 22. Rekursio ja 27. ASCII-koodi.

Tehtävät 1 ja 2 osoittivat, miten rekursio toimii parhaimmillaan, ja ohjelman toteutus voi olla vain yhden rivin mittainen. Kuten todettu, aina rekursio ei kuitenkaan ole silmukkaa parempi tai yksinkertaisempi ratkaisu.

Tässä tehtävässä tehdään ohjelma LisaaMerkit, joka osaa lisätä StringBuilder-muuttujaan kaikki merkit annetulta väliltä merkkien ASCII-koodiin perustuen. Toisin sanottuna ohjelmalle annetaan yhtenä parametrinä jokin merkki, jonka ASCII-koodi on lähtöpiste, ja toisena parametrinä jokin muu merkki, jonka ASCII-koodi on vuorostaan päätepiste. Kaikki merkit näiden pisteiden väliltä lisätään merkkijonoon.

Ohjelman kuuluu toimia seuraavasti:

    StringBuilder sb = new StringBuilder();
    LisaaMerkit(sb, 'a', 'e');
    Console.WriteLine(sb.ToString());
            // Tulostaa "abcde"


Huom! Joudut käyttämään manuaalista type castia muuttaaksesi tietyn ASCII-koodin (int) merkiksi (char).

a) Silmukalla

Tee aliohjelma LisaaMerkit(jono, eka, vika), joka lisää jonoon kaikki merkit alkaen ekasta ja päättyen vikaan. Käytä toteutuksessa mieleistäsi silmukkaa.

# lisaily1

b) Rekursiolla

Muokkaa a-kohdan funktio LisaaMerkit(jono, eka, vika) toimimaan rekursiolla silmukan sijaan.

# lisaily2

Tehtävä 4. Poikkeukset ja parametrit

Lue ensin: 24. Poikkeukset.

Kurssin ohjelmissa vastaan tulleet ongelmat ja poikkeukset on tähän mennessä kaikki kierretty if -lauseilla. Esimerkiksi tyhjän taulukon tutkiminen on estetty aliohjelman alussa seuraavasti:

if (t.Length < 0) return;

Poikkeukset voidaan kuitenkin käsitellä paremminkin hyödyntämällä try-catch -lausetta. Edellinen esimerkki tehtäisiin sen avulla vaikkapa näin:

try
{
    // ohjelman poikkeusalttiit rivit.
}
catch (IndexOutOfRangeException)
{
    return;
}

Tehdäänkin nyt aliohjelma Merkiksi, joka muuttaa ja palauttaa merkkijonon (string) merkkinä (char). Pidä huolta, että jos merkkijonoa ei voida muuttaa merkiksi (jono on joko tyhjä tai liian pitkä), ohjelma palauttaa sen sijaan sille annetun oletusmerkin.

Tehdään ohjelma sekä if-lauseella että try-catchilla.

a) If-lauseella

Tee aliohjelma Merkiksi(jono, oletus), joka palautta jonon char-tyyppisenä aina, kun mahdollista. Muissa tapauksissa palautetaan oletusmerkki. Käsittele poikkeukset if-lauseella.

# poikkeukset1

b) Try-catch -lauseella

Muokkaa a-kohdan aliohjelman Merkiksi(jono, oletus) poikkeuskäsittely toimimaan try-catch-lauseella if-lauseen sijaan.

Vinkki! catch -lauseelle kannattaa antaa parametriksi kiinniotettavan poikkeuksen tyyppi paremman kontrollin saamiseksi. Tässä tapauksessa kyseessä on FormatException.

# poikkeukset2

c) Kuormittaminen

Lue ensin: 6.5 Aliohjelman kuormittaminen.

Nykyisellään b-kohdan toteutuksen jälkeen aliohjelman Merkiksi(jono, oletus) jokaiseen kutsuun joudutaan syöttämään oletusmerkki parametrinä. Tuo voi tuntua turhalta, jos merkki ei koskaan vaihdu. Ohjelmaan voitaisiin vaihtoehtoisesti "kovakoodata" jokin tietty muuttumaton merkki parametrin sijasta. Toisaalta se voisi olla jopa vieläkin huonompi ratkaisu, sillä silloin palautettavaa oletusmerkkiä ei voida enää vaihtaa ollenkaan.

Monissa kielissä, kuten C#:ssa ja Javassa onkin mahdollista hyödyntää kuormittamista (function overloading) tämän ongelman ratkaisemiseksi. Sillä tarkoitetaan kykyä kirjoittaa useampi kuin yksi samanniminen ohjelma, joilla on joko eri tyyppiset tai eri määrä parametreja. Näin tehtynä esimerkiksi ohjelman Merkiksi kutsuun ei olisi pakko antaa tuota oletusmerkkiä parametriksi, vaikka se edelleen voitaisiin tarvittaessa tehdä.

Laita pääohjelma toimimaan tekemällä aliohjelman Merkiksi(jono, oletus) rinnalle toinen samanniminen aliohjelma Merkiksi(jono), jolle ei anneta toista parametria, ja jossa palautettava oletusmerkki on "kovakoodattuna" itse ohjelman sisälle arvolla 'b'.

# poikkeukset3

d) Valinnaiset parametrit

Lue ensin: Optional arguments.

Tehtävän c-kohdassa käytetty kuormittaminen on toimiva tapa ratkaista ohjelmassa tarvittavien parametrimäärien muodostamia ongelmia. Se on kuitenkin melko työläs keino, sillä joka kerta ohjelma täytyy kirjoittaa kokonaan uusiksi ja ohjelmien lisääntyessä ne vievät paljon tilaa koodissa.

C#:ssa on olemassa toinenkin keino, joka on kenties parempi. Parametreistä on nimittäin mahdollista tehdä valinnaisia (optional). Tämä ajaa saman asian kuin kuormittaminen, mutta useampia ohjelmia ei tarvita.

Muuta aliohjelma Merkiksi(jono, oletus) toimimaan niin, että oletusmerkkinä käytettävä parametri on valinnainen ja sen "kovakoodattu" oletusarvo on 'b'.

Huom! Et tarvitse enää kahta Merkiksi nimistä aliohjelmaa.

# poikkeukset4

Sarja J. Syötteen korjautus (2 p)

Ohjeet sarjatehtävien tekoon

Lue ensin: 13. Ehtolauseet ja Kysyminen käyttäjältä.

Suurimmat ongelmat syntyvät yleensä silloin, kun käyttäjältä kysytään jotain. Käyttäjän antama syöte voi nimittäin olla joko vahingossa tai tarkoituksella virheellinen. Tämä voi johtaa pahimmillaan todella huonoihin lopputulemiin. Kysyvät ohjelmat on siis syytä rakentaa erityisellä huolella tarkastamaan syötteet hyvin, ennen niiden varsinaista käyttöä.

Tässä lyhyessä sarjassa tehdään yksinkertaiseen syötettä kysyvään ohjelmaan syötteen tarkistukset.

Tehtävät

Tehtävä 5. Elämäpisteet

Lue ensin: Jypeli: muuttuja oliolle.

Alla on peli, jossa pelaaja voi ohjata koirahahmoa ja törmäillä meteoreihin, jotka räjähtävät. Pelissä on myös yksi tähti, jonka voi "kerätä". Tällä hetkellä pelissä ei tapahdu mitään muuta kuin meteorien ja tähden tuhoutuminen törmäyksestä pelaajaan.

Kopioi ja siirrä pelin ohjelmakoodi ja tarvittavat kuvat (koira.png, tahti.png, meteori.png) ensin Visual Studioon omaksi projektikseen ja tarkista, että peli toimii.

Tee sitten peliin seuraavat muutokset:

  • Pelaajalla on aluksi 3 elämäpistettä, mitä havainnollistaa elämäpalkki
  • Törmäys meteoriin vähentää pelaajalta 1 elämäpisteen
  • Jos elämäpisteitä on vähemmän kuin 1, pelaaja räjähtää ja tuhoutuu; ruutuun ilmestyy viesti pelin häviämisestä
  • Törmäys tähteen pysäyttää pelaajan liikkeen ja ruutuun ilmestyy viesti pelin voittamisesta


Huom! Peli kaatuu helposti virheellisesti käytettyjen kuvien vuoksi. Tarkista, että käyttämäsi kuvat löytyvät "Content" -hakemistosta ja ovat muutenkin kunnossa.

Vinkki! Jypelissä elämäpalkin voi tehdä ProgressBar -oliolla. PhysicsObject -olion liikkeen saa vuorostaan pysäytettyä esim. antamalla sen nopeudeksi (.Velocity) nollavektorin (Vector.Zero).

Esimerkkikuva pelistä
Esimerkkikuva pelistä


Pelissä käytetyt kuvat:

# elamapisteet

Tehtävä 6. Viitteet I

Alla on ohjelmakoodi ja sen muuttujista piirretty kuva tiettynä ajanhetkenä. Muuta alla oleva kuva vastaamaan toista ajanhetkeä kun listasta on otettu pois paikassa 0 oleva alkio ja lisätty uusi eläin. Älä muuta C#-ohjelmakoodia!

# listaelaimista

Halutessasi voit kokeilla piirto-ohjelmaa DrawIO

# viitekuva10

Tehtävä 7*. Viitteet II

Tämä oli syksyn 2020 tenttitehtävä.

# t63c

Taas piirtomoodissa. Tästä 4 kuvaa, kustakin 0.25 p. Täydennä ensin 1. kuva ja kun siitä saat 0.25p, kopioi täydennys seuraavaan kuvaan ja muokkaa vastaamaan sen tilannetta.

Vinkki: Älä ajattele piirtokieltä ohjelmana, vaan mieti mitä pitää kuvassa missäkin "laatikossa" olla, kun C# ohjelma on halutussa kohdassa ja mistä pitää mennä nuoli mihin. Ja sen sanot piirtokielellä. Esim Count ei tarvitse muuttaa monta kertaa, sen lopullinen arvo riittää.

# d9t10k1
# d9t10k2
# d9t10k3
# d9t10k4

B1. Pienimpien keskiarvon tulostus

Lue ensin: 12.7 Reaalilukujen muotoilu.

Tee ensin funktio PienimpienKeskiarvo, joka palauttaa reaalilukulistan kahden pienimmän (eli pienin ja toiseksi pienein) alkion välisen keskiarvon. Jos keskiarvoa ei voida laskea, palautetaan aina arvo 0.0.

Tee vielä aliohjelma TulostaLista, joka tulostaa käsiteltävän listan ja laskemasi keskiarvon TÄSMÄLLEEN seuraavan esimerkin mukaisessa formaatissa:

List<double> luvut = new List<double>() {0.25, 0.5, 0.125};
double keskiarvo = PienimpienKeskiarvo(luvut);
TulostaLista(luvut, keskiarvo);
    // Tulostaa "Taulukon [0.25, 0.5, 0.125] pienimpien keskiarvo on 0.19."


Huom! Et saa käyttää string -luokan valmista ohjelmaa .Join aliohjelman TulostaLista toteutuksessa.

Vinkki! Kannattaa ehkä hyödyntää joko string -luokan ohjelmaa .Format tai interpolaatiota (eli '$') tulostuksen formatointiin.

# pienimpienKa

B2. Rekursiivinen puu

Lue ensin: 22. Rekursio.

Katso mallia rekursiivisesta kolmion piirtämisestä suoraan canvakselle. Tee mallia muokaten ohjelma, joka piirtää alla olevan kuvan kaltaisen puun puu käyttäen rekursiota:

 * Puun yksi oksa ja kolme muuta rekursiivisesti
 *  x oksan alkupiste
 *  y oksan alkupiste
 *  d oksan suunta radiaaneina
 *  l oksan pituus
 *
 oksa( x, y, d, l) 
     viiva pisteestä (x,y) pisteeseen (x+l*cos(d),y+l*sin(d)) 
     jos l < 2 lopeta
     oksa(x+l*cos(d),y+l*sin(d),d+0.6,l*0.6);
     oksa(x+l*cos(d),y+l*sin(d),d-0.6,l*0.6);
     oksa(x+l*cos(d),y+l*sin(d),d,l*0.3);
# B34
# rekursiivinenPuu

Hyvä alkukulma piirtämiseen on vaikkapa pi/2 ja pituus vajaa puolet ikkunan korkeudesta. Tee ohjelmaan näppäinohjaus, jolla voit vaikuttaa kulman muutoskertoimeen 0.6, pituuden muutoskertoimeen 0.6 (eri luku kuin kulmalle) sekä keskioksan pituuden kertoimeen 0.3.

G1. Korttipakka

Tee ensin luokka Kortti, jolla on attribuutteinaan kortin arvo ja maa.

Tee sitten olioluokka Korttipakka, jolla on attribuuttinaan lista luokan Kortti olioista. Täytä tuo lista (eli korttipakka) oikeilla korteilla luokan Korttipakka konstruktorissa.

Tee luokkaan Korttipakka vielä funktio VedaKortti, joka valitsee pakasta satunnaisesti yhden kortin.

Anna luokan Korttipakka pääohjelmaksi seuraava ja laita se toimimaan:

    public static void Main()
    {
        Korttipakka pakka = new Korttipakka();

        for (int i = 0; i < 10; i++)
        {
            Kortti kortti = pakka.VedaKortti();
            Console.WriteLine($"Vedit kortin [{kortti.GetMaa()} {kortti.GetArvo()}]");
        }
    }


Vinkki! Kortti -luokan attribuutti maa voi olla tyypiltään string, mutta silloin sen käytöstä tulee tökeröä. Siitä kannattaakin ehkä tehdä enum (Enumerable), jonka käyttö on vaivattomampaa.

# pakka

G2. Pyrstötähdet VIII

Ota demojen 9 mallivastaus tehtävään Pyrstötähdet VII ja aja se ensin sellaisenaan.

Tee nyt vielä tähdille oma luokkansa Tahti ja pelaajalle Pelaaja samalla tavalla kuin osassa VII meteoreista tehtiin olio Meteori ja muuta ohjelma toimimaan tehdyillä olioilla.

Kokeile että toimii.

Esimerkkikuva pelistä
Esimerkkikuva pelistä


Huom! Olioluokan Pelaaja on palautettava muuttujaan talletettava pelaaja jollakin tavalla, sillä pelaajalle on pääohjelmassa Begin voitava jotenkin tehdä törmäyskäsittelijät (CollisionHandler).

Pelissä käytetyt kuvat:

# pyrstotahdet

PP

PP-tehtävät (Pahasti Pihalla) on tarkoitettu niille, joilla on vaikeuksia aivan perusasioissa. Tarkoitus on, että nämä ovat helpompia tehtäviä (mutta yhdessä on monta tehtävää), joiden tekemisen jälkeen pakollisen kahden tähtitehtävän tekeminen voi olla on helpompaa. PP-tehtävät eivät ole tarkoitettu niille, jotka ovat tehneet säännöllisesti 4 tai enemmän tehtäviä/kerta.

PP1

a)

Kirjoita for-silmukka, joka tulostaa

 0
 2
 4
 6
 ...
 98

Paina ensin "Näytä koko koodi".

# pp1a

b)

Lataa itsellesi Laskuharjoituksia.cs tiedosto ja täydennä aliohjelmat siten, että pääohjelma tulostaa konsoliin annettujen lukujen tulojen summan 2 * 3 + 4 * 7.

# pp1b

c)

Tee (funktio)aliohjelma, joka laskee (ja palauttaa) tuotteen alennetun hinnan kun viedään parametrina alkuperäinen hinta ja alennusprosentti. Tee pääohjelma, josta kutsut tekemääsi aliohjelmaa ja tulostat sen antaman arvon.

# pp1c

PP2

a)

Tee for-silmukka, joka tulostaa seuraavaa:

1
3
5
7
...
99
# pp2a

b)

Tee aliohjelma LaskeMatkanKesto, joka laskee kuinka kauan jokin matka kestää annetulla matkan pituudella ja keskinopeudella.

# pp2b

c)

Tee (funktio)aliohjelma joka laskee (ja palauttaa) tuotteen alkuperäisen hinnan kun viedään parametrina alennettu hinta ja alennusprosentti. Tee pääohjelma, josta kutsut tekemääsi aliohjelmaa ja tulostat sen antaman arvon. Ks. Näytä koko koodi.

# pp2c

Omaa tuotantoa

Näihin tehtäviin voit palauttaa jonkin oman kurssin tämän hetken oppimistavoitteita vastaavia tehtäviä. Ei kuitenkaan enää jos vastaavat tehtävät on tehty edellä olevissa tehtävissä.

Nämä on tarkoitettu lähinnä niille, joilla ei ole mahdollisuutta tehdä varsinaisia tehtäviä ajallaan esimerkiksi kertausharjoitusten tai sairauden takia. Yleensä jos tulee ajoissa ennakoitavia esteitä, pitäisi perustehtäviä tehdä etukäteen.

Nämä arvostellaan manuaalisesti ja opiskelijan pitää ottaa yhteyttä kurssin opettajiin kun toivoo näitä arvosteltavan. Jos tehtävä on liian lähellä mallivastauksia, ei sitä arvostella tai voidaan pyytää muuttamaan vastaustaan erilaiseksi. Samoin jos tehtävä ei liity viikon oppimistavoitteisiin (vertaa esim tähtitehtävät). Luonnollisesti nuo kaksi ohjelmaa eivät saa olla samanlaisia. Laita ohjelman kommentteihin mitä perustehtäviä nämä korvaisivat ja mikä olisi oma peruste millekin pistemäärälle (se voi olla enemmänkin kuin 1p/tehtävä).

# oma1
# oma2

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