Ohjelmoinnin perusteiden 5. harjoitusten malliratkaisut / 30.9.2008 Anne-Marie Grönroos 20. Laiva public class Laiva { //vakioita private static final double MINIMINOPEUS = 0.0; private static final double MAKSIMINOPEUS = 40.0; //sisäiset muuttujat private int suunta; private double nopeus; //konstruktorit public Laiva(){ this.suunta = 0; this.nopeus = 0.0; } public Laiva(double nopeus){ this.suunta = 0; this.asetaNopeus(nopeus); //käytetään nopeuden asettamiseen luokan omaa metodia, } //joka tarkistaa arvon oikeellisuuden public Laiva (int suunta){ this.nopeus = 0.0; if (suunta < 0) suunta = 0; else if (suunta > 359) suunta = 359; this.suunta = suunta; } public Laiva (double nopeus, int suunta){ this.asetaNopeus(nopeus); if (suunta < 0) suunta = 0; else if (suunta > 359) suunta = 359; this.suunta = suunta; } //aksessorit public int mikäSuunta(){ return this.suunta; } public double mikäNopeus(){ return this.nopeus; } public void styyrpuuriin(){ this.suunta++; if (this.suunta > 359) this.suunta = 0; } public void paapuuriin(){ this.suunta--; if (this.suunta < 0) this.suunta = 359; } public void asetaNopeus(double nopeus){ if (nopeus < MINIMINOPEUS) nopeus = MINIMINOPEUS; else if (nopeus > MAKSIMINOPEUS) nopeus = MAKSIMINOPEUS; this.nopeus = nopeus; } public String toString(){ return "Laivan suunta on " + this.suunta + " astetta ja nopeus " + this.nopeus + " solmua."; } } 21. Kippari import java.util.Scanner; public class Kippari { private static Scanner lukija = new Scanner(System.in); public static void main(String[] args) { Laiva purtilo = new Laiva(); // Tulostetaan ohjeet System.out.println("Tervetuloa laivaan, kapteeni!"); System.out.println("Käytä laivan ohjaamiseen seuraavia komentoja:"); System.out.println("v - käänny vasemmalle"); System.out.println("o - käänny oikealle"); System.out.println("n - muuta nopeutta"); System.out.println("Muut syötteet lopettavat\n"); boolean jatketaanko = true; do{ System.out.println(purtilo); System.out.println("Komentonne, söör?"); String komento = lukija.next(); if (komento.equals("v")){ System.out.println("Paapuuriin ahoi!"); System.out.print("Montako astetta: "); int asteet = lukija.nextInt(); for (int i = 0; i < asteet; i++) purtilo.paapuuriin(); } else if (komento.equals("o")){ System.out.println("Styyrpuuriin ahoi!"); System.out.print("Montako astetta: "); int turn = lukija.nextInt(); for (int i = 0; i < turn; i++) purtilo.styyrpuuriin(); } else if (komento.equals("n")){ System.out.println("Muutetaan nopeutta"); System.out.print("Uusi nopeus: "); double nopeus = lukija.nextDouble(); purtilo.asetaNopeus(nopeus); } else { jatketaanko = false; } } while(jatketaanko); System.out.println("Näkemiin, kapu!"); } } 22. Viljavarasto Muistin virkistämiseksi Pikkuvarasto-luokka (kurssimateriaalista): public class Pikkuvarasto { // toteutuksen tietorakenteet: private double määrä; // tuotteen määrä >= 0 private String tuote; // tuotteen nimi // ----- konstruktorit: ----------- public Pikkuvarasto() { this.määrä = 0.0; this.tuote = "(nimetön)"; } public Pikkuvarasto(double määrä, String tuote) { this.tuote = tuote; if (määrä > 0) this.määrä = määrä; else this.määrä = 0.0; } // ----- aksessorit: -------- public double paljonkoOn() { return this.määrä; } public String mikäNimi() { return this.tuote; } public void vieVarastoon(double paljonko) { // vain >0 kelpaa if (paljonko > 0) this.määrä += paljonko; } public double otaVarastosta(double paljonko) { // vain >0 kelpaa if (paljonko <= 0) return 0; if (paljonko <= this.määrä) { // vähennetään varastosta this.määrä -= paljonko; // koko parametri return paljonko; } else { // annetaan mitä voidaan! paljonko = this.määrä; this.määrä = 0; return paljonko; } } // ------ muita työkaluja Pikkuvarasto-olioiden käsittelyyn: ------- public String toString() { // varastotilanne merkkijonona return "("+this.tuote+": "+this.määrä+")"; } public Pikkuvarasto summa(Pikkuvarasto toinen) { return new Pikkuvarasto(this.määrä + toinen.paljonkoOn(), this.tuote + toinen.mikäNimi()); } } /* HUOM! Viljavarasto vaatii toimiakseen Pikkuvaraston.*/ public class Viljavarasto { private Pikkuvarasto siilo1, siilo2; private double siilo1vetoisuus, siilo2vetoisuus; public Viljavarasto(double ekaSiilo, double tokaSiilo) { this.siilo1 = new Pikkuvarasto(0, "Vilja"); this.siilo2 = new Pikkuvarasto(0, "Vilja"); this.siilo1vetoisuus = ekaSiilo; this.siilo2vetoisuus = tokaSiilo; } public double ekassaOn() { return this.siilo1.paljonkoOn(); } public double tokassaOn() { return this.siilo2.paljonkoOn(); } public boolean siirräViljaa(double määrä, boolean ekasta) { if (määrä < 0) return false; if (ekasta) { // jos siilo1:ssä on tarpeeksi, ja jos siilo2:ssa on tilaa if ((ekassaOn() >= määrä) && (this.siilo2vetoisuus - tokassaOn() >= määrä)) { this.siilo1.otaVarastosta(määrä); this.siilo2.vieVarastoon(määrä); return true; } } else { // jos siilo2:ssa on tarpeeksi, ja jos siilo1:ssä on tilaa if ((tokassaOn() >= määrä) && (this.siilo1vetoisuus - ekassaOn() >= määrä)) { this.siilo2.otaVarastosta(määrä); this.siilo1.vieVarastoon(määrä); return true; } } return false; } public boolean lisääViljaa(double määrä) { if ((määrä > (this.siilo1vetoisuus - ekassaOn())) || (määrä < 0)) return false; this.siilo1.vieVarastoon(määrä); return true; } public double otaViljaa(double määrä) { return this.siilo1.otaVarastosta(määrä); } public void hiirivahinko(double vakavuus) { if (vakavuus < 0) return; this.siilo1.otaVarastosta(ekassaOn() * vakavuus / 100); this.siilo2.otaVarastosta(tokassaOn() * vakavuus / 100); } public String toString() { String s = "\nsiilo1 (vetoisuus " + this.siilo1vetoisuus + ")\n * Sisältö: " + this.siilo1; s += "\nsiilo2 (vetoisuus " + this.siilo2vetoisuus + ")\n * Sisältö: " + this.siilo2; return s; } public static void main(String[] args) { Viljavarasto v = new Viljavarasto(1000, 100); System.out.println(v); v.lisääViljaa(1500); System.out.println(v); v.lisääViljaa(500); System.out.println(v); v.siirräViljaa(300, true); System.out.println(v); v.siirräViljaa(80, true); System.out.println(v); v.otaViljaa(5); System.out.println(v); double hiiriprosentti = 10; v.hiirivahinko(hiiriprosentti); System.out.println(v); } } Viljavaraston käyttöön tarkoituksenmukaisempi Siilo-luokka saattaisi näyttää vaikkapa tältä (luokan kirjoittamista ei tehtävässä vaadittu): public class Siilo { private double määrä; // viljan määrä >= 0 private double vetoisuus; // siilon vetoisuus public Siilo() { this(0.0, 10); } public Siilo(double vetoisuus, double määrä) { if (vetoisuus > 0) this.vetoisuus = vetoisuus; else this.vetoisuus = 0.0; if (määrä > 0) this.määrä = määrä; else this.määrä = 0.0; if (this.määrä > this.vetoisuus) this.määrä = this.vetoisuus; } public double annaMäärä() { return this.määrä; } public double annaVetoisuus() { return this.vetoisuus; } public boolean lisää(double paljonko) { if (paljonko < 0) return false; if (this.määrä + paljonko > this.vetoisuus) return false; else this.määrä += paljonko; return true; } public boolean siirrä(Siilo siilosta, double paljonko) { if (siilosta.annaMäärä() <= paljonko) return false; if (this.vetoisuus - this.määrä <= paljonko) return false; this.määrä += siilosta.ota(paljonko); return true; } public double ota(double paljonko) { if (paljonko <= 0) return 0; if (paljonko <= this.määrä) { this.määrä -= paljonko; return paljonko; } else { paljonko = this.määrä; this.määrä = 0; return paljonko; } } public String toString() { return "(vetoisuus:" + this.vetoisuus + ", määrä:" + this.määrä + ")"; } } Siiloa käyttävä, paranneltu Viljavarasto voisi puolestaan olla jotakin tämän näköistä: public class Viljavarasto { private Siilo siilo1, siilo2; public Viljavarasto(double ekaSiilo, double tokaSiilo) { siilo1 = new Siilo(ekaSiilo, 0); siilo2 = new Siilo(tokaSiilo, 0); } public double ekassaOn() { return siilo1.annaMäärä(); } public double tokassaOn() { return siilo2.annaMäärä(); } public boolean siirräViljaa(double määrä, boolean ekasta) { if (ekasta) return siilo2.siirrä(siilo1, määrä); else return siilo1.siirrä(siilo2, määrä); } public boolean lisääViljaa(double määrä) { return siilo1.lisää(määrä); } public double otaViljaa(double määrä) { return siilo1.ota(määrä); } public void hiirivahinko(double vakavuus) { if (vakavuus < 0) return; siilo1.ota(ekassaOn() * vakavuus / 100); siilo2.ota(tokassaOn() * vakavuus / 100); } public String toString() { return "\nSiilo1: " + siilo1 + "\nSiilo2: " + siilo2; } } Huomionarvoista on, että uuden Viljavaraston käyttäjälle näkyvä toteutus ("rajapinta") on täsmälleen sama kuin vanhassa Viljavarastossa. Luokan käyttäjältä ei siis vaadita mitään toimenpiteitä, vaikka Viljavaraston toteutus muuttuisikin. 23. Kyselijä import java.util.Scanner; public class Kyselija { private static Scanner lukija = new Scanner(System.in); private String kysymyksenAlku, kysymyksenLoppu; private boolean isotJaPienetSamaistettu; private int kysymyksiä, oikein; public Kyselija(String kysymyksenAlku, String kysymyksenLoppu) { this.kysymyksenAlku = kysymyksenAlku; this.kysymyksenLoppu = kysymyksenLoppu; this.isotJaPienetSamaistettu = false; this.kysymyksiä = this.oikein = 0; } /** * Vastaus hyväksytään oikeaksi, vaikka se sisältäisi ylimääräisiä välilyöntejä alussa tai lopussa. * Metodi palauttaa arvonaan true, jos vastaus on oikein, muuten false. * Myös onnistumisesta metodi raportoi */ public boolean kysy(String kysytty, String oikeaVastaus) { System.out.println(this.kysymyksenAlku + kysytty + " " + this.kysymyksenLoppu); String vastaus = lukija.nextLine(); vastaus = vastaus.trim(); //Poistetaan vastauksesta ylimääräiset välilyönnit this.kysymyksiä++; // Tarkistetaan vastaus if ((this.isotJaPienetSamaistettu && vastaus.equalsIgnoreCase(oikeaVastaus)) || (!this.isotJaPienetSamaistettu && vastaus.equals(oikeaVastaus))) { System.out.println("OIKEIN!"); this.oikein++; return true; } else { System.out.println("Väärin! Oikea vastaus on \"" + oikeaVastaus + "\"."); return false; } } /** * Jos metodia on kutsuttu viimeksi parametrilla true, isot ja pienet kirjaimet samaistetaan, * jos false, niitä ei samaisteta. * Oletusarvoisesti on samaistaIsotJaPienet(false). * Asiantilaa voi tarvittaessa siis muuttaa vaikka kysymyksittäin */ public void samaistaIsotJaPienet(boolean samaista) { this.isotJaPienetSamaistettu = samaista; } /** * palauttaa tähän mennessä kysyttyjen kysymysten lukumäärän */ public int montakoKysymystä() { return this.kysymyksiä; } /** * palauttaa oikeiden vastausten lukumäärän tähän mennessä */ public int montakoOikein() { return this.oikein; } public static void main(String[] args) { Kyselija kilpa = new Kyselija("Mitä on italian ", "suomeksi?"); kilpa.samaistaIsotJaPienet(true); boolean oikein; oikein = kilpa.kysy("tutti", "kaikki"); if (oikein) System.out.println("Hienoa, hyvä alku!"); kilpa.kysy("ferro", "rauta"); // Arvon palauttavaa metodia voi // kutsua myös arvoa käyttämättä! oikein = kilpa.kysy("matto", "hullu"); if (!oikein) System.out.println("No mitäs nyt?"); System.out.println("Kysymyksiä oli " + kilpa.montakoKysymystä() + ", oikeita vastauksia " + kilpa.montakoOikein() + "."); } }