Advertisement
Guest User

Untitled

a guest
Nov 11th, 2014
133
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scala 6.26 KB | None | 0 0
  1. package o1.peeveli
  2.  
  3. import Tilanne.Piilossa
  4. import scala.util.Random
  5.  
  6.  
  7. /**
  8.  * Kukin luokan `Tilanne` ilmentymä kuvaa yhtä Peeveli-hirsipuupelin pelitilannetta:
  9.  * Minkä näköinen on arvaajalle näytettävä (osin paljastettu) piilosana? Montako arvausta
  10.  * on jäljellä? Mitä arvauksia on jo tehty? Sekä huijaavalle Peevelille tärkeä tieto: Mitkä
  11.  * kaikki sanat ovat edelleen mahdollisia vastauksia?  
  12.  *
  13.  * Peeveli-pelin toiminta on selitetty tarkemmin kurssimateriaalin luvussa 9.3.
  14.  *
  15.  * Vaikka pelin aikana pelitilanne vaihteleekin, on kukin `Tilanne`-olio tilaltaan täysin
  16.  * muuttumaton. Uusi pelitilanne muodostetaan uutena `Tilanne`-oliona kutsumalla
  17.  * vanhalle tilanteelle `arvaa`-metodia.
  18.  *
  19.  * @param vaariaSallitaan se määrä vääriä arvauksia, joka vielä sallitaan ennen pelin päättymistä.
  20.  *                        Negatiivinen luku tarkoittaa, että peli on päättynyt.
  21.  * @param arvatut         merkkijono, joka sisältää järjestyksessä kaikki toistaiseksi arvatut merkit
  22.  * @param piilosana       merkkijono, jossa on piilosanan arvaajalle näkyvä muoto. Pelin alussa piilosanassa on
  23.  *                        vain piilossa olevia merkkejä (ks. [[Tilanne.Piilossa]]), mutta merkkejä paljastuu vähitellen.
  24.  * @param sopivatSanat    kaikki ne käytetyn sanaston sanat, jotka sopivat yhteen `piilosana`-parametrin kanssa eli
  25.  *                        ovat mahdollisia oikeita vastauksia    
  26.  */
  27. class Tilanne(val vaariaSallitaan: Int, val arvatut: String, val piilosana: String, val sopivatSanat: Vector[String])  {
  28.  
  29.  
  30.   /**
  31.    * Luo uuden `Tilanne`-olion, joka kuvaa juuri alkaneen uuden `Peeveli`-pelin tilaa.
  32.    * Pelin alkaessa koko piilosana on vielä piilossa ja kaikki annetun sanaston sopivan mittaiset sanat
  33.    * ovat mahdollisia oikeita ratkaisuja.
  34.    *
  35.    * Lisätieto opiskelijoille: Huomaa, miten tämä '''toinen konstruktori''' on määritelty annetussa ohjelmakoodissa.
  36.    * Tällä tavoin voidaan määritellä vaihtoehtoinen tapa luoda `Tilanne`-olio sen "oletustavan" lisäksi, joka
  37.    * on määritelty luokan otsikkorivillä. Voidaan siis luoda tilanneolio joko käskyllä `new Tilanne(arvauksia, arvatut,
  38.    * piilosana, sopivat)` (oletustapa) tai käskyllä `new Tilanne(arvauksia, pituus, sanasto)`.
  39.    *
  40.    * @param arvauksiaKaytettavissa se määrä vääriä arvauksia, joka yhteensä sallitaan ennen pelin päättymistä
  41.    * @param pituus                 uuden piilosanan pituus
  42.    * @param sanasto                sanasto, jonka `pituus`-mittaiset sanat ovat mahdollisia oikeita vastauksia
  43.    */
  44.   def this(arvauksiaKaytettavissa: Int, pituus: Int, sanasto: Vector[String]) = {
  45.     // Seuraava tarkoittaa: luo olio käyttäen "oletustapaa" ja antaen seuraavat konstruktoriparametrit:
  46.     this(arvauksiaKaytettavissa, "", Piilossa.toString * pituus, sanasto.map( _.toUpperCase ))
  47.   }
  48.  
  49.  
  50.   /**
  51.    * Palauttaa piilosanan pituuden.
  52.    */
  53.   def sananPituus = this.piilosana.length
  54.  
  55.  
  56.   /**
  57.    * Palauttaa niiden käytetystä sanastosta löytyvien sanojen lukumäärän, jotka ovat (edelleen) mahdollisia
  58.    * ratkaisuja piilosanaan.
  59.    */
  60.   def sopiviaSanojaJaljella = this.sopivatSanat.size
  61.  
  62.  
  63.   /**
  64.    * Palauttaa `true` jos arvaaja on arvannut väärin jo enemmän kertoja kuin sallittiin ja on siis
  65.    * hävinnyt pelin; palauttaa `false`, jos näin ei ole.
  66.    */
  67.   def onTappio = this.vaariaSallitaan < 0;
  68.  
  69.  
  70.   /**
  71.    * Palauttaa `true`, jos arvaaja on voittanut pelin eli ei ole arvannut liian monta kertaa väärin ja
  72.    * kaikki piilosanan kirjaimet ovat näkyvissä; muutoin palauttaa `false`.
  73.    */
  74.   def onVoitto = !piilosana.contains(Piilossa);
  75.  
  76.  
  77.   /**
  78.    * Palauttaa sanan, jota Peeveli väittää oikeaksi vastaukseksi pelin päättyessä arvaajan tappioon.
  79.    * Sana valitaan satunnaisesti; eri kutsukerroilla saadaan yleensä eri sana.
  80.    */
  81.   def oikeaVastaus() = {
  82.     this.sopivatSanat(Random.nextInt(this.sopivatSanat.size))
  83.   }
  84.  
  85.  
  86.   /**
  87.    * Palauttaa sellaisen version piilosanasta, josta on paljastettu osoitetut merkit.
  88.    * Esimerkiksi jos piilosana on `"K___A"` ja parametrimerkkijono on `"__SS_"`, palauttaa
  89.    * `"K_SSA"`.
  90.    */
  91.   private def paljasta(paljastettavat: String) = {
  92.     var uusiPiilosana = ""                                
  93.     for (indeksi <- this.piilosana.indices) {
  94.       if (paljastettavat(indeksi) != Piilossa) {
  95.         uusiPiilosana += paljastettavat(indeksi)    
  96.       } else {
  97.         uusiPiilosana += this.piilosana(indeksi)
  98.       }
  99.     }
  100.     uusiPiilosana
  101.   }
  102.  
  103.  
  104.   /**
  105.    * Palauttaa uuden pelitilanteen, joka seuraa nykyisestä, kun arvaaja arvaa annetun merkin.
  106.    * Uusi pelitilanne valitaan periaatteella, joka on selostettu kurssimateriaalin luvussa 9.3.
  107.    * Uudessa tilanteessa on ainakin yksi tehty arvaus enemmän kuin nykyisessä; lisäksi siinä saattaa
  108.    * olla enemmän näkyviä merkkejä piilosanassa, vähemmän vääriä arvauksia jäljellä ja/tai vähemmän
  109.    * mahdollisia oikeita vastauksia.
  110.    *
  111.    * @param arvaus viimeksi arvattu merkki; saa olla iso tai pieni kirjain, mutta tulkitaan aina isoksi
  112.    * @return uusi pelitilanne  
  113.    */
  114.   def arvaa(arvaus: Char) = {
  115.    
  116.     val remainingWords = jaljella(arvaus.toUpper);
  117.     val hiddenString = paljasta(remainingWords._1)
  118.     val noLettersFound = remainingWords._1.forall(_ == Piilossa);
  119.    
  120.     new Tilanne(this.vaariaSallitaan - (if (noLettersFound) 1 else 0), this.arvatut + arvaus.toUpper, hiddenString, remainingWords._2)
  121.    
  122.   }
  123.  
  124.   private def jaljella(arvaus:Char) = {
  125.     val grouped = sopivatSanat.groupBy(_.map(char => if (char.toUpper != arvaus) Piilossa else arvaus));
  126.     val sorted = grouped.maxBy(pair => pair._2.size*10 - pair._1.count(_ == arvaus));
  127.    
  128.     sorted;
  129.   }
  130.  
  131.   override def toString =
  132.     this.piilosana + ", " +
  133.     "vääriä sallitaan vielä: " + this.vaariaSallitaan + ", " +
  134.     "arvatut: " + (if (this.arvatut.isEmpty) "ei ole" else this.arvatut) + ", " +
  135.     "vaihtoehtoja: " + this.sopiviaSanojaJaljella
  136.  
  137. }
  138.  
  139.  
  140. /**
  141.  * Tämä `Tilanne`-luokan kumppaniolio vain tarjoaa yhden vakioarvon.
  142.  *
  143.  * @see [[Tilanne]]-luokka
  144.  */
  145. object Tilanne {
  146.  
  147.   /** merkki, jota käytetään piilossa olevien kirjainten merkitsemiseen Peeveli-pelissä */
  148.   val Piilossa = '_'
  149.    
  150. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement