Ohjelmoinnin perusteet - testaa taitosi

Arto Vihavainen ja Matti Luukkainen

Tämä dokumentti on tarkoitettu teille, jotka haluatte kerrata ohjelmooinnin perusteiden asiatlyhyesti. Nämä kertaustehtävät on koottu tänne jotta mukaan pääseminen tapahtuisi helposti ja ehtisitte tarvittaessa kertaamaan asioita, joiden hallintaa kurssilla odotetaan.

Varmista nämä tehtävät tekemällä että olet riittävällä lähtötasolla. Mikäli tehtävät tuottavat haasteita katso linkeistä materiaalia kerrataksesi. Koko OhPen materiaali löytyy täältä. Tehtävistä löytyy viittauksia materiaalin kohtiin, josta voi olla apua tehtäviä tehdessä.

Mikäli kaipaat apuja NetBeanssin käytön aloittamiseen tutustu seuraaviin linkeihin: NetBeans aloitusohje. Valitse kuitenkin kurssiksi XXX-ohpe-kertaus

Salasana

Salasana

Tässä tehtävässä luodaan ohjelma joka kyselee käyttäjältä salasanaa. Jos salasana menee oikein, nähdään salainen viesti.

Mikäli tehtävä tuottaa haasteita tutustu seuraaviin linkkeihin: Käyttäjän syötteen lukeminen ja Toiston alkeet

Anna salasana: nauris
Väärin!
Anna salasana: lanttu
Väärin!
Anna salasana: porkkana
Oikein!

Salaisuus on: znvavbfgv grugl!

Toteutetaan ohjelma kolmessa askeleessa.

Salasanan kysyminen

Testipalvelimelta tulevaan ohjelmarunkoon on määritelty muuttuja String salasana, jolle on asetettu arvoksi porkkana -- älä muuta tätä salasanaa. Toteuta lisätoiminnallisuus, jossa ohjelma kysyy käyttäjältä salasanaa ja vertailee sitä muuttujassa salasana olevaan arvoon. Muista mitä erityistä merkkijonojen vertailussa on!

Anna salasana: nauris
Väärin!
Anna salasana: porkkana
Oikein!
Anna salasana: bataatti
Väärin!

Salasanan kysyminen kunnes käyttäjä vastaa oikein

Muokkaa ohjelmaa siten, että se kysyy salasanaa kunnes käyttäjä syöttää oikean salasanan. Toteuta salasanan jatkuva kysyminen while-true -toistolausekkeen avulla. Toistolausekkeesta pääsee pois, jos ja vain jos käyttäjän syöttämä salasana on sama kuin muuttujassa salasana oleva arvo.

Anna salasana: nauris
Väärin!
Anna salasana: lanttu
Väärin!
Anna salasana: porkkana
Oikein!

Salainen viesti

Lisää ohjelmaan oma salainen viestisi joka näytetään kun käyttäjä kirjoittaa salasanan oikein. Se voi olla mitä tahansa!

Anna salasana: nauris
Väärin!
Anna salasana: lanttu
Väärin!
Anna salasana: porkkana
Oikein!

Salaisuus on: znvavbfgv grugl!

Ylläoleva salaisuus on salattu käyttäen Rot13-algoritmia. Toteutamme myöhemmin tällä kurssilla oman salausohjelman.

Yhdestä sataan

Yhdestä sataan

Tee ohjelma, joka tulostaa kokonaisluvut väliltä 1–100.

Mikäli tehtävä tuottaa haasteita tutustu seuraaviin linkkeihin:Toiston alkeet

Ohjelman tulostus on seuraava:

1
2
3
(välissä paljon rivejä)
98
99
100

Tulostelua Like A Boss

Tulostelua Like A Boss

Mikäli tehtävä tuottaa haasteita tutustu seuraaviin linkkeihin:Toiston alkeet ja Omat metodit

Tähtirivin ja tyhjien tulostus

Tee metodi tulostaTyhjaa(int koko) joka tulostaa koko kappaletta välilyöntejä. Metodi ei tulosta rivinvaihtoa.

Saat tehtäväpohjassa metodin tulostaTahtia. Se tulostaa parametrinaan saadun määrän tähtiä ja rivinvaihdon. Käytä tätä tähtien tulostamiseen.

Oikealle nojaavan kolmion tulostus

Tee metodi tulostaKolmio(int koko) joka tulostaa kolmion käyttäen tulostaTyhjaa- ja tulostaTahtia-metodeja. Siis esimerkiksi kutsu tulostaKolmio(4) tulostaa seuraavaa:

   *
  **
 ***
****

Joulukuusen tulostus

Tee metodi jouluKuusi(int korkeus) joka tulostaa joulukuusen. Joulukuusi koostuu annetun korkuisesta kolmiosta ja jalasta. Jalka on kaksi tähteä korkea ja kolme tähteä leveä ja se on keskellä kolmion pohjaa. Kuusi tulee rakentaa käyttämällä tulostukseen metodeja tulostaTyhjaa ja tulostaTahtia

Esimerkiksi kutsu jouluKuusi(4) tulostaa seuraavaa:

   *
  ***
 *****
*******
  ***
  ***

Kutsu jouluKuusi(10) tulostaa:

         *
        ***
       *****
      *******
     *********
    ***********
   *************
  ***************
 *****************
*******************
        ***
        ***

Huom: Korkeuksien jotka ovat alle 3 ei tarvitse toimia!

Silmukat, lopetus ja muistaminen

Silmukat, lopetus ja muistaminen

Tämä tehtäväsarja muodostaa yhden isomman ohjelman, jonka toiminnallisuus toteutetaan pienissä paloissa. Jos et tee tehtäväsarjaa loppuun asti, voit lähettää sen tarkastettavaksi vajaatekoisenakin. Tämä onnistuu painamalla testausnapin oikealla puolella olevasta "submit"-napista eli pienestä ylöspäinosoittavasta nuolesta. Vaikka palautusautomaatti valittaakin vielä tekemättä olevien tehtävänosien testeistä, kirjautuvat jo tekemiesi osien pisteet.

Huom: nyt (ja jatkossa) jokainen isomman tehtävän "alitehtävä" (kuten 36.1) on saman arvoinen tehtävä kuin alikohdaton tehtävä. Tehtävä 36 siis vastaa viittä normaalia tehtävää.

Mikäli tehtävä tuottaa haasteita tutustu seuraan linkkiin: Lisää toistoa

Lukujen lukeminen

Tee ohjelma, joka kysyy käyttäjältä lukuja (ohjelma tulostaa käyttäjälle aluksi "Syötä luvut:"), kunnes käyttäjä antaa luvun -1. Kun käyttäjä syöttää luvun -1, ohjelma tulostaa "Kiitos ja näkemiin!" ja päättyy.

Syötä luvut:
5
2
4
-1
Kiitos ja näkemiin!

Lukujen summa

Laajenna edellistä ohjelmaa siten, että ohjelma ilmoittaa käyttäjän syöttämien lukujen summan. (Lukua -1 ei lasketa mukaan.)

Syötä luvut:
5
2
4
-1
Kiitos ja näkemiin!
Summa: 11

Lukujen summa ja lukumäärä

Laajenna edellistä ohjelmaa siten, että ohjelma ilmoittaa myös käyttäjien antamien lukujen lukumäärän. (Lukua -1 ei lasketa mukaan.)

Syötä luvut:
5
2
4
-1
Kiitos ja näkemiin!
Summa: 11
Lukuja: 3

Lukujen keskiarvo

Muuta edellistä ohjelmaa siten, ohjelma ilmoittaa lukujen keskiarvon. (Lukua -1 ei lasketa mukaan.)

Syötä luvut:
5
2
4
-1
Kiitos ja näkemiin!
Summa: 11
Lukuja: 3
Keskiarvo: 3.666666666666

Parilliset ja parittomat

Laajenna edellistä ohjelmaa siten, että ohjelma ilmoittaa parillisten ja parittomien lukujen määrän. (Lukua -1 ei lasketa mukaan.)

Syötä luvut:
5
2
4
-1
Kiitos ja näkemiin!
Summa: 11
Lukuja: 3
Keskiarvo: 3.666666666666
Parillisia: 2
Parittomia: 1

Sanat

Sanat

Mikäli tehtävä tuottaa haasteita tutustu seuraavaan: ArrayList eli >oliosäiliö>

Tee ohjelma, joka kysyy käyttäjältä sanoja, kunnes käyttäjä antaa tyhjän merkkijonon. Sitten ohjelma tulostaa käyttäjän antamat sanat uudestaan. Kokeile tässä for-toistolauseketta. Käytä ohjelmassa ArrayList-rakennetta, joka määritellään seuraavasti:

ArrayList<String> sanat = new ArrayList<String>();
Anna sana: Mozart
Anna sana: Schubert
Anna sana: Bach
Anna sana: Sibelius
Anna sana: Liszt
Anna sana:
Annoit seuraavat sanat:
Mozart
Schubert
Bach
Sibelius
Liszt

Vihje: tyhjä merkkijono voidaan havaita seuraavasti

String sana = lukija.nextLine();

if ( sana.isEmpty() ) {  // myös tämä tomisi: sana.equals("")
   // sana oli tyhjä eli pelkkä enterin painallus
}

Sanat käänteisesti

Sanat käänteisesti

Mikäli tehtävä tuottaa haasteita tutustu seuraavaan: ArrayList eli >oliosäiliö>

Tee ohjelma, joka kysyy käyttäjältä sanoja, kunnes käyttäjä antaa tyhjän merkkijonon. Sitten ohjelma tulostaa käyttäjän antamat sanat päinvastaisessa järjestyksessä, eli viimeinen syötetty sana ensin jne.

Anna sana: Mozart
Anna sana: Schubert
Anna sana: Bach
Anna sana: Sibelius
Anna sana: Liszt
Anna sana:
Annoit seuraavat sanat:
Liszt
Sibelius
Bach
Schubert
Mozart

Lukujen summa

Lukujen summa

Tee metodi summa, joka laskee parametrinaan saamansa kokonaislukuja sisältävän, eli tyyppiä ArrayList<Integer> olevan listan summan.

Mikäli tehtävä tuottaa haasteita tutustu seuraavaan: ArrayList eli <oliosäiliö>

Tee metodi seuraavaan runkoon:

public static int summa(ArrayList<Integer> lista) {
    // kirjoita koodia tähän
}

public static void main(String[] args) {
    ArrayList<Integer> lista = new ArrayList<Integer>();
    lista.add(3);
    lista.add(2);
    lista.add(7);
    lista.add(2);

    System.out.println("Summa: " + summa(lista));

    lista.add(10);

    System.out.println("Summa: " + summa(lista));
}

Ohjelman tulostus:

Summa: 14
Summa: 24

Onko luku listalla monta kertaa

Onko luku listalla monta kertaa

Mikäli tehtävä tuottaa haasteita tutustu seuraavaan: ArrayList eli <oliosäiliö> ja Totuusarvojen käyttö

Tee metodi onkoListallaUseasti, joka saa parametrinaan kokonaislukuja sisältävän listan ja int-luvun. Jos luku esiintyy listalla yli yhden kerran, metodi palauttaa true ja muulloin false.

Ohjelman rakenne on seuraava:

public static boolean onkoListallaUseasti(ArrayList<Integer> lista, int luku) {
    // kirjoita koodia tähän
}

public static void main(String[] args) {
    ArrayList<Integer> lista = new ArrayList<Integer>();
    lista.add(3);
    lista.add(2);
    lista.add(7);
    lista.add(2);

    System.out.println("Anna luku: ");
    int luku = Integer.parseInt(lukija.nextLine());
    if (onkoListallaUseasti(luvut, luku)) {
        System.out.println(luku + " on listalla useasti.");
    } else {
        System.out.println(luku + " ei ole listalla useasti.");
    }
}
Anna luku: 2
Luku on on listalla useasti.
Anna luku: 3
Luku ei ole listalla useasti.

Palindromi

Palindromi

Mikäli tehtävä tuottaa haasteita tutustu seuraavaan: ArrayList eli <oliosäiliö> ja Totuusarvojen käyttö

Tee metodi palindromi, joka kertoo, onko merkkijono palindromi (merkkijonon sisältö on sama alusta loppuun ja lopusta alkuun luettuna).

Metodi voi käyttää apuna metodia kaanna tehtävästä 56. Metodin tyyppi on boolean, joten se pa lauttaa jokoarvon true (merkkijono on palindromi) tai false (merkkijono ei ole palindromi).

public static boolean palindromi(String merkkijono) {
    // kirjoita koodia tähän
}

public static void main(String[] args) {
    Scanner lukija = new Scanner(System.in);
  
    System.out.println("Anna merkkijono: ");
    String merkkijono = lukija.nextLine();    
    if (palindromi(merkkijono)) {
	   System.out.println("Merkkijono on palindromi!");
    } else {
	   System.out.println("Merkkijono ei ole palindromi!");
    }
}

Ohjelman tulostuksia:

Anna merkkijono: saippuakauppias
Merkkijono on palindromi!
Anna merkkijono: esimerkki
Merkkijono ei ole palindromi!

Lyyra-kortti

Lyyra-kortti

Helsingin Yliopiston opiskelijaruokaloissa eli Unicafeissa opiskelijat maksavat lounaansa käyttäen Lyyra-korttia.

Tässä tehtäväsäsarjassa tehdään luokka LyyraKortti, jonka tarkoituksena on jäljitellä Lyyra-kortin käyttämistä Unicafessa.

Mikäli tehtävä tuottaa haasteita tutustu seuraavaan: Olio-ohjelmointi ja Lisää luokista ja olioista

Luokan runko

Projektiin tulee kuulumaan kaksi kooditiedostoa:

Tehtäväpohjan eli projektin Viikko4_077.Lyyrakortti mukana tulee kooditiedosto Paaohjelma jonka sisällä on main-metodi.

Lisää projektiin uusi luokka nimeltä LyyraKortti. Uuden luokan saa lisättyä seuraavasti: Ruudun vasemmalla reunalla on projektilistaus. Paina projektin nimen Viikko4_077.Lyyrakortti kohdalla hiiren oikeaa nappia. Valitse avautuvasta valikosta New ja Java Class. Anna luokan nimeksi (Class Name) LyyraKortti.

Tee ensin LyyraKortti-olion konstruktori, jolle annetaan kortin alkusaldo ja joka tallentaa sen olion sisäiseen muuttujaan. Tee sitten toString-metodi, joka palauttaa kortin saldon muodossa "Kortilla on rahaa X euroa".

Seuraavassa on luokan LyyraKortti runko:

public class LyyraKortti {
    private double saldo;

    public LyyraKortti(double alkusaldo) {
        // kirjoita koodia tähän
    }

    public String toString() {
        // kirjoita koodia tähän
    }
}

Seuraava pääohjelma testaa luokkaa:

public class Paaohjelma {
    public static void main(String[] args) {
        LyyraKortti kortti = new LyyraKortti(50);
        System.out.println(kortti);
    }
}

Ohjelman tulisi tuottaa seuraava tulostus:

Kortilla on rahaa 50.0 euroa

Kortilla maksaminen

Täydennä LyyraKortti-luokkaa seuraavilla metodeilla:

    public void syoEdullisesti() {
        // kirjoita koodia tähän
    }

    public void syoMaukkaasti() {
        // kirjoita koodia tähän
    }

Metodin syoEdullisesti tulisi vähentää kortin saldoa 2.50 eurolla ja metodin syoMaukkaasti tulisi vähentää kortin saldoa 4.00 eurolla.

Seuraava pääohjelma testaa luokkaa:

public class Paaohjelma {
    public static void main(String[] args) {
        LyyraKortti kortti = new LyyraKortti(50);
        System.out.println(kortti);

        kortti.syoEdullisesti();
        System.out.println(kortti);

        kortti.syoMaukkaasti();
        kortti.syoEdullisesti();
        System.out.println(kortti);
    }
}

Ohjelman tulisi tuottaa seuraava tulostus:

Kortilla on rahaa 50.0 euroa
Kortilla on rahaa 47.5 euroa
Kortilla on rahaa 41.0 euroa

Ei-negatiivinen saldo

Mitä tapahtuu, jos kortilta loppuu raha kesken? Ei ole järkevää, että saldo muuttuu negatiiviseksi. Muuta metodeita syoEdullisesti ja syoMaukkaasti niin, että ne eivät vähennä saldoa, jos saldo menisi negatiiviseksi.

Seuraava pääohjelma testaa luokkaa:

public class Paaohjelma {
    public static void main(String[] args) {
        LyyraKortti kortti = new LyyraKortti(5);
        System.out.println(kortti);

        kortti.syoMaukkaasti();
        System.out.println(kortti);

        kortti.syoMaukkaasti();
        System.out.println(kortti);
    }
}

Ohjelman tulisi tuottaa seuraava tulostus:

Kortilla on rahaa 5.0 euroa
Kortilla on rahaa 1.0 euroa
Kortilla on rahaa 1.0 euroa

Yllä toinen metodin syoMaukkaasti kutsu ei vaikuttanut saldoon, koska saldo olisi mennyt negatiiviseksi.

Kortin lataaminen

Lisää LyyraKortti-luokkaan seuraava metodi:

    public void lataaRahaa(double rahamaara) {
        // kirjoita koodia tähän
    }

Metodin tarkoituksena on kasvattaa kortin saldoa parametrina annetulla rahamäärällä. Kuitenkin kortin saldo saa olla korkeintaan 150 euroa, joten jos ladattava rahamäärä ylittäisi sen, saldoksi tulisi tulla silti tasan 150 euroa.

Seuraava pääohjelma testaa luokkaa:

public class Paaohjelma {
    public static void main(String[] args) {
        LyyraKortti kortti = new LyyraKortti(10);
        System.out.println(kortti);

        kortti.lataaRahaa(15);
        System.out.println(kortti);

        kortti.lataaRahaa(10);
        System.out.println(kortti);

        kortti.lataaRahaa(200);
        System.out.println(kortti);
    }
}

Ohjelman tulisi tuottaa seuraava tulostus:

Kortilla on rahaa 10.0 euroa
Kortilla on rahaa 25.0 euroa
Kortilla on rahaa 35.0 euroa
Kortilla on rahaa 150.0 euroa

Kortin lataus negatiivisella arvolla

Muuta metodia lataaRahaa vielä siten, että jos yritetään ladata negatiivinen rahamäärä, ei kortilla oleva arvo muutu.

Seuraava pääohjelma testaa luokkaa:

public class Paaohjelma {
    public static void main(String[] args) {
        LyyraKortti kortti = new LyyraKortti(10);
        System.out.println(kortti);
        kortti.lataaRahaa(-15);
        System.out.println(kortti);
    }
}

Ohjelman tulisi tuottaa seuraava tulostus:

Kortilla on rahaa 10.0 euroa
Kortilla on rahaa 10.0 euroa

Monta korttia

Tee pääohjelma, joka sisältää seuraavan tapahtumasarjan:

Pääohjelman runko on seuraava:

public class Main {
    public static void main(String[] args) {
        LyyraKortti pekanKortti = new LyyraKortti(20);
        LyyraKortti matinKortti = new LyyraKortti(30);

        // kirjoita koodia tähän
    }
}

Ohjelman tulisi tuottaa seuraava tulostus:

Pekka: Kortilla on rahaa 16.0 euroa
Matti: Kortilla on rahaa 27.5 euroa
Pekka: Kortilla on rahaa 36.0 euroa
Matti: Kortilla on rahaa 23.5 euroa
Pekka: Kortilla on rahaa 31.0 euroa
Matti: Kortilla on rahaa 73.5 euroa

Asuntovertailu

Asuntovertailu

Asuntovälitystoimiston tietojärjestelmässä myynnissä olevaa asuntoa kuvataan seuraavan luokan olioilla:

public class Asunto {
  private int huoneita;
  private int nelioita;
  private int neliohinta;

  public Asunto(int huoneita, int nelioita, int neliohinta){
    this.huoneita = huoneita;
    this.nelioita = nelioita;
    this.neliohinta = neliohinta;
  }
}

Tehtävänä on toteuttaa muutama metodi, joiden avulla myynnissä olevia asuntoja voidaan vertailla.

Mikäli tehtävä tuottaa haasteita tutustu seuraavaan: Lisää luokista ja olioista

Suurempi

Tee metodi public boolean suurempi(Asunto verrattava) joka palauttaa true jos asunto-olio, jolle metodia kutsutaan on suurempi kuin verrattavana oleva asunto-olio.

Esimerkki metodin toiminnasta:

  Asunto eiraYksio = new Asunto(1, 16, 5500);
  Asunto kallioKaksio = new Asunto(2, 38, 4200);
  Asunto jakomakiKolmio = new Asunto(3, 78, 2500);

  System.out.println( eiraYksio.suurempi(kallioKaksio) );       // false
  System.out.println( jakomakiKolmio.suurempi(kallioKaksio) );  // true

Hintaero

Tee metodi public int hintaero(Asunto verrattava) joka palauttaa asunto-olion jolle metodia kutsuttiin ja parametrina olevan asunto-olion hintaeron. Hintaero on asuntojen hintojen (=neliöhinta*neliöt) itseisarvo.

Esimerkki metodin toiminnasta:

  Asunto eiraYksio = new Asunto(1, 16, 5500);
  Asunto kallioKaksio = new Asunto(2, 38, 4200);
  Asunto jakomakiKolmio = new Asunto(3, 78, 2500);

  System.out.println( eiraYksio.hintaero(kallioKaksio) );        // 71600
  System.out.println( jakomakiKolmio.hintaero(kallioKaksio) );   // 35400

Kalliimpi

Tee metodi public boolean kalliimpi(Asunto verrattava) joka palauttaa true jos asunto-olio, jolle metodia kutsutaan on kalliimpi kuin verrattavana oleva asunto-olio.

Esimerkki metodin toiminnasta:

  Asunto eiraYksio = new Asunto(1, 16, 5500);
  Asunto kallioKaksio = new Asunto(2, 38, 4200);
  Asunto jakomakiKolmio = new Asunto(3, 78, 2500);

  System.out.println( eiraYksio.kalliimpi(kallioKaksio) );       // false
  System.out.println( jakomakiKolmio.kalliimpi(kallioKaksio) );   // true

Joukkueet ja pelaajat

Joukkueet ja pelaajat

Mikäli tehtävä tuottaa haasteita tutustu seuraavaan: Lisää luokista ja olioista

Joukkue-luokka

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

Seuraava pääohjelma testaa luokan toimintaa:

public class Main {
    public static void main(String[] args) {
	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:

public class Main {
    public static void main(String[] args) {
	Joukkue tapiiri = new Joukkue("FC Tapiiri");
	System.out.println("Joukkue: " + tapiiri.haeNimi());

        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:

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

Seuraava pääohjelma testaa luokan toimintaa:

public class Main {
    public static void main(String[] args) {
	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:

Joukkueen suurin sallittu pelaajamäärä on oletusarvoisesti 16. Metodin asetaMaksimikoko avulla tätä rajaa voi muuttaa. Muuta metodia lisaaPelaaja niin, että se ei lisää pelaajaa joukkueeseen, jos sallittu pelaajamäärä ylittyisi.

HUOM: muista lisätä oletusarvoinen maksimikoko koodiisi sillä muuten arvoksi tulee 0. Tämä aiheuttaa edellisen kohdan testien hajoamisen, sillä testit luovat oletusmaksimikokoisia joukkueita ja jos joukkueen maksimikoko on 0, ei joukkueeseen voi lisätä yhtään pelaajaa.

Seuraava pääohjelma testaa luokan toimintaa:

public class Main {
    public static void main(String[] args) {
	Joukkue tapiiri = new Joukkue("FC Tapiiri");
        tapiiri.asetaMaksimikoko(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.koko());
    }
}
Pelaajia yhteensä: 1

Joukkueen maalit

Lisää luokkaan Joukkue metodi:

Seuraava pääohjelma testaa luokan toimintaa:

public class Main {
    public static void main(String[] args) {
	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.maalit());
    }
}
Maaleja yhteensä: 40

Päivämäärien erotus

Päivämäärien erotus

Mikäli tehtävä tuottaa haasteita tutustu seuraavaan: Lisää luokista ja olioista

Kahden päiväyksen erotus vuosissa

Lisää päiväykselle metodi public int erotusVuosissa(Paivays verrattava), jonka avulla saadaan selville päiväyksen ja verrattavan päiväyksen ero vuosissa. Huomioi seuraavat:

Seuraava pääohjelma demonstroi metodin käyttöä:

public class Paaohjelma {
    public static void main(String[] args) {
        Paivays eka = new Paivays(24, 12, 2009);
        Paivays toka = new Paivays(1, 1, 2011);
        Paivays kolmas = new Paivays(25, 12, 2010);

        System.out.println( toka + " ja " + eka + " ero vuosissa: " + toka.erotusVuosissa(eka) );

        System.out.println( kolmas + " ja " + eka + " ero vuosissa: " + kolmas.erotusVuosissa(eka) );

        System.out.println( toka + " ja " + kolmas + " ero vuosissa: " + toka.erotusVuosissa(kolmas) );
    }
}

Tulos näyttää seuraavalta:

1.1.2011 ja 24.12.2009 ero vuosissa: 2
25.12.2010 ja 24.12.2009 ero vuosissa: 1
1.1.2011 ja 25.12.2010 ero vuosissa: 1

Tarkennettu versio

Vuosien laskenta ei edellisessä versiossa ollut vielä kovin tarkkaa. Esim. 1.1.2011 ja 25.12.2010 välillä ilmoitettiin olevan vuoden ero. Tarkennetaan metodin toiminta sellaiseksi, että se osaa laskea vuodet kunnolla. Laske erotukseen mukaan vain täydet vuodet. Eli vaikka päiväysten ero olisi 1 vuosi ja 364 päivää, ilmoittaa metodi eroksi vuoden.

Metodin tämänkin version tarvitsee toimia ainoastaan siten, että parametriksi annettava päivämäärä on aiempi kuin se päivämäärä jolle metodia kutsutaan.

Edellisen esimerkin tulos on nyt:

1.1.2011 ja 24.12.2009 ero vuosissa: 1
25.12.2010 ja 24.12.2009 ero vuosissa: 1
1.1.2011 ja 25.12.2010 ero vuosissa: 0

Ja lopullinen versio

Laitetaan metodi toimimaan samoin riippumatta onko parametrina annettava päiväys myöhempi vai aiempi kuin päiväys mille metodia kutsutaan. Esimerkkipääohjelma:

public class Paaohjelma {
    public static void main(String[] args) {
        Paivays eka = new Paivays(24, 12, 2009);
        Paivays toka = new Paivays(1, 1, 2011);
        Paivays kolmas = new Paivays(25, 12, 2010);

        System.out.println( eka + " ja " + toka + " ero vuosissa: " + toka.erotusVuosissa(eka) );
        System.out.println( toka + " ja " + eka + " ero vuosissa: " + eka.erotusVuosissa(toka) );
        System.out.println( eka + " ja " + kolmas + " ero vuosissa: " + kolmas.erotusVuosissa(eka) );
        System.out.println( kolmas + " ja " + eka + " ero vuosissa: " + eka.erotusVuosissa(kolmas) );
        System.out.println( kolmas + " ja " + toka + " ero vuosissa: " + toka.erotusVuosissa(kolmas) );
        System.out.println( toka + " ja " + kolmas + " ero vuosissa: " + kolmas.erotusVuosissa(toka) );
    }
}
24.12.2009 ja 1.1.2011 ero vuosissa: 1
1.1.2011 ja 24.12.2009 ero vuosissa: 1
24.12.2009 ja 25.12.2010 ero vuosissa: 1
25.12.2010 ja 24.12.2009 ero vuosissa: 1
1.1.2011 ja 25.12.2010 ero vuosissa: 0
25.12.2010 ja 1.1.2011 ero vuosissa: 0

Taulukon lukujen summa

Taulukon lukujen summa

Mikäli tehtävä tuottaa haasteita tutustu seuraavaan: Taulukko

Tee metodi public static int laskeTaulukonLukujenSumma(int[] taulukko), joka palauttaa taulukossa olevien lukujen summan.

Ohjelman runko on seuraava:

public class Main {
  public static void main(String[] args) {
    // Tässä voit testata metodia
    int[] taulukko = {5, 1, 3, 4, 2};
    System.out.println(laskeTaulukonLukujenSumma(taulukko));
  }

  public static int laskeTaulukonLukujenSumma(int[] taulukko) {
    // Kirjoita koodia tänne
    return 0;
  }
}

Ohjelman tulostus on seuraava:

15

Huom: tämän tehtävän metodi samoin kuin muutamien seuraavien tehtävien taulukkoa käsittelevät metodit ovat viikkojen 2 ja 3 tapaan static eli staattisia metodeja. Karkeasti ottaen tämä johtuu siitä, että metodi ei liity mihinkään olioon, vaan saa kaiken datan jota se käyttää eli tässä tapauksessa taulukon, parametrina. Luvussa 28 palaamme tarkemmin aiheeseen staattiset vs. olioihin liittyvät metodit.

Tähtitaivas

Tähtitaivas

Mikäli tehtävä tuottaa haasteita tutustu seuraavaan: Satunnaisuus ja Lohkoista ja sisäkkäisitä toistolauseista

Luodaan ohjelma tähtitaivaan tulostamiseen. Tähtitaivaan tähtien määrä kerrotaan tiheyden avulla. Esimerkiksi jos tähtitaivaan tiheys on 0.1, on noin 10% tähtitaivaasta peitettynä tähdillä. Pääset harjoittelemaan siis myös satunnaisuuslukujen käyttöä.

Käytä tähtien tulostamiseen *-merkkiä. Alla on esimerkki lopullisen Tahtitaivas-luokan käytöstä ja käyttöä vastaavasti tulostuksesta.

    Tahtitaivas tahtitaivas = new Tahtitaivas(0.1);
    tahtitaivas.tulosta();
    System.out.println("Tähtiä: " + tahtitaivas.tahtiaViimeTulostuksessa());
    System.out.println("");
    
    tahtitaivas = new Tahtitaivas(0.2, 15, 6);
    tahtitaivas.tulosta();
    System.out.println("Tähtiä: " + tahtitaivas.tahtiaViimeTulostuksessa());
        *     *                  *      
    *             * *         *      ** 
                                     *  
        *       *      *         *  *   
 *     *                     *          
*            * *                   *    
*  * *           *          * *  **     
                            *  *        
          *               *             
     *                             *    
Tähtiä: 36

 * * *     *   
     * *   *   
*     *        
   *  *       *
*       *   * *
* ** **     *  
Tähtiä: 22

Huom! tehtävissä kannattaa käyttää for-lauseketta. Vaikka edellinen luku puhuukin sisäkkäisistä toistolauseista, tässä tehtävässä "sisempi" toisto piilotetaan metodin sisälle.

Tahtitaivas-luokka ja yhden rivin tulostaminen

Luo luokka Tahtitaivas, jolla on kolme oliomuuttujaa: tiheys (double), leveys (int), ja korkeus (int). Luo luokalle myös kolme konstruktoria:

Lisää luokalle Tahtitaivas metodi tulostaRivi, joka tulostaa yhden rivin. Rivin leveyden määrää oliomuuttuja leveys. Oliomuuttuja tiheys kertoo todennäköisyyden tähdelle. Arvo jokaisen merkin kohdalla tulostetaanko tähti vai ei Random-luokan nextDouble-metodin avulla.

Testaa ohjelmaasi, esimerkkinä seuraava kutsu ja esimerkkitulostus.

    Tahtitaivas tahtitaivas = new Tahtitaivas(0.1);
    tahtitaivas.tulostaRivi();
            *  *                  *     

Tähtitaivaan tulostus

Luo Tahtitaivas-luokalle metodi tulosta, joka tulostaa koko tähtitaivaan. Käytä tässä hyödyksesi aiempaa tulostaRivi-metodia.

    Tahtitaivas tahtitaivas = new Tahtitaivas(8, 4);
    tahtitaivas.tulosta();
    *   
        
  *     
    *   

Tähtien laskeminen

Lisää Tahtitaivas-luokalle oliomuuttuja tahtiaViimeTulostuksessa (int) ja metodi tahtiaViimeTulostuksessa(), joka palauttaa viime tulostuksessa tulostuneiden tähtien lukumäärän. Toteuta ohjelmaasi tähtien laskeminen.

    Tahtitaivas tahtitaivas = new Tahtitaivas(8, 4);
    tahtitaivas.tulosta();
    System.out.println("Tähtiä: " + tahtitaivas.tahtiaViimeTulostuksessa());
    System.out.println("");
    
    tahtitaivas.tulosta();
    System.out.println("Tähtiä: " + tahtitaivas.tahtiaViimeTulostuksessa());
        
        
 *      
        
Tähtiä: 1

 *      
      * 
*       
        
Tähtiä: 3

Kirjaston tietojärjestelmä

Kirjaston tietojärjestelmä

Mikäli tehtävä tuottaa haasteita tutustu seuraavaan: Lohkoista ja sisäkkäisitä toistolauseista ja static:illa vai ilman?

Kumpulan tiedekirjasto tarvitsee uuden järjestelmän kirjojen hallintaan. Tässä tehtävässä toteutetaan prototyyppi, jossa toteutetaan kirjan haku nimen, julkaisijan tai julkaisuvuoden perusteella.

Rakennetaan järjestelmä osista, ensin toteutetaan oleelliset luokat eli Kirja ja Kirjasto. Luokka Kirja sisältää kirjaan liittyvät tiedot, luokka Kirjasto tarjoaa erilaisia hakutoiminnallisuuksia kirjoihin liittyen.

Kirja

Luodaan ensiksi luokka Kirja. Kirjalla on oliomuuttujina nimike, eli kirjan nimi, julkaisija, eli kirjan julkaisija, ja julkaisuvuosi eli vuosi jolloin kirja on julkaistu. Kaksi ensimmäistä muuttujaa on merkkijonotyyppisiä, viimeisin on kokonaisluku. Oletamme tässä että kirjalla on aina vain yksi kirjoittaja.

Toteuta luokka Kirja. Kirjalla tulee olla myös konstruktori public Kirja(String nimike, String julkaisija, int julkaisuvuosi) sekä metodit public String nimike(), public String julkaisija(), public int julkaisuvuosi() ja public String toString(). Arvannet mitä metodien tulee tehdä, alla esimerkki.

Testaa luokan toimintaa:

Kirja cheese = new Kirja("Cheese Problems Solved", "Woodhead Publishing", 2007);
System.out.println(cheese.nimike());
System.out.println(cheese.julkaisija());
System.out.println(cheese.julkaisuvuosi());

System.out.println(cheese);
Cheese Problems Solved
Woodhead Publishing
2007
Cheese Problems Solved, Woodhead Publishing, 2007

Kirjasto

Kirjaston tehtävä on antaa käyttäjälle mahdollisuus kirjojen lisäämiseen ja niiden hakemiseen. Luo luokka Kirjasto, jolla on konstruktori public Kirjasto() ja metodit public void lisaaKirja(Kirja uusiKirja) ja public void tulostaKirjat()

Kirjasto kirjasto = new Kirjasto();

Kirja cheese = new Kirja("Cheese Problems Solved", "Woodhead Publishing", 2007);
kirjasto.lisaaKirja(cheese);

Kirja nhl = new Kirja("NHL Hockey", "Stanley Kupp", 1952);
kirjasto.lisaaKirja(nhl);

kirjasto.lisaaKirja(new Kirja("Battle Axes", "Tom A. Hawk", 1851));

kirjasto.tulostaKirjat();
Cheese Problems Solved, Woodhead Publishing, 2007
NHL Hockey, Stanley Kupp, 1952
Battle Axes, Tom A. Hawk, 1851

Hakutoiminnallisuus

Kirjastosta tulee pystyä etsimään kirjoja nimikkeiden ja julkaisijoiden perusteella. Lisää kirjastolle metodit public ArrayList<Kirja> haeKirjaNimikkeella(String nimike), public ArrayList<Kirja> haeKirjaJulkaisijalla(String julkaisija) ja public ArrayList<Kirja> haeKirjaJulkaisuvuodella(int julkaisuvuosi). Metodit palauttavat listan kirjoista, joissa on haluttu nimike, julkaisija tai julkaisuvuosi.

Huom: joudut siis tehdä metodin jonka paluuarvona on ArrayList. Tämä onnustuu seuraavaa metodirunkoa hyödyntäen:

public class Kirjasto {
   // ...

   public ArrayList<Kirja> haeKirjaNimikkeella(String nimike) {
     ArrayList<Kirja> loydetyt = new ArrayList<Kirja>

     // käy läpi kaikki kirjat ja lisää ne joilla haetun kaltainen nimike listalle loydetyt

     return loydetyt;  
   }

Huom! Kun haet teet hakua merkkijonon avulla, älä tee tarkkaa hakua (metodi equals) vaan käytä String-luokan metodia contains. Huomaat todennäköisesti myös että sinulla on ns. copy-paste -koodia Kirjasto-luokan koodissa. Keksitkö tavan päästä siitä eroon?

Kirjasto kirjasto = new Kirjasto();

kirjasto.lisaaKirja(new Kirja("Cheese Problems Solved", "Woodhead Publishing", 2007));
kirjasto.lisaaKirja(new Kirja("The Stinky Cheese Man and Other Fairly Stupid Tales", "Penguin Group", 1992));
kirjasto.lisaaKirja(new Kirja("NHL Hockey", "Stanley Kupp", 1952));
kirjasto.lisaaKirja(new Kirja("Battle Axes", "Tom A. Hawk", 1851));

ArrayList<Kirja> hakutulos = kirjasto.haeKirjaNimikkeella("Cheese");
for (Kirja kirja: hakutulos) {
    System.out.println(kirja);
}

System.out.println("---");
for (Kirja kirja: kirjasto.haeKirjaJulkaisijalla("Penguin Group  ")) {
    System.out.println(kirja);
}

System.out.println("---");
for (Kirja kirja: kirjasto.haeKirjaJulkaisuvuodella(1851)) {
    System.out.println(kirja);
}
Cheese Problems Solved, Woodhead Publishing, 2007
The Stinky Cheese Man and Other Fairly Stupid Tales, Penguin Group, 1992
---
---
Battle Axes, Tom A. Hawk, 1851

Paranneltu hakutoiminnallisuus

Hakutoiminnallisuutemme on jo hyvä, mutta se ei ymmärrä isojen ja pienten kirjainten eroa. Yllä olleessa esimerkissä haku nimikkeellä "cheese" ei olisi tuottanut yhtäkään tulosta. Myös toinen esimerkki, jossa oli ylimääräisiä välilyöntejä, ei näyttänyt haluttua tulosta. Haluamme että nimikkeiden ja julkaisijoiden nimillä haettaessa ei välitetä merkkien koosta, ja että käyttäjä voi syöttää ylimääräisiä välilyöntejä kirjan nimen alkuun tai loppuun (meidän ei tarvitse välittää sanojen välillä olevista tyhjistä!). Toteutetaan pieni apukirjasto StringUtils merkkijonojen vertailuun.

Luo luokka StringUtils, ja lisää sille staattinen metodi public static boolean sisaltaa(String sana, String haettava), joka tarkistaa sisältääkö merkkijono sana merkkijonon haettava. Jos jommankumman merkkijonon arvo on null, metodin tulee palauttaa arvo false. Metodin tarjoaman vertailun tulee olla välittämättä merkin koosta.

Lisää metodille sisaltaa myös toiminnallisuus, joka poistaa merkkijonojen sana ja haettava alusta ja lopusta ylimääräiset välilyönnit. Käytä tähän String-luokan metodia trim, esim. trimmattu = trimmattava.trim()

Vinkki! String-luokan metodista toUpperCase() on hyötyä kun haluat verrata ovatko kaksi merkkijonoa samat -- riippumatta niiden alkuperäisestä merkkikoosta.

Kun olet saanut metodin valmiiksi, käytä sitä Kirjasto-luokassa. Alla esimerkki:

if(StringUtils.sisaltaa(kirja.nimike(), haettuNimike)) {
   // kirja löytyi!
}
Kirjasto kirjasto = new Kirjasto();

kirjasto.lisaaKirja(new Kirja("Cheese Problems Solved", "Woodhead Publishing", 2007));
kirjasto.lisaaKirja(new Kirja("The Stinky Cheese Man and Other Fairly Stupid Tales", "Penguin Group", 1992));
kirjasto.lisaaKirja(new Kirja("NHL Hockey", "Stanley Kupp", 1952));
kirjasto.lisaaKirja(new Kirja("Battle Axes", "Tom A. Hawk", 1851));

for (Kirja kirja: kirjasto.haeKirjaNimikkeella("CHEESE")) {
    System.out.println(kirja);
}

System.out.println("---");
for (Kirja kirja: kirjasto.haeKirjaJulkaisijalla("PENGUIN  ")) {
    System.out.println(kirja);
}
Cheese Problems Solved, Woodhead Publishing, 2007
The Stinky Cheese Man and Other Fairly Stupid Tales, Penguin Group, 1992
---
The Stinky Cheese Man and Other Fairly Stupid Tales, Penguin Group, 1992

Arvosanajakauma

Arvosanajakauma

Tehtävä vastaa kolmea yksiosaista tehtävää.

Mikäli tehtävä tuottaa haasteita tutustu seuraavaan: Koko OhPen materiaali

HUOM: Ohjelmassa saa käyttää vain yhtä Scanner-olioa, eli vain kertaalleen saa sanoa new Scanner. Jos tarvitset Scanneria monessa kohtaa, voit välittää sen muualle parametrina seuraavaan tyyliin:

  public static void main(String[] args) {
     Scanner lukija = new Scanner(System.in);

     // ...
     
     teeJotain(lukuja);  
  }

  public static void teeJotain(Scanner lukija) {
     String rivi = lukija.nextLine();
     // ...
  }

Tai jos toinen olio tarvitsee Scanneria, voi sen välittää konstruktoriparametrina ja tallettaa oliomuuttujaan jolloin Scanner on olion kaikkien metodien käytössä.

Ohjelman syöte on joukko kokonaislukuja, jotka kuvaavat opiskelijoiden kokeesta saamia pistemääriä. Käyttäjä syöttää yhden pistemäärän per rivi. Kun syöte on -1, lopettaa ohjelma pistemäärien kyselyn.

Pisteiden syöttö toimii seuraavasti:

Syötä koepisteet, -1 lopettaa:
34
41
53
36
55
27
43
40
-1

Pisteiden syöttämisen jälkeen ohjelma tulostaa kurssin arvosanajakauman ja hyväksymisprosentin seuraavassa muodossa:

Arvosanajakauma:
5: **
4:   
3: ***
2: *
1: *
0: *
Hyväksymisprosentti: 87.5 

Arvosananajakauma muodostetaan seuraavasti:

pistemäärä arvosana
0–29 hylätty
30–34 1
35–39 2
40–44 3
45–49 4
50-60 5

Hyväksyttyjä ovat muut paitsi arvosanan 0 saaneet. Hyväksyttyjä edellä on siis 7 osallistujaa 8:sta. Hyväksymisprosentti lasketaan kaavalla 100*hyväksytyt/osallistujat.