Tehtävät

Kertaustehtäviä osiin 8-14 liittyen

Tällä sivulla on kertaustehtäviä materiaalin osiin 8-14 liittyen. Kertaustehtävät saa ladattua TMC:stä kun osan 14 tehtävistä on tehty 75%. Tehtävät eivät missään nimessä kata kaikkea osien 8-14 sisällöstä, vaan ne toimivat lisäkertauksena kurssin aihepiiriin.

Kertaustehtävissä ei ole automaattisia testejä mukana, eli palauta niitä sitä mukaa kun saat tehtävän toimimaan toivotusti. Mieti aina minkälaisilla syötteillä tehtävän toimintaa kannattaa testata.

Kertaustehtävät eivät ole "pakollisia" -- ne toimivat ensisijaisesti kertaustehtävinä koetta varten. Kertaustehtävillä voi paikata tekemättä jääneitä ohjelmoinnin perusteiden tehtäviä. Kukin tämän sivun kertaustehtävä lasketaan kahdeksi pisteeksi; mikäli sinulta on jäänyt joltain viikolta esimerkiksi kaksi pistettä vajaaksi 75%:sta, saat paikattua tuon tekemällä yhden tällä sivulla olevan kertaustehtävän.

Joissain tehtävissä pyydetään useampaa erilaista ratkaisua. Pyri näissä ratkaisemaan tehtävä esimerkiksi sekä virran avulla että normaalin toistolauseen avulla. Voit myös kokeilla esimerkiksi hajautustaulun käyttöä toisessa ratkaisussa ja normaalin listan käyttöä toisessa ym.

Painoindeksi on mitta-arvo, jonka avulla voidaan arvioida ihmisen painon ja pituuden suhdetta. Painoindeksi lasketaan kaavalla:

Painoindeksi = paino / (pituus * pituus)

Painoindeksiä käytetään muunmuassa ali- ja ylipainon tunnistamisessa. Jos henkilön painoindeksi on alle 18.5 luokitellaan hänet alipainoiseksi ("alipaino"). Jos painoindeksi on vähintään 18.5 mutta alle 25, on luokittelu "normaali". Jos taas painoindeksi on vähintään 25 mutta alle 30, on luokittelu "ylipainoinen". Jos taas painoindeksi on vähintään 30, on luokittelu "merkittävästi ylipainoinen".

Luokissa Raportinluoja1 ja Raportinluoja2 on metodi public PainoindeksiRaportti painoindeksiRaportti(List<Henkilo> henkilotiedot), joka saa parametrina listan henkilöitä ja palauttaa painoindeksiraportin -- kannattaa tutustua luokkiin Painoindeksiraportti ja Henkilo.

Luo luokkiin Raportinluoja1 ja Raportinluoja2 erilaiset toteutukset metodille painoindeksiRaportti painoindeksiraporttien luomiseen.

Tuotettavan painoindeksiraportin tulee sisältää lista nimistä (huom! ei henkilöistä) siten, että henkilöt ovat kategorisoitu heihin sopiviin painoindeksiluokkiin.

Data-analytiikassa mittausten tasoittamisella tarkoitetaan liiallisen kohinan tai muiden häiriöiden poistamiseen datasta, jonka jälkeen oleellisten hahmojen tunnistamista datasta tulee mahdollisesti helpommaksi. Eräs suoraviivainen tekniikka mittausten tasoitukseen on muuttaa jokainen mittausarvo sen, sitä edeltävän mittausarvon ja sitä seuraavan mittausarvon mittausten keskiarvoksi. Jos oletamme, että poikkeukselliset arvot ovat häiriö mittadatassa, tämä keskiarvomenetelmä tasaa arvot potentiaalisesti luotettavimmiksi arvoiksi.

Tutkitaan esimerkiksi seuraavia sykemittauksia, jotka on kerätty henkilötietodatasta.

  95 102 98 88 105
  

Jos ylläolevan mittausdatan tasaa keskiarvomenetelmällä, on tasauksen tuottama data seuraavanlainen:

  95 98.33 96 97 105
  

Tässä:

  • Arvo 102 muutettiin arvoon 98.33: (95 + 102 + 98) / 3
  • Arvo 98 muutettiin arvoon 96: (102 + 98 + 88) / 3
  • Arvo 88 muutettiin arvoon 97: (98 + 88 + 105) / 3

Luokissa MittaustenTasoittaja1 ja MittaustenTasoittaja2 on metodi public List<Double> tasoita(List<Henkilo> henkilotiedot), joka saa parametrina listan henkilö-olioita (henkilöiden nimillä ei ole väliä, oleellista on sykemittausdata -- muuttuja syke) ja palauttaa listan tasattuja sykemittauksia -- luokka Henkilo on tässä sama kuin edellisessä tehtävässä.

Luo luokkiin MittaustenTasoittaja1 ja MittaustenTasoittaja2 erilaiset toteutukset metodille tasoita listana annettujen henkilo-olioihin tallennettujen sykemittausten tasoittamiseen. Toteutusten tulee siis käsitellä lista henkilötietueita, joista jokaisessa on sykemittaus, ja palauttaa lista double-arvoja, jotka ovat tasoitettuja sykemittauksia.

Luokissa YleisimmatSanat1 ja YleisimmatSanat2 on metodi public List<String> yleisetSanat(List<String> sanat), joka saa parametrina listan merkkijonoja ja palauttaa listan merkkijonoja.

Luo luokkiin YleisimmatSanat1 ja YleisimmatSanat2 erilaiset toteutukset kolmen yleisimmän merkkijonon tunnistamiseen. Yleisimmät merkkijonot tulee tunnistaa metodille yleisetSanat syötteeksi annetusta listasta, ja metodin tulee palauttaa yleisimmät merkkijonot listassa. Palauttava lista tulee olla järjestettynä siten, että listan ensimmäisenä alkiona on yleisin merkkijono, toisena alkiona on toiseksi yleisin merkkijono, ja kolmantena alkiona on kolmanneksi yleisin merkkijono.

Jos merkkijonot ovat yhtä yleisiä, aseta lyhin sana (vähiten merkkejä) ennen pidempää sanaa. Voit olettaa, että syötteen kolme yleisintä sanaa ovat eri pituisia. Voit lisäksi olettaa, että syötteessä on vähintään kolme eri sanaa.

Geologit haluavat tarkastella paikallisen vuoren mahdollista maanjäristystoimintaa. He ovat asentaneet mittarin seismisen toiminnan (maan tärinän) mittaamiseen. Mittari lukee seismistä toimintaa tietyin aikavälein ja lähettää mitattua dataa mittausarvo kerrallaan tutkimuslaboratorion tietokoneelle.

Mittari lisää lisäksi mittausdataan päivämäärätietoja näyttämään seismisen toiminnan mittauspäivää. Mittarin lähettämä data on seuraavassa muodossa:

  20151004 200 150 175 20151005 0.002 0.03 20151007 ...
  

Kahdeksanlukuiset arvot ovat päivämääriä (vuosi-kuukausi-päivä -muodossa) ja numerot nollan ja viidensadan välillä ovat värähtelyjen taajuuksia (hertzeinä). Ylläoleva esimerkki näyttää mittaukset 200, 150, ja 175 lokakuun neljäntenä päivänä vuonna 2015 ja mittaukset 0.002 ja 0.03 lokakuun viidentenä päivänä vuonna 2015. Lokakuun kuudennelta päivältä ei ole lainkaan mittausdataa (välillä verkkoyhteydessä on ongelmia, jolloin mittausdataa saattaa kadota).

Oleta, että mittausdata on järjestetty päivämäärien mukaan (myöhempi päivämäärä ei ikinä ilmesty datassa ennen aiempaa päivämäärää) ja että kaikki data on samalta vuodelta. Voit myös olettaa, että jokaiselta datassa olevalta päivältä on vähintään yksi mittausarvo.

Luokissa MittausRaportoija1 ja MittausRaportoija2 on tyhjä metodi List<SuurinTaajuusRaportti> paivittaisetMaksimit(List<Double> mittausData, int kuukausi), joka saa parametrina listan mittausdataa sekä kuukauden (oleta, että yksi (01) vastaa tammikuuta ja kaksitoista (12) vastaa joulukuuta). Metodin tulee tuottaa lista raportteja, joista jokainen sisältää suurimman mittaustuloksen kuukauden yksittäiselle päivälle, josta löytyy mittausdataa.

Suunnittele ja toteuta kaksi erilaista toteutusta metodille paivittaisetMaksimit ja toteuta ne luokkiin MittausRaportoija1 ja MittausRaportoija2. Metodin tulee siis käsitellä lista Double-muotoisia syötteitä, joista löytyy sekä päivämääriä että mittausarvoja. Metodin tulee käsitellä vain parametrina annettuun kuukauteen liittyviä arvoja, ja syötteiden perusteella tulee tunnistaa jokaiselle parametrina annetulle kuukauden päivälle suurin päiväkohtainen arvo. Suurimmat päiväkohtaiset arvot asetetaan palautettavaan listaan SuurinTaajuusRaportti-muotoisina olioina, ja metodi palauttaa lopulta listan tulevaa käsittelyä varten.

Kun olet tehnyt neljä edellistä tehtävää (tai ainakin yrittänyt tehdä kaikkia neljää tehtävää), vastaa osoitteessa http://goo.gl/forms/VZ2yyRNUVB olevaan kyselyyn. Tämän jälkeen voit jatkaa seuraavien kertaustehtävien parissa.

Tässä tehtävässä tehdään joukkueiden ja joukkueen pelaajien ylläpitoon tarkoitettuun ohjelmistoon tarvittavat ydinluokat.

Joukkue

Tee luokka Joukkue, johon tallennetaan joukkueen nimi (String). Tee luokkaan seuraavat metodit:

  • konstruktori, jolle annetaan joukkueen nimi
  • getNimi, joka palauttaa joukkueen nimen

Seuraava pääohjelma demonstroi luokan toimintaa:

Joukkue tapiiri = new Joukkue("FC Tapiiri");
System.out.println("Joukkue: " + tapiiri.haeNimi());

Ohjelman tulostus on seuraava:

Joukkue: FC Tapiiri

Pelaaja

Luo luokka Pelaaja, johon tallennetaan pelaajan nimi ja tehtyjen maalien määrä. Tee luokkaan kaksi konstruktoria: yksi jolle annetaan vain pelaajan nimi, toinen jolle annetaan sekä pelaajan nimi että pelaajan tekemien maalien määrä. Lisää pelaajalle myös metodit:

  • getNimi, joka palauttaa pelaajan nimen
  • getMaalit, joka palauttaa tehtyjen maalien määrän
  • toString, joka palauttaa pelaajan merkkijonoesityksen
Joukkue tapiiri = new Joukkue("FC Tapiiri");
System.out.println("Joukkue: " + tapiiri.getNimi());

Pelaaja matti = new Pelaaja("Matti");
System.out.println("Pelaaja: " + matti);

Pelaaja pekka = new Pelaaja("Pekka", 39);
System.out.println("Pelaaja: " + pekka);
Joukkue: FC Tapiiri
Pelaaja: Matti, maaleja 0
Pelaaja: Pekka, maaleja 39

Pelaajat joukkueisiin

Lisää luokkaan Joukkue seuraavat metodit:

  • lisaaPelaaja, joka lisää pelaajan joukkueeseen
  • tulostaPelaajat, joka tulostaa joukkueessa olevat pelaajat

Tallenna joukkueessa olevat pelaajat Joukkue-luokan sisäiseen ArrayList-listaan.

Seuraava pääohjelma testaa luokan toimintaa:

Joukkue tapiiri = new Joukkue("FC Tapiiri");

Pelaaja matti = new Pelaaja("Matti");
Pelaaja pekka = new Pelaaja("Pekka", 39);

tapiiri.lisaaPelaaja(matti);
tapiiri.lisaaPelaaja(pekka);
tapiiri.lisaaPelaaja(new Pelaaja("Mikael", 1)); //vaikutus on sama kuin edellisillä

tapiiri.tulostaPelaajat();

Ohjelman tulostuksen tulisi olla seuraava:

Matti, maaleja 0
Pekka, maaleja 39
Mikael, maaleja 1

Joukkueen maksimikoko ja nykyinen koko

Lisää luokkaan Joukkue seuraavat metodit:

  • setMaksimikoko(int maksimikoko), joka asettaa joukkueen maksimikoon (eli maksimimäärän pelaajia)
  • getPelaajienLukumaara, joka palauttaa pelaajien määrän (int)

Joukkueen suurin sallittu pelaajamäärä on oletusarvoisesti 16 (lisää tämä luokan oliomuuttujaksi ja alusta muuttujan arvo konstruktorissa). Metodin setMaksimikoko avulla tätä rajaa voi muuttaa. Muuta edellisessä osassa tehtyä metodia lisaaPelaaja niin, että se ei lisää pelaajaa joukkueeseen, jos sallittu pelaajamäärä ylittyisi.

Seuraava pääohjelma testaa luokan toimintaa:

Joukkue tapiiri = new Joukkue("FC Tapiiri");
tapiiri.setMaksimikoko(1);

Pelaaja matti = new Pelaaja("Matti");
Pelaaja pekka = new Pelaaja("Pekka", 39);
tapiiri.lisaaPelaaja(matti);
tapiiri.lisaaPelaaja(pekka);
tapiiri.lisaaPelaaja(new Pelaaja("Mikael", 1)); //vaikutus on sama kuin edellisillä

System.out.println("Pelaajia yhteensä: " + tapiiri.getPelaajienLukumaara());
Pelaajia yhteensä: 1

Joukkueen maalit

Lisää luokkaan Joukkue metodi:

  • yhteismaalit, joka palauttaa joukkueen pelaajien tekemien maalien yhteismäärän.

Seuraava pääohjelma testaa luokan toimintaa:

Joukkue tapiiri = new Joukkue("FC Tapiiri");

Pelaaja matti = new Pelaaja("Matti");
Pelaaja pekka = new Pelaaja("Pekka", 39);
tapiiri.lisaaPelaaja(matti);
tapiiri.lisaaPelaaja(pekka);
tapiiri.lisaaPelaaja(new Pelaaja("Mikael", 1)); //vaikutus on sama kuin edellisillä

System.out.println("Maaleja yhteensä: " + tapiiri.yhteismaalit());
Maaleja yhteensä: 40

Tehtäväpohjan mukana tulee luokat Tavara ja Laatikko. Luokka Laatikko on abstrakti luokka, jossa useamman tavaran lisääminen on toteutettu siten, että kutsutaan aina lisaa-metodia. Yhden tavaran lisäämiseen tarkoitettu metodi lisaa on abstrakti, joten jokaisen Laatikko-luokan perivän laatikon tulee toteuttaa se. Tehtävänäsi on muokata luokkaa Tavara ja toteuttaa muutamia erilaisia laatikoita luokan Laatikko pohjalta.

Lisää kaikki uudet luokat pakkaukseen laatikot.

package laatikot;

import java.util.Collection;

public abstract class Laatikko {

    public abstract void lisaa(Tavara tavara);

    public void lisaa(Collection<Tavara> tavarat) {
        for (Tavara t: tavarat) {
            lisaa(t);
        }
    }

    public abstract boolean onkoLaatikossa(Tavara tavara);
}

Tavaran muokkaus

Lisää Tavara-luokan konstruktoriin tarkistus, jossa tarkistetaan että tavaran paino ei ole koskaan negatiivinen (paino 0 hyväksytään). Jos paino on negatiivinen, tulee konstruktorin heittää IllegalArgumentException-poikkeus. Toteuta Tavara-luokalle myös metodit equals ja hashCode, joiden avulla pääset hyödyntämään erilaisten listojen ja kokoelmien contains-metodia. Toteuta metodit siten, että Tavara-luokan oliomuuttujan paino arvolla ei ole väliä. Voit hyvin hyödyntää NetBeansin tarjoamaa toiminnallisuutta equalsin ja hashCoden toteuttamiseen.

Maksimipainollinen laatikko

Toteuta pakkaukseen laatikot luokka MaksimipainollinenLaatikko, joka perii luokan Laatikko. Maksimipainollisella laatikolla on konstruktori public MaksimipainollinenLaatikko(int maksimipaino), joka määrittelee laatikon maksimipainon. Maksimipainolliseen laatikkoon voi lisätä tavaraa jos ja vain jos tavaran lisääminen ei ylitä laatikon maksimipainoa.

MaksimipainollinenLaatikko kahviLaatikko = new MaksimipainollinenLaatikko(10);
kahviLaatikko.lisaa(new Tavara("Saludo", 5));
kahviLaatikko.lisaa(new Tavara("Pirkka", 5));
kahviLaatikko.lisaa(new Tavara("Kopi Luwak", 5));

System.out.println(kahviLaatikko.onkoLaatikossa(new Tavara("Saludo")));
System.out.println(kahviLaatikko.onkoLaatikossa(new Tavara("Pirkka")));
System.out.println(kahviLaatikko.onkoLaatikossa(new Tavara("Kopi Luwak")));
true
true
false

Yhden tavaran laatikko ja Hukkaava laatikko

Toteuta seuraavaksi pakkaukseen laatikot luokka YhdenTavaranLaatikko, joka perii luokan Laatikko. Yhden tavaran laatikolla on konstruktori public YhdenTavaranLaatikko(), ja siihen mahtuu tasan yksi tavara. Jos tavara on jo laatikossa sitä ei tule vaihtaa. Laatikkoon lisättävän tavaran painolla ei ole väliä.

YhdenTavaranLaatikko laatikko = new YhdenTavaranLaatikko();
laatikko.lisaa(new Tavara("Saludo", 5));
laatikko.lisaa(new Tavara("Pirkka", 5));

System.out.println(laatikko.onkoLaatikossa(new Tavara("Saludo")));
System.out.println(laatikko.onkoLaatikossa(new Tavara("Pirkka")));
true
false

Toteuta seuraavaksi pakkaukseen laatikot luokka HukkaavaLaatikko, joka perii luokan Laatikko. Hukkaavalla laatikolla on konstruktori public HukkaavaLaatikko(). Hukkaavaan laatikkoon voi lisätä kaikki tavarat, mutta tavaroita ei löydy niitä etsittäessä. Laatikkoon lisäämisen tulee siis aina onnistua, mutta metodin onkoLaatikossa kutsumisen tulee aina palauttaa false.

HukkaavaLaatikko laatikko = new HukkaavaLaatikko();
laatikko.lisaa(new Tavara("Saludo", 5));
laatikko.lisaa(new Tavara("Pirkka", 5));

System.out.println(laatikko.onkoLaatikossa(new Tavara("Saludo")));
System.out.println(laatikko.onkoLaatikossa(new Tavara("Pirkka")));
false
false

Tässä tehtävässä demonstroit perinnän ja rajapintojen käyttöä. Toteuta kaikki luokat ja rajapinnat pakkaukseen perintaa.

Eläin

Toteuta ensin abstrakti luokka Elain. Luokalla Elain on konstruktori, jolle annetaan parametrina eläimen nimi. Luokalla Elain on lisäksi parametrittomat metodit syo ja nuku, jotka eivät palauta arvoa (void), sekä parametriton metodi getNimi, joka palauttaa eläimen nimen.

Metodin nuku tulee tulostaa "(nimi) nukkuu" ja metodin syo tulee tulostaa "(nimi) syo". Tässä (nimi) on eläimelle annettu nimi.

Koira

Toteuta luokan Elain perivä luokka Koira. Luokalla Koira tulee olla parametrillinen konstruktori, jolla luotavalle koiraoliolle voi antaa nimen. Tämän lisäksi koiralla tulee olla parametriton konstruktori, jolla koiran nimeksi tulee "Koira" sekä parametriton metodi hauku, joka ei palauta arvoa (void). Koiralla tulee olla myös metodit syo ja nuku kuten eläimillä yleensä ottaen.

Alla on esimerkki luokan Koira odotetusta toiminnasta:

Koira koira = new Koira();
koira.hauku();
koira.syo();
    
Koira vuffe = new Koira("Vuffe");
vuffe.hauku();
Koira haukkuu
Koira syo
Vuffe haukkuu

Kissa

Toteuta seuraavaksi luokka Kissa, joka perii luokan Elain. Luokalla Kissa tulee olla parametrillinen konstruktori, jolla luotavalle kissaoliolle voi antaa nimen. Tämän lisäksi kissalla tulee olla parametriton konstruktori, jolla kissan nimeksi tulee "Kissa" sekä parametriton metodi mourua, joka ei palauta arvoa (void). Kissalla tulee olla myös metodit syo ja nuku kuten ensimmäisessä osassa.

Alla on esimerkki luokan Kissa odotetusta toiminnasta:

Kissa kissa = new Kissa();
kissa.mourua();
kissa.syo();
    
Kissa karvinen = new Kissa("Karvinen");
karvinen.mourua();
Kissa mouruaa
Kissa syo
Karvinen mouruaa

Ääntelevä

Luo lopulta rajapinta Aanteleva, joka maarittelee parametrittoman metodin aantele, joka ei palauta arvoa (void). Toteuta rajapinta luokissa Koira että Kissa. Rajapinnan tulee hyödyntää aiemmin määriteltyjä hauku ja mourua -metodeja.

Alla on esimerkki odotetusta toiminnasta:

Aanteleva koira = new Koira();
koira.aantele();
    
Aanteleva kissa = new Kissa("Karvinen");
kissa.aantele();
Kissa k = (Kissa) kissa;
k.mourua();
Koira haukkuu
Karvinen mouruaa
Karvinen mouruaa    

Tee ohjelma, joka lukee käyttäjältä kirjoja ja niiden minimikohdeikiä. Minimikohdeiällä tarkoitetaan pienintä ikää vuosina, jolle kyseistä kirjaa suositellaan.

Ohjelma kysyy uusia kirjoja kunnes käyttäjä syöttää tyhjän merkkijonon kirjan nimen kohdalla (eli painaa rivinvaihtoa). Täämän jälkeen ohjelma tulostaa syötettyjen kirjojen lukumäärän sekä kirjat.

Kirjojen lukeminen ja tulostaminen

Toteuta ensin kirjojen lukeminen ja niiden listaaminen. Tässä vaiheessa kirjojen järjestyksellä ei ole vielä väliä.

Syötä kirjan nimi, tyhjä lopettaa: Soiva tuutulaulukirja
Syötä kirjan pienin kohdeikä: 0

Syötä kirjan nimi, tyhjä lopettaa: Kurkkaa kulkuneuvot
Syötä kirjan pienin kohdeikä: 0
    
Syötä kirjan nimi, tyhjä lopettaa: Lunta tupaan
Syötä kirjan pienin kohdeikä: 12
    
Syötä kirjan nimi, tyhjä lopettaa: Litmanen 10
Syötä kirjan pienin kohdeikä: 10
    
Syötä kirjan nimi, tyhjä lopettaa:
    
Yhteensä 4 kirjaa.
    
Kirjat:
Soiva tuutulaulukirja (0 vuotiaille ja vanhemmille)
Kurkkaa kulkuneuvot (0 vuotiaille ja vanhemmille)
Lunta tupaan (12 vuotiaille ja vanhemmille)
Litmanen 10 (10 vuotiaille ja vanhemmille)

Kirjojen järjestäminen kohdeiän perusteella

Täydennä toteuttamaasi ohjelmaa siten, että kirjat järjestetään tulostuksen yhteydessä kohdeiän perusteella. Jos kahdella kirjalla on sama kohdeikä, näiden kahden kirjan keskinäinen järjestys saa olla mielivaltainen.

Syötä kirjan nimi, tyhjä lopettaa: Soiva tuutulaulukirja
Syötä kirjan pienin kohdeikä: 0

Syötä kirjan nimi, tyhjä lopettaa: Kurkkaa kulkuneuvot
Syötä kirjan pienin kohdeikä: 0
    
Syötä kirjan nimi, tyhjä lopettaa: Lunta tupaan
Syötä kirjan pienin kohdeikä: 12
    
Syötä kirjan nimi, tyhjä lopettaa: Litmanen 10
Syötä kirjan pienin kohdeikä: 10
    
Syötä kirjan nimi, tyhjä lopettaa:
    
Yhteensä 4 kirjaa.
    
Kirjat:
Soiva tuutulaulukirja (0 vuotiaille ja vanhemmille)
Kurkkaa kulkuneuvot (0 vuotiaille ja vanhemmille)
Litmanen 10 (10 vuotiaille ja vanhemmille)
Lunta tupaan (12 vuotiaille ja vanhemmille)

Kirjojen järjestäminen kohdeiän ja nimen perusteella

Täydennä edellistä ohjelmaasi siten, että saman kohdeiän kirjat tulostetaan aakkosjärjestyksessä.

Syötä kirjan nimi, tyhjä lopettaa: Soiva tuutulaulukirja
Syötä kirjan pienin kohdeikä: 0

Syötä kirjan nimi, tyhjä lopettaa: Kurkkaa kulkuneuvot
Syötä kirjan pienin kohdeikä: 0
    
Syötä kirjan nimi, tyhjä lopettaa: Lunta tupaan
Syötä kirjan pienin kohdeikä: 12
    
Syötä kirjan nimi, tyhjä lopettaa: Litmanen 10
Syötä kirjan pienin kohdeikä: 10
    
Syötä kirjan nimi, tyhjä lopettaa:
    
Yhteensä 4 kirjaa.
    
Kirjat:
Kurkkaa kulkuneuvot (0 vuotiaille ja vanhemmille)
Soiva tuutulaulukirja (0 vuotiaille ja vanhemmille)
Litmanen 10 (10 vuotiaille ja vanhemmille)
Lunta tupaan (12 vuotiaille ja vanhemmille)

2048 on suosittu peli. Peliä pelataan 4x4 -kokoisessa lukuja sisältävässä ruudukossa, ja siinä on neljä mahdollista siirtoa: (o)ikealle, (a)las, (v)asemmalle ja (y)lös. Jokainen siirto siirtää kaikkia ruudukossa olevia arvoja niin paljon haluttuun suuntaan kuin mahdollista. Jos kahdessa vierekkäisessä ruudussa on sama arvo, yhdistetään ruutujen arvot yhteen. Esimerkiksi:


2 0 2 0
0 0 0 1
0 1 0 0
0 0 0 0
> o

0 0 0 4
0 0 0 1
0 0 0 1
0 1 0 0
  

Aina kun pelaaja tekee siirron, satunnaiseen nolla-arvoiseen kohtaan arvotaan uusi luku. Peli loppuu kun yhdessä ruuduista on luku 2048 tai siirtäminen ei enää onnistu. Alla esimerkki pelin kulusta.

1 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0

> o
0 0 0 1
0 0 0 0
0 0 0 0
0 1 0 0

> o
0 0 0 1
0 0 0 0
0 0 0 1
0 0 0 1

> a
0 0 0 0
0 0 0 0
1 0 0 2
0 0 0 1

> a
1 0 0 0
0 0 0 0
0 0 0 2
1 0 0 1

> v
1 0 0 0
0 0 0 0
2 0 0 0
2 1 0 0

> y
1 1 0 0
4 0 0 0
0 0 0 0
0 1 0 0

> v
2 0 0 0
4 0 0 0
0 0 0 0
1 0 1 0

> v
2 0 0 0
4 1 0 0
0 0 0 0
2 0 0 0

>
  

Tässä tehtävässä rakennat pelin toimintaan tarvittua ydintoiminnallisuutta. Tehtävässä kerrataan myös toistolauseiden ja indeksien käyttöä.

Peliruudukko

Luo pakkaukseen sovellus luokka Peliruudukko. Luokalla tulee olla parametriton konstruktori, joka luo 4x4-kokoisen ruudukon, ja jonka vasemmassa yläkulmassa on arvo 1. Oleta, että kaksiulotteisen taulukon ensimmäinen indeksi kuvaa y-koordinaattia, ja toinen indeksi x-koordinaattia. Oleta lisäksi, että y-koordinaatti kasvaa alaspäin. Vasen yläkulma on siis kohdassa taulukko[0][0] ja vasen alakulma kohdassa taulukko[3][0] -- olettaen, että taulukon koko on 4.

Lisää luokalle myös metodit public int[][] getTaulukko(), joka palauttaa pelin sisäisen tilan, ja public void setTaulukko(int[][] taulukko), jolla voi asettaa pelin sisäisen tilan.

Siirrä oikealle

Tee tämän jälkeen peliruudukolle metodi public void siirraOikealle(), joka siirtää jokaisen rivin palat oikealle. Metodi yhdistää tarvittaessa myös samanarvoiset muuttujat. Alla muutamia esimerkkeja.

1 1 1 1
1 1 0 1
1 1 1 0
1 0 1 1

> o
0 0 0 4
0 0 1 2
0 0 1 2
0 0 1 2
  
1 0 0 1
0 1 0 1
2 2 4 0
0 1 0 0

> o
0 0 0 2
0 0 0 2
0 0 0 8
0 0 0 1
  

Siirrä ylös ja siirrä alas

Tee seuraavaksi peliruudukolle metodit public void siirraYlos(), joka siirtää jokaisen rivin palat ylös, ja public void siirraAlas(), joka siirtää jokaisen rivin palat alas. Metodi yhdistää tarvittaessa myös samanarvoiset muuttujat.

Siirrä vasemmalle ja pelin loppuminen

Tee seuraavaksi peliruudukolle metodi public void siirraVasemmalle(), joka siirtää jokaisen rivin palat vasemmalle. Kun metodi siirraVasemmalle on valmis, toteuta sovellukseen metodi public boolean peliKaynnissa(), joka palauttaa tiedon pelin jatkumisesta.

Peli jatkuu jos (1) pelissä on yksikin ruutu, jossa on arvo 0, tai (2) kaksi pelin vierekkaista (vaaka- tai pystytasossa) ruutua ovat samanarvoiset.

Tekstikayttoliittyma ja uuden luvun arpominen

Tee lopulta pelille tekstikäyttöliittymä. Pelin tulee käynnistyä kun luokassa Peli olevaa main-metodia kutsutaan. Pelaajalle tulee tarjota vaihtoehdot o, v, y, a, x, missä o on oikealle, v on vasemmalle, y on ylös, a on alas, ja x on lopeta. Jokaisen siirron -- paitsi pelin lopettavan x:n -- jälkeen taulukon satunnaiseen tyhjään kohtaan tulee lisätä luku 1. Alla on esimerkki tekstikäyttöliittymän toiminnasta.

1 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0

> o
0 0 0 1
0 0 0 0
0 0 0 1
0 0 0 0

> y
0 0 0 2
1 0 0 0
0 0 0 0
0 0 0 0

> v
2 0 1 0
1 0 0 0
0 0 0 0
0 0 0 0

> o
0 0 2 1
0 0 0 1
0 1 0 0
0 0 0 0

> y
0 1 2 2
0 0 0 0
0 0 0 0
0 0 1 0

> o
0 0 1 4
0 0 0 0
0 0 0 1
0 0 0 1

> x

Tehtävässä on tarkoitus toteuttaa yksinkertainen laskin. Laskimen käyttöliittymän tulee tarjota kaksi tekstikenttää sekä napit +, - sekä Z.

Layout kuntoon

Toteuta laskimen käyttöliittymä siten, että asettelijana on GridPane, jossa on kolme riviä. Ensimmäisellä kahdella rivillä on tekstikenttä, ja kolmannella rivillä on uusi GridPane, joka sisältää kolme saraketta. Ensimmäisessä sarakkeessa on +-nappi, toisessa sarakkeessa on --nappi, ja kolmannessa sarakkeessa on Z-nappi.

Ylempi tekstikentistä toimii "tuloskenttänä", johon käyttäjä ei saa syöttää numeroita. Alempi toimii kenttänä, johon käyttäjä saa syöttää numeroita. Tuloskentässä on aluksi numero 0 ja syötekenttä on tyhjä.

Perustoiminnallisuus

Laskimen toimintalogiikka on seuraava. Käyttäjän kirjoittaessa syötekenttään luvun n ja painaessa +, lisätään tuloskentässä olevaan arvoon n ja päivitetään tuloskenttä uuteen arvoon. Vastaavasti käyttäjän kirjoittaessa syötekenttään luvun n ja painaessa -, vähennetään tuloskentässä olevasta arvosta n ja päivitetään tuloskenttä uuteen arvoon. Jos käyttäjä painaa Z, nollautuu tuloskenttä.

Vihje: joskus on tarkoituksenmukaista hoitaa yhdellä tapahtumankuuntelijalla usean napin painallusten käsittely.

Hienosäätö

Laajennetaan vielä ohjelmaa seuraavilla ominaisuuksilla:

  • Jos tuloskentässä on 0, ei Z-nappia voi painaa, eli se tulee olla asetettu "pois päältä". Muissa tilanteissa napin tulee olla päällä.
  • Kun käyttäjä painaa jotain napeista +, -, Z syötekenttä tyhjenee.
  • Jos syötekentässä oleva syöte ei ole kokonaisluku ja käyttäjä painaa jotain napeista+, -, Z syötekenttä tyhjenee ja tuloskentän tila ei muutu (paitsi napin ollessa Z).

Sisällysluettelo