Pakolliset tehtävät on merkitty harmaalla taustavärillä. Pakollisuus tarkoittaa, että kyseiset tehtävät ovat erityisen oleellisia ja niiden tekeminen on hyvin suositeltavaa. Jos joskus jokin "pakollinen" tehtävä jää tekemättä, kurssi ei kuitenkaan kaadu siihen.
Tee luokka henkilö joka toimii seuraavan pääohjelman yhteydessä
public static void main(String[] args) { Henkilo pekka = new Henkilo("Pekka Mikkola", "Korsontie 1 03100 Vantaa"); Henkilo esko = new Henkilo("Esko Ukkonen", "Mannerheimintie 15 00100 Helsinki"); System.out.println( pekka ); System.out.println( esko ); }
siten että tulostuu
Pekka Mikkola Korsontie 1 03100 Vantaa Esko Ukkonen Mannerheimintie 15 00100 Helsinki
Tee luokka Opiskelija
joka perii luokan Henkilo
.
Opiskelijalla on aluksi 0 opintopistettä. Aina kun opiskelija opiskelee, kasvaa opintopistemäärä. Toteuta luokka siten, että seuraava pääohjelma:
public static void main(String[] args) { Opiskelija olli = new Opiskelija("Olli", "Ida Albergintie 1 00400 Helsinki"); System.out.println( olli ); System.out.println( "opintopisteitä " + olli.opintopisteita() ); olli.opiskele(); System.out.println( "opintopisteitä "+ olli .opintopisteita() ); }
tuottaa tulostuksen:
Olli Ida Albergintie 1 00400 Helsinki opintopisteitä 0 opintopisteitä 1
Edellisessä tehtävässä Opiskelija
perii toString-metodin luokalta Henkilo
.
Perityn metodin voi myös ylikirjoittaa, eli korvata omalla versiolla. Tee nyt Opiskelija
:lle oma versio toString:istä joka toimii seuraavan esimerkin mukaan:
public static void main(String[] args) { Opiskelija olli = new Opiskelija("Olli", "Ida Albergintie 1 00400 Helsinki"); System.out.println( olli ); olli.opiskele(); System.out.println( olli ); }
Tulostuu:
Olli (0 op) Ida Albergintie 1 00400 Helsinki Olli (1 op) Ida Albergintie 1 00400 Helsinki
Huom: voit toimia joko luvun 12.2 tai luvun 12.3 tapaan.
Tee Henkilo
:n perivä luokka Opettaja
. Opettajalla on palkka joka tulostuu opettajan merkkijonoesityksessä.
Testaa, että seuraava pääohjelma
public static void main(String[] args) { Opettaja pekka = new Opettaja("Pekka Mikkola", "Korsontie 1 03100 Vantaa", 1200); Opettaja esko = new Opettaja("Esko Ukkonen", "Mannerheimintie 15 00100 Helsinki", 5400); System.out.println( pekka ); System.out.println( esko ); Opiskelija olli = new Opiskelija("Olli", "Ida Albergintie 1 00400 Helsinki"); for ( int i=0; i < 25; i++ ) olli.opiskele(); System.out.println( olli ); }
Aikaansaa tulostuksen
Pekka Mikkola palkka 1200 euroa/kk Korsontie 1 03100 Vantaa Esko Ukkonen palkka 5400 euroa/kk Mannerheimintie 15 00100 Helsinki Olli (25 op) Ida Albergintie 1 00400 Helsinki
Ota pääohjelmassasi käyttöön seuraavan tyyppinen lista:
ArrayList<Henkilo> henkilot = new ArrayList<Henkilo>();
Lisää opettajia ja opiskelijoita listalle. Tee metodi, jonka saa parametrikseen listan ja tulostaa listan sisällä olevat henkilöt. Metodin esittelyrivi ja kutsutapa:
private static void tulostaLaitoksenHenkilot(ArrayList<Henkilo> henkilot){ // tulostetaan kaikki listan henkilöt } public static void main(String[] args) { ArrayList<Henkilo> henkilot = new ArrayList<Henkilo>(); // lisätään listalle opiskelijoita ja opettajia tulostaLaitoksenHenkilot(henkilot); }
Meillä on valmiina käytössämme luokka Varasto
jonka tarjoamat konstruktorit ja metodit ovat seuraavat:
Tälle luokalle aletaan nyt tehdä täydennyksiä aliluokkana.
Hae Varasto-luokan koodi täältä.
Luokka Varasto osaa jo hoidella tuotteen määrän käsittelyn. Nyt tuotteelle halutaan lisäksi tuotenimi ja nimen käsittelyvälineet. Luokan voisi tietysti ohjelmoida alusta alkaen uudelleen, mutta miksi ihmeessä? Ohjelmoidaan Tuotevarasto Varaston aliluokaksi! Toteutetaan ensin pelkkä yksityinen kenttä tuotenimelle, konstruktori ja getteri nimikentälle:
Muista millä tavoin konstruktori voi ensi toimenaan suorittaa yliluokan konstruktorin!
Käyttöesimerkki:
... Tuotevarasto mehu = new Tuotevarasto("Juice", 1000.0, 1000.0); mehu.otaVarastosta(11.3); System.out.println(mehu.getNimi()); // Juice System.out.println(mehu); // saldo = 988.7, vielä tilaa 11.3 ...
Tulostus siis:
Juice saldo = 988.7, vielä tilaa 11.3
Kuten edellisestä esimerkistä näkee, Tuotevarasto-olion perimä toString() ei tiedä (tietenkään!) mitään tuotteen nimestä. Asialle on tehtävä jotain! Lisätään samalla myös setteri tuotenimelle:
Uuden toString()-metodin voisi toki ohjelmoida käyttäen yliluokalta perittyjä gettereitä, joilla perittyjen, mutta piilossa pidettyjen kenttien arvoja saa käyttöönsä. Koska yliluokkaan on kuitenkin jo ohjelmoitu tarvittava taito varastotilanteen merkkiesityksen tuottamiseen, miksi nähdä vaivaa sen uudelleen ohjelmointiin. Käytä siis hyväksesi perittyä toStringiä.
Muista miten korvattua metodia voi kutsua aliluokassa!
Käyttöesimerkki:
... Tuotevarasto mehu = new Tuotevarasto("Juice", 1000.0, 1000.0); mehu.otaVarastosta(11.3); System.out.println(mehu.getNimi()); // Juice mehu.lisaaVarastoon(1.0); System.out.println(mehu); // Juice: saldo = 989.7, vielä tilaa 10.299999999999955 ...
Tulostus siis:
Juice Juice: saldo = 989.7, vielä tilaa 10.299999999999955
Toisinaan saattaa olla kiinostavaa tietää, millä tavoin jonkin tuotteen varastotilanne muuttuu: onko varasto usein hyvin vajaa, ollaanko usein ylärajalla, onko vaihelu suurta vai pientä, jne. Varustetaan siksi Tuotevarasto-luokka taidolla muistaa tuotteen määrän muutoshistoriaa.
Aloitetaan apuvälineen laadinnalla.
Muutoshistorian muistamisen voisi toki toteuttaa suoraankin ArrayList<Double>-oliona luokassa Tuotevarasto, mutta nyt laaditaan kuitenkin oma erikoistettu väline tähän tarkoitukseen. Väline toteutetaan kapseloimalla ArrayList<Double>-olio.
Muutoshistoria-luokan julkiset konstruktorit ja metodit:
Havainnollista olioiden luontia ja käyttöä pienellä ohjelmalla.
Täydennä Muutoshistoria-luokkaa analyysimetodein:
Havainnollista uusien metodien käyttöä ja toimivuutta pienellä ohjelmalla.
Täydennä Muutoshistoria-luokkaa analyysimetodein:
Jos et muista miten varianssi lasketaan, katso mallia ohjelmoinnin perusteiden viikon 3 tehtävästä 5.5
Havainnollista uusien metodien käyttöä ja toimivuutta pienellä ohjelmalla.
Toteuta luokan Tuotevarasto aliluokkana MuistavaTuotevarasto. Uusi versio tarjoaa vanhojen lisäksi varastotilanteen muutoshistoriaan liittyviä palveluita. Historiaa hallitaan Muutoshistoria-oliolla.
Julkiset konstruktorit ja metodit:
Huomaa että tässä esiversiossa historia ei vielä toimi kunnolla; nyt vasta vain aloitussaldo muistetaan.
Käyttöesimerkki:
// tuttuun tapaan: MuistavaTuotevarasto mehu = new MuistavaTuotevarasto("Juice", 1000.0, 1000.0); mehu.otaVarastosta(11.3); System.out.println(mehu.getNimi()); // Juice mehu.lisaaVarastoon(1.0); System.out.println(mehu); // Juice: saldo = 989.7, vielä tilaa 10.3 ... // mutta vielä historia() ei toimi kunnolla: System.out.println(mehu.historia()); // [1000.0] // saadaan siis vasta konstruktorin asettama historian alkupiste... ...
Tulostus siis:
Juice Juice: saldo = 989.7, vielä tilaa 10.299999999999955 [1000.0]
On aika aloittaa historia! Ensimmäinen versio ei historiasta tiennyt kuin alkupisteen. Täydennä luokkaa metodein
Käyttöesimerkki:
// tuttuun tapaan: MuistavaTuotevarasto mehu = new MuistavaTuotevarasto("Juice", 1000.0, 1000.0); mehu.otaVarastosta(11.3); System.out.println(mehu.getNimi()); // Juice mehu.lisaaVarastoon(1.0); System.out.println(mehu); // Juice: saldo = 989.7, vielä tilaa 10.3 ... // mutta nyt on historiaakin: System.out.println(mehu.historia()); // [1000.0, 988.7, 989.7] ...
Tulostus siis:
Juice Juice: saldo = 989.7, vielä tilaa 10.299999999999955 [1000.0, 988.7, 989.7]
Muista miten korvaava metodi voi käyttää hyväkseen korvattua metodia!
Täydennä luokkaa metodilla
Käyttöesimerkki:
MuistavaTuotevarasto mehu = new MuistavaTuotevarasto("Juice", 1000.0, 1000.0); mehu.otaVarastosta(11.3); mehu.lisaaVarastoon(1.0); //System.out.println(mehu.historia()); // [1000.0, 988.7, 989.7] mehu.tulostaAnalyysi();
Metodi tulostaAnalyysi kirjoittaa ilmoituksen tyyliin:
Tuote: Juice Historia: [1000.0, 988.7, 989.7] Suurin tuotemäärä: 1000.0 Pienin tuotemäärä: 988.7 Keskiarvo: 992.8
Täydennä analyysin tulostus sellaiseksi, että mukana ovat myös muutoshistorian suurin muutos ja historian varianssi.
Havainnollista kehiteltyä analyysiraporttia pienellä esimerkkiohjelmalla.
Tietojenkäsittelytieteen vanha unelma on ollut luoda ohjelma, joka kääntää tekstiä luonnollisesta kielestä toiseen. Suoraviivainen lähestymistapa ongelmaan on jakaa käännettävä teksti sanoiksi ja etsiä niille vastineet sanakirjasta. Tässä tehtäväsarjassa luodaan ohjelma, joka kääntää tekstiä suomesta englanniksi.
Tee ohjelma, joka erottaa sanat käyttäjän antamasta lauseesta. Käytännössä sanat tunnistaa siitä, että niiden välissä on välilyönti.
Ohjelman tulisi toimia seuraavasti:
Anna lause: Tämä ohjelma on kääntäjä. Tämä ohjelma on kääntäjä.
Vihje: String
-luokan metodista split
lienee tässä tapauksessa hyötyä. Voit esim. googlata ohjeita splitin käyttöön.
Edellisen tehtävän ohjelman tuloksena sanojen osana voi olla suuria kirjaimia ja välimerkkejä (pisteitä, pilkkuja jne.). Nämä saattaisivat häiritä kääntämistä, joten muuta ohjelmaa niin, että se muuttaa kaikki kirjaimet pieniksi ja poistaa välimerkit.
Ohjelman tulisi toimia seuraavasti:
Anna lause: Tämä ohjelma on kääntäjä. tämä ohjelma on kääntäjä
Liitä ohjelmaan mukaan sanakirja viikon 1 tehtävän 3 tyyliin. Lisää sanakirjaan yleisimpiä sanoja, kuten seuraavat:
Muuta edellistä ohjelmaasi niin, että se hakee sanoille käännöksen sanakirjasta ja tulostaa käännökset samalle riville. Päätä sopiva toiminta, kun käännös puuttuu sanakirjasta.
Ohjelman tulisi toimia seuraavasti:
Anna lause: Tämä ohjelma on kääntäjä. Käännös: this program is translator
Huom: kuten jo muutaman kerran on ollut puhetta, ei ole kovin järkevää laittaa kaikkea toiminnallisuutta mainiin. Yritä tehdä ohjelmasi rakenteesta selkeä! Jatkamme tehtävää ensi viikolla ja jos nyt teet hyvää jälkeä, on ensi viikolla helpompi hymyillä.
Lisää ohjelmaan enemmän sanoja ja yritä saada siitä mahdollisimman hyvä kääntäjä. Mitä ongelmia kohtaat ohjelman toteutuksessa?
Ohjelman tulisi toimia seuraavasti:
Anna lause: Ohjelmointi on kivaa! Käännös: programming is fun
Anna lause: Alussa olivat suo, kuokka ja Jussi. Käännös: in the beginning were swamp hoe and john
Maatiloilla on lypsäviä eläimiä, jotka tuottavat maitoa. Maatilat eivät itse käsittele maitoa, vaan se kuljetetaan Maitoautoilla meijereille. Meijerit ovat yleisiä maitotuotteita tuottavia rakennuksia. Jokainen meijeri erikoistuu yhteen tuotetyyppiin, esimerkiksi Juustomeijeri tuottaa Juustoa, Voimeijeri tuottaa voita ja Maitomeijeri tuottaa maitoa.
Rakennetaan maidon elämää kuvaava simulaattori.
Jotta maito pysyisi tuoreena, täytyy se säilöä sille tarkoitettuun säiliöön. Säiliöitä valmistetaan sekä oletustilavuudella 2000 litraa, että asiakkaalle räätälöidyllä tilavuudella. Toteuta luokka Maitosailio jolla on seuraavat konstruktorit ja metodit.
Toteuta Maitosailio-luokalle myös toString()-metodi, jolla kuvaat sen tilaa. Ilmaistessasi säiliön tilaa toString()-metodissa, pyöristä litramäärät ylöspäin käyttäen Math-luokan tarjoamaa ceil()-metodia.
Testaa maitosailiötä seuraavalla ohjelmapätkällä
Maitosailio sailio = new Maitosailio(); sailio.otaSailiosta(100); sailio.lisaaSailioon(25); sailio.otaSailiosta(5); System.out.println(sailio); sailio = new Maitosailio(50); sailio.lisaaSailioon(100); System.out.println(sailio);
Ohjelman tulostuksen tulee olla seuraavankaltainen
20.0/2000.0 50.0/50.0
Huomaa että kutsuttaessa System-luokan out-olioon liittyvää println()-metodia, joka saa parametrikseen Object-tyyppisen muuttujan, tulostus käyttää Maitosailio-luokassa korvattua toString()-metodia! Tässä on kyse polymorfismista, eli ajonaikaisesta käytettävien metodien päättelystä.
Saadaksemme maitoa tarvitsemme myös lehmiä. Lehmällä on nimi ja
utareet. Lehman utareiden
tilavuus on satunnainen luku väliltä 15 ja 40 -- luokkaa Random voi käyttäää satunnaislukujen arpomiseen, esimerkiksi int luku = 15 + new Random().nextInt(26);
. Lehma toteuttaa
myös rajapinnat
Lypsava, joka kuvaa lypsämiskäyttäytymistä, ja Eleleva, joka kuvaa
elelemiskäyttäytymistä.
public interface Lypsava { public double lypsa(); } public interface Eleleva { public void eleleTunti(); }
Lehmää lypsettäessä sen koko maitovarasto tyhjennetään jatkokäsittelyä varten. Lehmän elellessä sen maitovarasto täyttyy hiljalleen. Suomessa maidontuotannossa käytetyt lehmät tuottavat keskimäärin noin 25-30 litraa maitoa päivässä. Simuloidaan tätä tuotantoa tuottamalla noin 0.7 - 2 litraa tunnissa.
Jos lehmälle ei anneta nimeä, valitse sille nimi satunnaisesti seuraavasta listasta.
private static String[] NIMIA = new String[]{ "Anu", "Arpa", "Essi", "Heluna", "Hely", "Hento", "Hilke", "Hilsu", "Hymy", "Ihq", "Ilme", "Ilo", "Jaana", "Jami", "Jatta", "Laku", "Liekki", "Mainikki", "Mella", "Mimmi", "Naatti", "Nina", "Nyytti", "Papu", "Pullukka", "Pulu", "Rima", "Soma", "Sylkki", "Valpu", "Virpi"};
Toteuta luokka Lehma ja testaa sen toimintaa seuraavan ohjelmapätkän avulla. Toteuta luokalle myos metodi toString(), joka palauttaa sitä kuvaavan merkkijonon.
Lehma lehma = new Lehma(); System.out.println(lehma); Eleleva elelevaLehma = lehma; elelevaLehma.eleleTunti(); elelevaLehma.eleleTunti(); elelevaLehma.eleleTunti(); elelevaLehma.eleleTunti(); System.out.println(lehma); Lypsava lypsavaLehma = lehma; lypsavaLehma.lypsa(); System.out.println(lehma); System.out.println(""); lehma = new Lehma("Ammu"); System.out.println(lehma); lehma.eleleTunti(); lehma.eleleTunti(); System.out.println(lehma); lehma.lypsa(); System.out.println(lehma);
Ohjelman tulostus on erimerkiksi seuraavanlainen.
Liekki 0.0/23.0 Liekki 16.0/23.0 Liekki 0.0/23.0 Ammu 0.0/53.0 Ammu 9.0/53.0 Ammu 0.0/53.0
Nykyaikaisilla maatiloilla lypsyrobotit hoitavat lypsämisen. Jotta lypsyrobotti voi lypsää lypsävää otusta, tulee lypsyrobotin olla kiinnitetty maitosäiliöön.
Toteuta luokka Lypsyrobotti ja testaa sitä seuraavan ohjelmapätkän avulla. Varmista että lypsyrobotti voi lypsää kaikkia Lypsava-rajapinnan toteuttavia olioita!
Lypsyrobotti lypsyrobotti = new Lypsyrobotti(); Lehma lehma = new Lehma(); lypsyrobotti.lypsa(lehma); System.out.println(""); Maitosailio sailio = new Maitosailio(); lypsyrobotti.setMaitosailio(sailio); System.out.println("Säiliö: " + sailio); for(int i = 0; i < 2; i++) { System.out.println(lehma); System.out.println("Elellään.."); for(int j = 0; j < 5; j++) { lehma.eleleTunti(); } System.out.println(lehma); System.out.println("Lypsetään..."); lypsyrobotti.lypsa(lehma); System.out.println("Säiliö: " + sailio); System.out.println(""); }
Ohjelman tulostus on esimerkiksi seuraavanlainen.
Ei kiinnitetty maitosäiliöön, ei voida lypsää. Säiliö: 0.0/2000.0 Mella 0.0/23.0 Elellään.. Mella 17.0/23.0 Lypsetään... Säiliö: 17.0/2000.0 Mella 0.0/23.0 Elellään.. Mella 13.0/23.0 Lypsetään... Säiliö: 29.0/2000.0
Lehmät hoidetaan (eli tässä tapauksessa lypsetään) navetassa. Alkukantaisissa navetoissa on maitosäiliö ja tilaa yhdelle lypsyrobotille. Huomaa että lypsyrobottia asennettaessa se kytketään juuri kyseisen navetan maitosäiliöön. Jos navetassa ei ole lypsyrobottia, ei siellä voida myöskään hoitaa lehmiä. Toteuta luokka Navetta jolla on seuraavat konstruktorit ja metodit.
Lisää navettaan myös aksessori maitosailiölle. Metodi hoida
lypsää parametrina annetun lehmän tai lehmäkokoelman Lypsyrobotin avulla. Toteuta navetalle myös toString()-metodi, joka palautaa sen sisältämän maitosäiliön tilan.
Collection on Javan oma rajapinta joka kuvaa kokoelmien käyttäytymistä. Esimerkiksi luokat ArrayList ja LinkedList toteuttavat rajapinnan Collection. Jokaista Collection-rajapinnan toteuttavaa ilmentymää voi myös iteroida for-each-tyyppisesti.
Testaa luokkaa Navetta seuraavan ohjelmapätkän avulla. Älä hermoile luokasta LinkedList, se toimii ulkoapäin katsottuna kuin ArrayList, mutta sen kapseloima toteutus on hieman erilainen. Tästä lisää tietorakenteet kurssilla!
Navetta navetta = new Navetta(new Maitosailio()); System.out.println("Navetta: " + navetta); Lypsyrobotti robo = new Lypsyrobotti(); navetta.asennaLypsyrobotti(robo); Lehma ammu = new Lehma(); ammu.eleleTunti(); ammu.eleleTunti(); navetta.hoida(ammu); System.out.println("Navetta: " + navetta); LinkedList<Lehma> lehmaLista = new LinkedList(); lehmaLista.add(ammu); lehmaLista.add(new Lehma()); for(Lehma lehma: lehmaLista) { lehma.eleleTunti(); lehma.eleleTunti(); } navetta.hoida(lehmaLista); System.out.println("Navetta: " + navetta);
Tulostuksen tulee olla esimerkiksi seuraavanlainen:
Navetta: 0.0/2000.0 Navetta: 5.0/2000.0 Navetta: 17.0/2000.0
Maatilalla on omistaja ja siihen kuuluu navetta sekä joukko lehmiä. Maatila toteuttaa myös aiemmin nähdyn rajapinnan Eleleva, jonka metodia eleleTunti()-kutsumalla kaikki maatilaan liittyvät lehmät elelevät tunnin. Toteuta luokka maatila siten, että se toimii seuraavien esimerkkiohjelmien mukaisesti.
Maatila maatila = new Maatila("Esko", new Navetta(new Maitosailio())); System.out.println(maatila);
Odotettu tulostus:
Maatilan omistaja: Esko Navetan maitosäiliö: 0.0/2000.0 Ei lehmiä.
Maatila maatila = new Maatila("Esko", new Navetta(new Maitosailio())); maatila.lisaaLehma(new Lehma()); maatila.lisaaLehma(new Lehma()); maatila.lisaaLehma(new Lehma()); System.out.println(maatila);
Odotettu tulostus:
Maatilan omistaja: Esko Navetan maitosäiliö: 0.0/2000.0 Lehmät: Naatti 0.0/19.0 Hilke 0.0/30.0 Sylkki 0.0/29.0
Maatila maatila = new Maatila("Esko", new Navetta(new Maitosailio())); maatila.lisaaLehma(new Lehma()); maatila.lisaaLehma(new Lehma()); maatila.lisaaLehma(new Lehma()); maatila.eleleTunti(); maatila.eleleTunti();
Odotettu tulostus:
Maatilan omistaja: Esko Navetan maitosäiliö: 0.0/2000.0 Lehmät: Heluna 6.0/17.0 Rima 8.0/42.0 Ilo 8.0/25.0
Maatila maatila = new Maatila("Esko", new Navetta(new Maitosailio())); Lypsyrobotti robo = new Lypsyrobotti(); maatila.asennaNavettaanLypsyrobotti(robo); maatila.lisaaLehma(new Lehma()); maatila.lisaaLehma(new Lehma()); maatila.lisaaLehma(new Lehma()); maatila.eleleTunti(); maatila.eleleTunti(); maatila.hoidaLehmat(); System.out.println(maatila);
Odotettu tulostus:
Maatilan omistaja: Esko Navetan maitosäiliö: 18.0/2000.0 Lehmät: Hilke 0.0/30.0 Sylkki 0.0/45.0 Hento 0.0/54.0
Luodaan ohjelma jolla voidaan simuloida maatilan toimintaa. Simulaattori kysyy ensiksi maatilan omistajan nimeä, jonka jälkeen kysytään maatilalla olevien nautojen määrä. Kun nämä ovat tiedossa luodaan maatila ja siihen liittyvät lehmät (muista asettaa maatilalle myös navetta, ja navetalle lypsyrobotti!). Kun maatila on luotu, käyttäjälle annetaan 3 vaihtoehtoa: "Elele tunti", "Hoida lehmät" ja "Lopeta" -- jokainen toiminto laukaistaan numerolla. Pyydetty numero kannattaa lukea Scannerin ja Integer-luokan yhteistyöllä seuraavasti:
int luku = Integer.parseInt(scanner.nextLine());
Toteuta maatilasimulaattori, seuraavassa esimerkkitulostus:
Anna maatilan omistajan nimi: Esko Montako nautaa? 2 Maatilan omistaja: Esko Navetan maitosäiliö: 0.0/2000.0 Lehmät: Mella 0.0/54.0 Nina 0.0/21.0 Komennot: 1 - Elele tunti 2 - Hoida lehmat muut - Lopeta ? 1 Maatilan omistaja: Esko Navetan maitosäiliö: 0.0/2000.0 Lehmät: Mella 4.0/54.0 Nina 5.0/21.0 Komennot: 1 - Elele tunti 2 - Hoida lehmat muut - Lopeta ? 1 Maatilan omistaja: Esko Navetan maitosäiliö: 0.0/2000.0 Lehmät: Mella 7.0/54.0 Nina 8.0/21.0 Komennot: 1 - Elele tunti 2 - Hoida lehmat muut - Lopeta ? 2 Maatilan omistaja: Esko Navetan maitosäiliö: 15.0/2000.0 Lehmät: Mella 0.0/54.0 Nina 0.0/21.0 Komennot: 1 - Elele tunti 2 - Hoida lehmat muut - Lopeta ? x Kiitos!
Tikkupelin alussa pöydällä on kasa tikkuja. Pelissä on kaksi pelaajaa, jotka ottavat pöydältä vuorotellen yhden, kaksi tai kolme tikkua. Pelin häviää se, joka joutuu ottamaan viimeisen tikun.
Ohjelmoi tikkupeli kahdelle pelaajalle. Pelin alussa kysytään tikkujen määrä pöydällä, minkä jälkeen pelaajat poistavat vuorotellen tikkuja. Ohjelman tulee valvoa, että pelaajat poistavat aina yhden, kaksi tai kolme tikkua. Lopuksi ohjelma ilmoittaa pelin voittajan.
Ohjelman tulisi toimia seuraavasti:
Tervetuloa tikkupeliin! Montako tikkua on pöydällä? 10 Pöydällä on 10 tikkua. Kuinka monta poistat, pelaaja 1? 2 Pöydällä on 8 tikkua. Kuinka monta poistat, pelaaja 2? 1 Pöydällä on 7 tikkua. Kuinka monta poistat, pelaaja 1? 4 Virheellinen määrä! Kuinka monta poistat, pelaaja 1? 3 Pöydällä on 4 tikkua. Kuinka monta poistat, pelaaja 2? 3 Pöydällä on 1 tikkua. Kuinka monta poistat, pelaaja 1? 0 Virheellinen määrä! Kuinka monta poistat, pelaaja 1? 2 Virheellinen määrä! Kuinka monta poistat, pelaaja 1? 1 Voittaja on pelaaja 2!
Tee pelistä uusi versio, jossa toinen pelaaja on tekoäly. Tekoälyn strategiaksi kelpaa tässä vaiheessa, että se poistaa aina yhden tikun.
Ohjelman tulisi toimia seuraavasti:
Tervetuloa tikkupeliin! Montako tikkua on pöydällä? 10 Pöydällä on 10 tikkua. Kuinka monta poistat? 2 Pöydällä on 8 tikkua. Tekoäly poistaa 1 tikkua. Pöydällä on 7 tikkua. Kuinka monta poistat? 3 Pöydällä on 4 tikkua. Tekoäly poistaa 1 tikkua. Pöydällä on 3 tikkua. Kuinka monta poistat? 2 Pöydällä on 1 tikkua. Tekoäly poistaa 1 tikkua. Voittaja olet sinä!
Ilmaukset "tekoäly poistaa 1 tikkua" ja "pöydällä on 1 tikkua" eivät muuten ole kovin tyylikkäitä. Voit halutessasi korjata asian.
Tikkupeliin on olemassa todella yksinkertainen voittostrategia eli varma keino voittaa peli. Tekoälyn riittää varmistaa, että aina kun pelaaja on vuorossa, pöydällä olevien tikkujen määrän jakojäännös 4:llä on 1.
Esimerkiksi jos pöydällä on 7 tikkua, tekoälyn kannattaa poistaa 2 tikkua, koska silloin jäljelle jää 5 tikkua ja 5:n jakojäännös 4:llä on 1. Vastaavasti jos pöydällä on 56 tikkua, tekoälyn kannattaa poistaa 3 tikkua, koska silloin jäljelle jää 53 tikkua ja 53:n jakojäännös 4:llä on 1.
Jos pöydällä olevan tikkujen määrän jakojäännös 4:llä on 1, tekoäly on heikossa asemassa eikä sen auta muuta kuin poistaa jokin määrä tikkuja ja toivoa, että pelaaja tekee virheen.
Muuta tekoälyä niin, että se noudattaa tätä strategiaa.
Ohjelman tulisi toimia seuraavasti:
Tervetuloa tikkupeliin! Montako tikkua on pöydällä? 10 Pöydällä on 10 tikkua. Kuinka monta poistat? 2 Pöydällä on 8 tikkua. Tekoäly poistaa 3 tikkua. Pöydällä on 5 tikkua. Kuinka monta poistat? 3 Pöydällä on 2 tikkua. Tekoäly poistaa 1 tikkua. Pöydällä on 1 tikkua. Kuinka monta poistat? 1 Voittaja on tekoäly!
Perustele pätevästi, miksi edellisen tehtävän strategia on toimiva. Miksi tekoälyn kannattaa pyrkiä siihen, että tikkujen määrän jakojäännös 4:llä on 1?
Entä jos tikkupelissä pitäisi poistaa aina yksi, kolme tai neljä tikkua? Muuta pelisi toiminta tällaiseksi ja suunnittele toimiva tekoäly.
Tee ohjelma, joka kysyy käyttäjältä kokonaisluvun ja tulostaa sen suomeksi. Lukuväli 0–1000000 riittää hyvin.
Ohjelman suoritus voi näyttää seuraavalta:
Anna luku: 2713 kaksituhattaseitsemänsataakolmetoista