Tehtävät viikolle 6

Pakolliset tehtävät on merkitty harmalla taustavärillä. Punaisella taustavärillä merkatut ovat kontrollitehtäviä, jotka näytetään ohjaajalle harjoitustilaisuudessa!

HUOM: nimeä tiedostot otsikossa olevan sanan mukaan

Lämmittely

Nimeä oikein

Korjaa seuraava koodi käyttämään materiaalissa olevia nimeämissääntöjä.

public class laskin {

    public static void main(String[] KomentoriviParametrit) {

        int i = 0;
        Laskuri OmaLaskuri = new laskuri(0);

        System.out.println("omaLaskurin arvo on " + OmaLaskuri.annaArvo());

        OmaLaskuri.KasvataArvoa();
        OmaLaskuri.KasvataArvoa();
        OmaLaskuri.KasvataArvoa();
        OmaLaskuri.KasvataArvoa();
        OmaLaskuri.KasvataArvoa();
        OmaLaskuri.KasvataArvoa();

        if (i == 0) {
            System.out.println("i on 0");
            System.out.println("ja pysyy");
        } else {
            System.out.println("i oli jotain muuta");
            i = 0;
            System.out.println("mutta nyt se on 0");
        }

        int Arvo = OmaLaskuri.annaArvo();

        System.out.println("omaLaskurin arvo on " + Arvo);
    }
}

Metrorata

Tämä tehtävä on kokonaisuus, voit tehdä sen yhteen projektiin.

Asema

Tee luokka Asema. Aseman nimi ilmaistaan kahdella kirjaimella.

Asema rl = new Asema("RL");
Asema kp = new Asema("KP");
Asema rt = new Asema("RT");
Asema kn = new Asema("KN");
Asema ht = new Asema("HT");
Asema sn = new Asema("SN");
Asema ka = new Asema("KA");
Asema ks = new Asema("KS");
Asema hn = new Asema("HN");
Asema st = new Asema("ST");
Asema ik = new Asema("IK");
Asema pt = new Asema("PT");
Asema rs = new Asema("RS");
Asema vs = new Asema("VS");
Asema mp = new Asema("MP");
Asema kl = new Asema("KL");
Asema mm = new Asema("MM");


System.out.println(rt);  // Tulostaa "RT"

Rata

Tee luokka Rata ja testaa seuraavalla ohjelmalla.

Asema[] linja1983 = {kp, rt, ht, ks, hn, st, ik};
Rata metroRata1983 = new Rata("Helsingin Metro", 1983, linja1983);

System.out.println(metroRata1983);

Ohjelma tulostaa seuraavaa.

Helsingin Metro: 1983

-KP--RT--HT--KS--HN--ST--IK-

Haarat

Seuraava ohjelma tulostaa kaksi versiota metroradasta, vuosien 1983 ja 2010 tilanteen.

Tulostuksessa voit ottaa eri tilanteet huomioon vertaamalla mahdollisten haarojen olemassaoloa tyhjään viitearvoon null.

Muista, että välillä saattaa käydä vesivahinko ja jokin asema otetaan kokonaan pois kartasta. Ohjelman tulee toimia myös tällöin oikein (katso seuraava tehtävä).

Asema[] linja1983 = {kp, rt, ht, ks, hn, st, ik};

Asema[] linja2010 = {rl, kp, rt, kn, ht, sn, ka, ks, hn, st, ik};
Asema[] haaraVs = {pt, rs, vs};
Asema[] haaraMm = {mp, kl, mm};

Rata metroRata1983 = new Rata("Helsingin Metro", 1983, linja1983);
Rata metroRata2010 = new Rata("Helsingin Metro", 2010, linja2010, haaraMm, haaraVs);

System.out.println(metroRata1983);
System.out.println(metroRata2010);

Ohjelman tuloste

Helsingin Metro: 1983

-KP--RT--HT--KS--HN--ST--IK-

Helsingin Metro: 2010

                                        -MP--KL--MM-
-RL--KP--KN--HT--SN--KA--KS--HN--ST--IK-
                                        -PT--RS--VS-	

Vesivahinko

Mikä tahansa asema tulee voida poistaa käytöstä. Haarojen tulostuksen pitää silti toimia oikein (haarat ovat kiinni metrolinjan itäisessä päässä)

Asema[] linja1983 = {kp, rt, ht, ks, hn, st, ik};
Asema[] linja2010 = {rl, kp, rt, kn, ht, sn, ka, ks, hn, st, ik};
Asema[] vesivahinko2010 = {rl, kp, kn, ht, sn, ka, ks, hn, st, ik};

Asema[] haaraVs = {pt, rs, vs};
Asema[] haaraMm = {mp, kl, mm};


Rata metroRata1983 = new Rata("Helsingin Metro", 1983, linja1983);
Rata metroRata2010 = new Rata("Helsingin Metro", 2010, linja2010, haaraMm, haaraVs);
Rata vesivahinkoRata2010 = new Rata("Helsingin Vesivahinkometro", 2010, vesivahinko2010, haaraMm, haaraVs);

System.out.println(metroRata1983);
System.out.println(metroRata2010);
System.out.println(vesivahinkoRata2010);

Ohjelman tuloste

Helsingin Metro: 1983

-KP--RT--HT--KS--HN--ST--IK-

Helsingin Metro: 2010

                                            -MP--KL--MM-
-RL--KP--RT--KN--HT--SN--KA--KS--HN--ST--IK-
                                            -PT--RS--VS-

Helsingin Vesivahinkometro: 2010

                                        -MP--KL--MM-
-RL--KP--KN--HT--SN--KA--KS--HN--ST--IK-
                                        -PT--RS--VS-	

Järjestäminen ja hakeminen

Tämä tehtävä on kokonaisuus, voit tehdä sen yhteen projektiin.

taulukonPienin

Tee staattinen metodi public static int taulukonPienin(int[] taulukko) joka palautaa taulukon pienimmän alkion.

int[] luvut = {8, 3, 7, 12, -3, 2, 4};	

System.out.println("Pienin on: " + taulukonPienin(luvut));
Pienin on: -3

taulukonPieninIndeksi

Tee staattinen metodi public static int taulukonPieninIndeksi(int[] taulukko) joka palautaa taulukon pienimmän alkion indeksin, eli sen lokeronumeron jossa taulukon pienin alkio on.

int[] luvut = {8, 3, 7, 12, -3, 2, 4};	

System.out.println("Pienin on indeksissä: " + taulukonPieninIndeksi(luvut));
Pienin indeksi on: 4

taulukkoTekstiksi

Tee staattinen metodi public static String taulukkoTekstiksi(int[] taulukko), joka palauttaa taulukon sisällön tekstinä.

int[] luvut = {8, 3, 7, 12, -3, 2, 4};	

System.out.println(taulukkoTekstiksi(luvut));
8,3,7,12,-3,2,4

vaihda

Tee staattinen metodi public static void vaihda(int[] taulukko, int vaihdettava1, int vaihdettava2), joka vaihtaa taulukon kahden alkion paikkaa annettujen indeksien vaihdettava1 ja vaihdettava2 perusteella.

int[] luvut = {8, 3, 7, 12, -3, 2, 4};	

System.out.println(taulukkoTekstiksi(luvut));

vaihda(luvut, 1, 0);
System.out.println(taulukkoTekstiksi(luvut));

vaihda(luvut, 0, 3);
System.out.println(taulukkoTekstiksi(luvut));
8,3,7,12,-3,2,4
3,8,7,12,-3,2,4
12,8,7,3,-3,2,4

pieninIndeksiAlkaen

Tee staattinen metodi public static int pieninIndeksiAlkaen(int[] taulukko, int alkaen), joka palauttaa taulukon pienimmän arvon sisältävän indeksin indeksistä alkaen taulukon loppuun asti tutkittaessa.

int[] luvut = {8, 3, 7, 12, -3, 2, 4};

System.out.println(pieninIndeksiAlkaen(luvut, 1));
System.out.println(pieninIndeksiAlkaen(luvut, 5));
System.out.println(pieninIndeksiAlkaen(luvut, 6));
4
5
6	

Järjestäminen

Tee staattinen metodi public static void jarjesta(int[] taulukko), joka järjestää minkä tahansa int[]-taulukon. Käytä toteutuksessa edellä tehtyjä staattisia metodeja.

Toteuta järjestäminen seuraavasti

  1. Tulosta taulukon tämänhetkinen tilanne.
  2. Hae taulukon pienin alkio.
  3. Vaihda pienin alkio taulukon ensimmäisen alkion kanssa.
    • Ensimmäinen alkio siirtyy taulukon pienimmän tilalle ja pienin taulukon alkuun.
  4. Tulosta taulukon tämänhetkinen tilanne.
  5. Vaihda taulukon alun kohtaa yhdellä eteenpäin ja mene kohtaan 1
    • Taulukon "kasvava" alkuosa on siis aina järjestyksessä

Testaa metodin toimintaa seuraavalla esimerkillä:

int[] luvut = {8, 3, 7, 12, -3, 2, 4};
jarjesta(luvut);

Ohjelman tulosteen tulisi olla seuraavanlainen

8,3,7,12,-3,2,4
-3,3,7,12,8,2,4

-3,3,7,12,8,2,4
-3,2,7,12,8,3,4

-3,2,7,12,8,3,4
-3,2,3,12,8,7,4

-3,2,3,12,8,7,4
-3,2,3,4,8,7,12

-3,2,3,4,8,7,12
-3,2,3,4,7,8,12

-3,2,3,4,7,8,12
-3,2,3,4,7,8,12

-3,2,3,4,7,8,12
-3,2,3,4,7,8,12

Binäärihaku

Tee staattinen metodi public static void jarjestaJaHae(int[] taulukko), joka järjestää luvut, kysyy käyttäjältä haettavaa lukua ja hakee suuruusjärjestyksessä olevasta taulukosta alkion käyttäen binäärihakua (eli puolitushakua).

Ohjelman suoritus näyttää seuraavalta:

Taulukon luvut ovat: -3,2,3,4,7,8,12

Anna haettava luku: 8

Luku 8 on taulukossa
Taulukon luvut ovat: -3,2,3,4,7,8,12

Anna haettava luku: 99

Luku 99 ei ole taulukossa

Opintopisteen VIP-lista

Opintopiste-nimiseen ravintolassa on joka viikko uusiutuva VIP lista. VIP-listalle pääsee soittamalla ravintolaan. Jos listalla tilaa, lisätään nimi listalle. Perjantaisin nimet annetaan portsarille, joka järjestää nimet ja varmistaa VIP-ihmisten oikeinkohtelun.

Tee kaikki tehtävät saman projektin sisään.

Ravintola

Tee luokka Ravintola, jonka konstruktorille annetaan parametrina VIP-listan koko. Ravintola tarjoaa metodit lisaaListalle(String nimi), joka palauttaa totuusarvon riippuen siitä mahtuiko listalle, annaLista() joka palauttaa tämän hetkisen VIP-listan, sekä tyhjennaLista(), joka tyhjentaa VIP-listan.

Metodin annaLista() tulee palauttaa taulukko, jossa on vain tämän hetkiset VIP-listalla olijat, eikä yhtään tyhjää viitettä. Testaa luokan Ravintola toteutusta seuraavalla pääohjelmalla.

public class Opintopiste {
  public static void main(String[] komentoriviParametrit) {
    Ravintola op = new Ravintola(2);
    tulostaVipit(op.annaLista());
    
    op.lisaaListalle("Matti L.");
    tulostaVipit(op.annaLista());
    

    op.lisaaListalle("Matti P.");
    tulostaVipit(op.annaLista());
    
    if(op.lisaaListalle("Matti V.")) {
      System.out.println("Matti V. mahtui listalle.");
    } 
    else {
      System.out.println("Matti V. ei mahtunut listalle.");
    }
    tulostaVipit(op.annaLista());
    
    // tyhjennetään VIP-lista
    op.tyhjennaLista();
    if(op.lisaaListalle("Matti V.")) {
      System.out.println("Matti V. mahtui listalle.");
    } 
    else {
      System.out.println("Matti V. ei mahtunut listalle.");
    }
    tulostaVipit(op.annaLista());
  }
  
  private static void tulostaVipit(String[] lista) {
    if(lista.length == 0) {
      System.out.println("VIP-lista on tyhjä.");
    } else {
      System.out.println("VIP-lista:");
      for(String nimi: lista) {
        System.out.println(nimi);
      }      
    }
    System.out.println();
  }
}

Opintopiste-ohjelman tulosteen tulee olla seuraavanlainen

VIP-lista on tyhjä.

VIP-lista:
Matti L.

VIP-lista:
Matti L.
Matti P.

Matti V. ei mahtunut listalle.
VIP-lista:
Matti L.
Matti P.

Matti V. mahtui listalle.
VIP-lista:
Matti V.

Portsari

Opintopiste-ravintolan portsari on hyvin käytännöllinen. Heti saatuaan VIP-listan hän järjestää sen nopeampaa tutkimista varten. Toteuta luokka Portsari, joka saa konstruktorinsa parametrina String[] - taulukon. Portsarilla on julkinen metodi annaLista(), joka palauttaa jo järjestetyn listan.

Toteuta portsarille myös metodi private void jarjestaLista(), jota käytetään Portsari-luokan konstruktorissa taulukon saamisen jälkeen. Toteuta myös apumetodit private int pieninIndeksiAlkaen(int alkaen) ja private void vaihda(int indeksiEka, int indeksiToka), joita jarjestaLista() käyttää. Voit käyttää Järjestäminen ja hakeminen-tehtävässä luotua järjestysalgoritmia lähtökohtana!

Testaa ohjelman toimintaa seuraavalla Opintopiste-ohjelmalla.

public class Opintopiste {
  public static void main(String[] komentoriviParametrit) {
    Ravintola op = new Ravintola(3);

    op.lisaaListalle("Matti V.");
    op.lisaaListalle("Matti L.");
    op.lisaaListalle("Matti P.");
    tulostaVipit(op.annaLista());
    
    Portsari portsari = new Portsari(op.annaLista());
    tulostaVipit(portsari.annaLista());
  }
  
  private static void tulostaVipit(String[] lista) {
    if(lista.length == 0) {
      System.out.println("VIP-lista on tyhjä.");
    } else {
      System.out.println("VIP-lista:");
      for(String nimi: lista) {
        System.out.println(nimi);
      }      
    }
    System.out.println();
  }
}

Ohjelman tulosteen tulee olla seuraavanlainen

VIP-lista:
Matti V.
Matti L.
Matti P.

VIP-lista:
Matti L.
Matti P.
Matti V.

VIP-listalla olon tarkistaminen

Lisää Portsari-luokkaan metodi public boolean onkoListalla(String nimi), joka palauttaa arvon true jos nimi on listalla, muulloin false. Toteuta hakeminen puolitushaun, eli binäärihaun, avulla.

Testaa ohjelman toimintaa seuraavalla Opintopiste-ohjelmalla.

public class Opintopiste {
  public static void main(String[] komentoriviParametrit) {
    Ravintola op = new Ravintola(3);

    op.lisaaListalle("Matti V.");
    op.lisaaListalle("Matti L.");
    op.lisaaListalle("Matti P.");
    
    Portsari portsari = new Portsari(op.annaLista());
    
    if(portsari.onkoListalla("Arto V.")) {
      System.out.println("Arto V. on listalla");
    }
    else {
      System.out.println("Arto V. ei ole listalla");
    }
    
    if(portsari.onkoListalla("Matti V.")) {
      System.out.println("Matti V. on listalla");
    }
    else {
      System.out.println("Matti V. ei ole listalla");
    }
    
    if(portsari.onkoListalla("Matti L.")) {
      System.out.println("Matti L. on listalla");
    }
    else {
      System.out.println("Matti L. ei ole listalla");
    }    
  }
}

Ohjelman tulostuksen tulee olla seuraavanlainen

Arto V. ei ole listalla
Matti V. on listalla
Matti L. on listalla

Listalle liittyminen ja pääohjelma

Muuta opintopiste-ohjelman toteutusta siten, että listalle lisätään ihmisiä kunnes annetaan tyhjä syöte. Sovitaan että opintopiste-ravintolan VIP-listalle mahtuu maksimissaan 50 ihmistä. Kun tyhjä syöte on annettu, lista annetaan portsarille, joka alkaa tarkastamaan ihmisten sisäänpääsyä. Seuraava tyhjä syöte lopettaa ohjelman.

Ohjelman tulostus voi olla esimerkiksi seuraavanlainen

Tervetuloa opintopiste-ravintolan VIP-palveluun.

Anna nimi: Matti V.
Matti V. mahtui listalle

Anna nimi: Matti P.
Matti P. mahtui listalle

Anna nimi: Matti L.
Matti L. mahtui listalle

Anna nimi:
Tyhjä syöte annettu, annetaan lista portsarille.

VIP-lista:
Matti L.
Matti P.
Matti V.

Ilta alkaa, tarkastetaan VIP-listalla olijoita.
Anna nimi: Arto V.
Arto V. ei ole VIP-listalla

Anna nimi: Matti P.
Matti P. on VIP-listalla

Anna nimi:
Tyhjä syöte annettu, ilta on ohi.
Kiitos!

Kivi-Paperi-Sakset

Tehdään kivi-paperi-sakset -peli. Kivi-paperi-sakset pelissä on tarkoitus arvata minkä kolmesta vaihtoehdosta (kivi, paperi tai sakset) vastustaja valitsee, ja valita itse vaihtoehto joka voittaa vastustajan valinnan.

Kivi voittaa sakset, sakset voittaa paperin ja paperi kiven.

Tuomari

Tuomari pitää kirjaa ensimmäisen ja toisen pelaajan pisteistä sekä tasapelien määrästä. Toteuta Tuomari-luokka, jolla on metodi kirjaaSiirto(String ekanSiirto, String tokanSiirto), joka kirjaa siirron. Siirrot ovat "k" kivelle, "p" paperille, sekä "s" saksille. Lisää luokalle myös toString()-metodi olion tilanteen tulostamista varten. Testaa Tuomari-luokan toteutusta seuraavalla Kps-ohjelmalla.

public class Kps {

  public static void main(String[] args) {
    Tuomari tuomari = new Tuomari();
    System.out.println(tuomari);
    System.out.println();
    
    tuomari.kirjaaSiirto("k", "p");
    System.out.println(tuomari);
    System.out.println();
    
    tuomari.kirjaaSiirto("k", "k");
    System.out.println(tuomari);
    System.out.println();
  }
}

Ohjelman Kps tulostus on seuraavanlainen:

Pelitilanne 0-0
Tasapelejä 0

Pelitilanne 0-1
Tasapelejä 0

Pelitilanne 0-1
Tasapelejä 1

Kahden pelaajan Kivi-Paperi-Sakset

Laajenna pääohjelmaa Kps siten, että se kysyy syötteitä kahdelta pelaajalta. Peli jatkuu niin pitkään kunnes jompikumpi pelaajista antaa syötteeksi muun syötteen kuin ("k", "p" tai "s"). Käytä tuomari-luokkaa tulostamaan pelitilanteen jokaisen kierroksen jälkeen.

Pääohjelman tulostuksen tulee olla seuraavanlainen:

Ensimmäisen pelaajan siirto: p
Toisen pelaajan siirto: p
Pelitilanne 0-0
Tasapelejä 1

Ensimmäisen pelaajan siirto: s 
Toisen pelaajan siirto: p
Pelitilanne 1-0
Tasapelejä 1

Ensimmäisen pelaajan siirto: s 
Toisen pelaajan siirto: k
Pelitilanne 1-1
Tasapelejä 1

Ensimmäisen pelaajan siirto: s
Toisen pelaajan siirto: riitti!

Kiitos!
Pelitilanne 1-1
Tasapelejä 1

Tietokone vastustajana

Tee luokka Tekoaly, jolla on metodi annaSiirto(). Voit itse päättää millä perusteella siirto annetaan.

Laajenna luokkaa Kps siten, että peli kysyy aluksi pelataanko tietokonetta vastaan. Jos pelaaja vastaa "k" tai "kyllä", peli on tietokonetta vastaan. Muuten pelataan toista pelaajaa vastaan.

Pääohjelman tulostus on seuraavanlainen jos valitaan pelaaja pelaajaa vastaan

Pelataanko tietokonetta vastaan: ei!

Ensimmäisen pelaajan siirto: p
Toisen pelaajan siirto: p
Pelitilanne 0-0
Tasapelejä 1

Ensimmäisen pelaajan siirto: s
Toisen pelaajan siirto: riitti!

Kiitos!
Pelitilanne 0-0
Tasapelejä 1

Jos valitaan vastustajaksi tietokone, tietokoneen valinnat tulostetaan myös.

Pelataanko tietokonetta vastaan: k

Ensimmäisen pelaajan siirto: p
Tietokone valitsi: k
Pelitilanne 1-0
Tasapelejä 0

Ensimmäisen pelaajan siirto: k
Tietokone valitsi: p
Pelitilanne 1-1
Tasapelejä 0

Ensimmäisen pelaajan siirto: riitti!

Kiitos!
Pelitilanne 1-1
Tasapelejä 0

Muistava tekoäly

Laajenna Tekoaly-luokkaa siten, että se pitää kirjaa vastustajan tekemistä siirroista. Metodi asetaSiirto(String siirto) asettaa vastustajan siirron tekoälyn muistiin. Toteuta tekoälyn muisti String - taulukkona, jonka koko voidaan määritellä Tekoaly-luokan konstruktorissa. Muistin täyttyessä tekoäly unohtaa aina vanhimman siirron.

Muuta myös Tekoaly-luokan annaSiirto-metodia siten, että se käyttää muistissa olevaa taulukkoa seuraavan siirron tekemiseen. Kannattaa verrata vastustajan viimeistä siirtoa aikaisempiin siirtoihin ja pohtia minkä verran mitäkin siirtoa on tehty aikaisemman siirron jälkeen.

Esimerkiksi, jos vastustajan viimeisin nähty siirto on k, ja muistissa on ppkspkkspk, on vastustaja pelannut kiven jälkeen kerran kiven ja kaksi kertaa sakset. Tällöin tekoälyn kannattaa pelata kivi.

Fibonacci

Fibonacci

Fibonaccin lukujonon ensimmäiset kolme arvoa ovat 0, 1 ja 1. Tämän jälkeen seuraavat Fibonaccin luvut saadaan laskemalla kaksi edellistä lukua yhteen. Neljäs Fibonaccin luku on 1+1 eli 2, viides Fibonaccin luku on kolmas plus neljäs eli 1+2 eli 3. Kuudes Fibonaccin luku on jälleen kahden edellisen, eli viidennen ja neljännen summa, sen arvo on 2+3 eli 5, jne...

Tee stattinen metodi public static int fibo(int monesko), joka palauttaa parametrin monesko määrittelemän Fibonaccin luvun.

Ennen kuin rupeat ohjelmoimaan, mieti kynällä ja paperilla millä strategialla ratkaiset ongelman.

Testaa metodin toimintaa seuraavalla ohjelmalla.

public class Fibonacci {
  public static void main(String[] args) {
    System.out.println("Seitsemäs fibonaccin luku on: " + fibo(7));
    System.out.println("Yhdestoista fibonaccin luku on: " + fibo(11));
    System.out.println("Kolmaskymmeneskolmas fibonaccin luku on: " + fibo(33));
  }

  .. metodi fibonaccin luvun laskemiseen
}

Ohjelman tulosteen tulisi olla seuraavanlainen

Seitsemäs fibonaccin luku on: 8
Yhdestoista fibonaccin luku on: 55
Kolmaskymmeneskolmas fibonaccin luku on: 2178309