Miinantallaaja¶
Keltainen valtio on aloittanut sotatoimet isänmaatamme kohtaan hyökäten armottomalla miinoituksella. Nohevana pioneerijohtajana tehtäväsi on kouluttaa osaavia miinantal... miinanpurkajia. Tähän tarvitaan luonnollisesti ninjatason ohjelmointitaitoja. Kyllä. Tehtävänäsi on toteuttaa eeppinen miinanpurkusimulaattori, joka tunnetaan myös nimellä miinaharava.
Pelin aloitus¶
Miinakenttä on suorakulmion muotoinen ja se muodostaa kaksiulotteisen ruudukon, jonka leveys ja pituus ovat pelaajan mielivaltaisesti valittavissa. Miinakentän ruudut ovat alussa tutkimattomia ja satunnaisesti arvottuihin ruutuihin on piilotettu miina. Miinojen määrä on myös pelaajan valittavissa. Muita ruututyyppejä ovat numeroruutu, joka ilmoittaa ruutua ympäröivien miinojen lukumäärän, sekä tyhjä ruutu.
Pelin kulku¶
Pelaaja voi valita ruudukosta yhden leveys-pituus-koordinaatin kerrallaan. Valittu koordinaatti aukaistaan eli pelaajalle näytetään ruudun sisältö. Jos valitussa ruudussa oli miina, pelaaja häviää ja peli päättyy. Muuten menetellään seuraavasti:
- Jos valitun ruudun viereisissä (myös viistosti!) ruuduissa on vähintään yksi piiloitettu miina, kyseessä on numeroruutu ja sen kohdalla näytetään ympäröivien miinojen lukumäärä.
- Jos valitun ruudun viereisissä ruuduissa ei ole miinoja, aukaistaan kaikki ympäröivät ja niitä ympäröivät jne. ruudut joka suuntaan niin pitkälle, että saavutetaan miinakentän raja tai ensimmäinen numeroruutu, joka myös aukaistaan.
Pelin päättyminen¶
Peli voi päättyä kahdella tavalla:
- Pelaaja häviää avatessaan ruudun, johon on piilotettu miina.
- Pelaaja voittaa, kun kaikki miinattomat ruudut on aukaistu kentältä.
Suunnittelupöydälle kannattaa ottaa vaikkapa kuva pelistä, josta voisi lähteä liikkeelle. Taitaa verkon syövereistä löytyä joku selaimessa pelattava versiokin. Alla olevista ohjeista voit tarkistaa, saatko lopputyösi hyväksyttävästi suoritettua. Eli vaikka kuinka tekisi mieli rynnätä jo koodaamaan, kannattanee kuitenkin lukaista tämä sivu loppuun.
Toimiva toteutus¶
Tärkeimpänä vaatimuksena, joka erottaa hyväksytyn ja hylätyn työn toisistaan on se, että hyväksyttäväksi kelpaavassa työssä täytyy pystyä pelaamaan Miinaharavaa, eli pelin tulee toimia vähintään siinä määrin, että työn tarkastaja tietää pelaavansa juuri sitä peliä, joka tehtävänannossa on määritelty. Seuraavien tarkempien vaatimusten täyttämisen tarkoitus on osoittaa, että opiskelija on oppinut kurssilla käsitellyt asiat.
- Pelitilanne esitetään pelaajalle ymmärrettävässä muodossa graafisesti
- Pelaaja pystyy tekemään siirtoja hiirellä; siirtojen sääntöjenmukaisuus tarkistetaan ja laittomat siirrot estetään
- Peli päättyy kun päättymisehto täyttyy
- Peli tallentaa tilastoja pelatuista peleistä: vähintään pelin ajankohdan (päivämäärä + kellonaika), keston minuuteissa, keston vuoroissa ja lopputuloksen (voitto tai häviö, kentän koko ja miinojen lukumäärä). Tilastojen kirjoitus ja lukeminen on toteuttu itse (ts. ei käytetä mitään valmista ratkaisua kuten SQLite tai Pickle)
- Pelissä on alkuvalikko, josta voi valita uuden pelin, lopettamisen ja tilastojen katsomisen - huom! valikko voi olla tekstipohjainen, ainoastaan itse peli-ikkunan tulee olla graafinen.
Grafiikka¶
Peligrafiikkaa varten olemme toteuttaneet pienen kirjaston, jonka avulla grafiikan piirto peli-ikkunaan onnistuu jotakuinkin samoilla keinoilla kuin muutkin asiat kurssilla tähän asti - kutsumalla siis funktiota. Kirjastoa ei ole pakko käyttää, mutta pelissä on oltava vastaava graafinen käyttöliittymä jollain tavalla toteutettuna - terminaaliharavien valtakausi on ohi! Kirjastomoduulissa on varsin kattavat dokumentaatiomerkkijonot, jotka kertovat sen käytöstä. Lisää ohjeistusta on koottu alle.
Käyttöönotto¶
Lataa kirjasto yllä olevasta linkistä. Lisäksi tarvitset grafiikkaa varten kuvatiedostot, jotka voit napata täältä, tai halutessasi voit ladata yltä skriptin, joka generoi kuvat (vaatii PyCairon asentamisen). Kuvat laitetaan oletuksena spritet-nimiseen kansioon projektikansiosi sisälle. Sinun tulee myös asentaa Pyglet-kirjasto, koska pikkuinen kirjastomme on sen päälle toteutettu. Pyglet on muutenkin ihan näppärä kirjasto, jos haluaa tehdä Pythonilla 2D-pelejä.
Pelikirjastojen 101¶
Siinä missä tähän asti ohjelman käyttöliittymäsilmukka on koodattu kokonaan itse (yleensä
while True
:lla), pelikirjastoissa on tyypillisesti konepellin alle piilotettuna huomattavasti monimutkaisempi pääsilmukka. Se on piilotettu, jotta sillä ei tarvitse vaivata päätään. Kirjastoa käytettäessä määritellään tyypillisesti käsittelijäfunktioita, joita pääsilmukka kutsuu, kun funktioon liitetty asia tapahtuu. Esimerkiksi hiiren klikkaukseen voidaan kytkeä käsittelijäfunktio. Jos näin tehdään, tuota funktiota kutsutaan aina, kun käyttäjä painaa hiiren nappia. Toinen hyvin yleinen käsittelijä on grafiikan piirtofunktio, jota kutsutaan aina, kun ruudulla oleva näkymä pitää päivittää. Pelikoodissasi et siis määrittele omaa pääsilmukkaa, vaan toteutat tarvittavat käsittelijäfunktiot. Käsittelijäfunktiot tulee erikseen kytkeä tapahtumiin. Tämä onnistuu kirjastossa olevilla funktioilla (muotoa aseta_joku_kasittelija). Näiden funktioiden dokumenttimerkkijonoista ilmenee millainen käsittelijäfunktio niihin tulee liittää. Työjärjestys grafiikan piirtämisessä annetulla kirjastolla on kaiken kaikkiaan seuraavanlainen:
- lataa peligrafiikat
- luo peli-ikkuna
- määrittele ja rekisteröi käsittelijäfunktiot
- käynnistä peli
Tästä eteenpäin peli pyörii käsittelijäfunktioiden varassa. Grafiikan piirtämisestä löydät hyvin yksinkertaisen esimerkin kirjastomoduulin lopusta. Siellä on koodinpätkä, joka piirtää kaikki ruutugrafiikat satunnaisessa järjestyksessä ikkunaan yhdelle riville.
Koodin suunnittelussa on syytä huomoida, että koska käsittelijäfunktioita kutsuu ns. konepellin alla pyörivä pääsilmukka, et pysty vaikuttamaan siihen mitä argumentteja niille annetaan. Erityisesti pelin tila (kuten kenttä) täytyy hankkia käsittelijöiden tietoon jotain muuta kautta. Suositeltava lähestymistapa on tehdä tilaa varten sanakirja pääohjelmassa. Pääohjelmassa määriteltyä sanakirjaa voidaan muuntuvan luonteensa ansiosta lukea sekä muokata kaikissa funktioissa.
Yhteistyö¶
Me tykkäämme tällä kurssilla yhteistyöstä. Näitä viikottaisia kivoja pikku tehtäväpakettejakin on värkkäilty monen assistentin voimavaroilla. Yhdessä näitä ongelmia on varmaan myös kivempi ratkoa. Kaverilla voi olla parempi käsitys jostain asiasta, ja muutenkin kaksi silmäparia on tehokkaampi virheitä etsiessä. Usein oman virheensä tajuaa jo siinä vaiheessa kun alkaa kaverille avautumaan siitä, että ohjelma ei toimi. Niinpä siis emme missään nimessä halua ryöstää teiltä tätä yhdessä tekemisen riemua ja kannustammekin kysymään assistenttien lisäksi apua myös kavereilta.
Tällä kurssilla on kuitenkin vaatimus, että jokainen opiskelija oppisi ohjelmoimaan ihan itse. Tämä on hyvä pitää mielessä kun värkkäilee koodia kaverin tai useamman kanssa. Mitään ei kannata naputella omaan koodiin ilman, että tajuaa, mitä siinä tapahtuu. Vaadi kavereiltasi selitystä, jos et ymmärrä saamaasi neuvoa! Koodin muilta kopioinnissa on semmoinen ikävä puoli, että kaikki häviävät. Se joka kopioi, ei itse viisastu kopioimastaan millään tavalla, ja se, jolta kopioidaan, ei pääse syventämään omaa ymmärrystään asiasta muotoilemalla sen ymmärrettävään muotoon.
Näitä tapauksia sattuu kuitenkin vuosittain, joten pelkkien kauniiden ajatusten lisäksi kurssilla on selkeät ja helposti ymmärrettävä pelisäännöt yhteistyötä koskien. Noudatahan näitä sääntöjä niin vältyt ongelmilta. Ongelmat yleensä tarkoittavat, että suoritusmerkintääsi saatetaan pantata jonnekin hamaan tulevaisuuteen kun asiaa selvitetään. Pahimmassa tapauksessa voi käydä niinkin ikävästi, että joudut uusimaan kurssin. Säännöt voi tiivistää muutamaan kohtaan:
- Älä kopioi koodia mistään tai keneltäkään ja pidä huoli siitä että ymmärrät aina kaiken koodin mitä kirjoitat
- Ilmoita aina kenen kanssa olet tehnyt yhteistyötä. Tiedostotehtävissä on tätä varten oma kenttänsä
- Jos otat mallia jostain muualta (Internet), merkitse kommenteilla koodin yläpuolelle mistä se on otettu
Lopputyötä voi tehdä yhdessä kaverin tai useamman kanssa. Tällöin on kuitenkin pidettävä huoli siitä, että kaikki tekijät ovat kartalla siitä, mitä ohjelmassa tapahtuu ja osallistuvat sen tekemiseen. Kannattaa huomioida, että lopputyön tarkastamisessa ja katselmoinnissa keskitytään siihen, miten hyvin sinä itse osaat ohjelmoida ja miten se tulee esiin. Maailman paraskaan koodi ei mene läpi, jos se on kokonaan jonkun muun tekemä.
Työn hyväksyminen¶
Hyväksyttävään työhön vaaditaan ohjelma, joka toteuttaa tällä sivulla esitetyt vaatimukset. Ellei koodisi ole aivan luokattoman huonoa, tyypillisesti kaikki täysin toimivat ohjelmat hyväksytään. Puutteiden paikkaamiseen on mahdollisuus kunhan työn ensimmäinen versio on palautettu ajoissa. Työn palautuksen lisäksi hyväksyttyyn suoritukseen kuuluu 15 minuutin keskustelu assistentin kanssa. Tähän keskusteluun kuuluu, että assistentti esittää kysymyksiä koodistasi. Mikäli et pysty vastaamaan kaikkiin kysymyksiin tyydyttävästi, saat kotitehtäväksi opetella koodisi toiminnan tarkemmin ja joudut varaamaan uuden keskusteluajan. Säännöt vaativat meitä varmistamaan, että opiskelijat ovat tehneet oman työnsä. Kyse on kuitenkin myös tärkeämmästä periaatteesta: ohjelmoijan ei tulisi koskaan lähettää eteenpäin koodia jota ei itse ymmärrä. Ohjelmoija on aina vastuussa omasta koodistaan.
Koodin laatu¶
Kurssilla on pyritty opettamaan tapoja tuottaa hyvää koodia, ja sen odotetaan näkyvän myös lopputyössä. Ihan mikä tahansa toimiva toteutus ei vielä takaa läpipääsyä, jos koodin laatu on aivan sekundaa - vastaavasti erittäin laadukkaalla toteutuksella voi paikata hieman vaillinaista toteutusta. Sinänsä tässä ei pitäisi tulla ongelmia, jos oppimateriaalit on käyty kunnolla läpi. Alla on hieman suuntaa antavia ohjeita miten eri laatukategorioita katsotaan. Tavoitteena olisi saada jokaiseen kohtaan vähintään "hyvä".
Muuttujat ja nimeäminen¶
- huono: Muuttujien ja funktioiden nimistä on mahdoton päätellä mihin ne on tarkoitettu tai mitä ne sisältävät.
- hyvä: Muuttujien ja funktioiden nimistä pystyy pääasiassa päättelemään mihin ne on tarkoitettu, vaikka osa nimistä voikin olla lähinnä "vähän sinne päin". Asioita on nimetty usealla eri kielellä ja nimeämiskäytäntö ei muutenkaan ole välttämättä kauhean yhdenmukainen.
- erinomainen: Ohjelmassa on johdonmukainen ja yhtenäinen nimeämiskäytäntö. Lisäksi muuttujien määrä on hillitty, ja ohjelmassa on vältetty turhia muuttujaansijoituksia. Vastaavasti ohjelmassa on käytetty muuttujaansijoitusta silloin, kun koodirivistä uhkaa muuten tulla liian pitkä.
Ehtolauseiden käyttö¶
- huono: Ehtolauseiden
elif
- jaelse
-osien käyttö puuttuu kokonaan tai on hyvin vajavaista. Vastaavastiand
- jaor
-operaattorit eivät ole hallussa. Näistä johtuen ehtolauseet näyttävät todella hankalilta. Ylipäätään ehtolauseet saattavat toimia enemmänkin vahingossa kuin tarkoituksella. - hyvä: Pääosin ehtolauseet ovat järkeviä. Tämä tarkoittaa sitä, että
elif
- jaelse
-osia on osattu käyttää, kuten myös sisäkkäisiä ehtolauseita sekä em. loogisia operaatioita. Ehtolauseet saattavat kuitenkin olla vähän huteran näköisiä ja tarpeettoman monihaaraisia. - erinomainen: Ehtolauseet ovat nättejä ja ytimekkäitä. Kaikkia em. keinoja on käytetty siten, että ne parantavat koodin luettavuutta ja mahdollistavat erilaisten tilanteiden tunnistamisen siten, että käyttäjällekin pystytään kertomaan, mitä pelissä tapahtuu.
Tietorakenteet (lue: listat, monikot, sanakirjat)¶
- huono: Tietorakenteita ei ole käytetty lainkaan, tai hyvin vähän. Tämä ilmenee koodissa siten, että siellä on paljon muuttujia, joiden nimessä on numero. Vähiä tietorakenteita on väärinkäytetty siinä määrin, että pahaa tekee.
- hyvä: Listoja ja kumppaneita on käytetty muodostamaan järkeviä tietorakenteita sellaisiin paikkoihin, joissa niitä selkeästi tarvitaan. Sellaisissa paikoissa, joissa tarve ei ole ilmeinen, on sen sijaan saatettu käyttää numeroituja muuttujia tai muita vastaavia keinoja.
- erinomainen: Tietorakenteita on käytetty ilmeisten paikkojen lisäksi silloin, kun niillä saa aikaan tiivimpää ja selkeämpää koodia. Myös sisäkkäiset tietorakenteet ovat selkeästi hallussa. Tietorakenteita on toteutuksen kannalta minimaalinen määrä.
Silmukoiden käyttö¶
- huono: Kaikki silmukat on tehty samaan muottiin, vaikka väkisin. Esimerkiksi kaikki silmukat on voitu tehdä
while True
-muottiin, vaikka siellä käytäisiin sisällä läpi listaa. - hyvä: Silmukoissa on osattu tunnistaa milloin tarvitaan
while
a ja milloinfor
ia. Silmukkamuuttujien käyttöfor
-lauseissa saattaa olla vähän hakusissa, ja silmukointi ei välttämättä ole optimaalista. - erinomainen: Silmukat ovat tehokkaita, ja niiden määrä sekä niissä pyörittyjen kierrosten määrä on pääasiassa juuri sen verran kuin on tarpeen eikä yhtään ylimääräistä. Silmukkamuuttujia käytetään hyvin – erityisesti sisäkkäisten listojen tapauksessa – ja temput kuten enumerate ovat hallussa, jos niitä tarvitaan.
Funktioiden käyttö¶
- huono: Ei lainkaan funktioita, tai funktioita on käytetty lähinnä funktioiden käyttämisen vuoksi. Funktiot eivät millään järkevällä tavalla jaa ohjelmaa toiminnallisiin kokonaisuuksiin. Argumenttien käyttöä on liberaalisti kierretty käyttämällä globaaleja muuttujia.
- hyvä: Funktiot jakavat ohjelman loogisiin kokonaisuuksiin, vaikka kokonaisuudet saattavat ollakin ajoittain turhan suuria. Argumenttien ja paluuarvojen käyttö on ymmärretty oikein. Mahdollinen globaalien muuttujien käyttö on rajallista ja perusteltavissa.
- erinomainen: Funktiot on jaettu siinä määrin hyvin, että ne kaikki ovat miellyttävän lyhyitä ja selkeästi rajattuja toiminnaltaan. Ainoastaan pääohjelma tai -funktio voi olla hieman lihavampi. Sekin on kuitenkin järjellisissä rajoissa. Argumenttien kuskaus funktiosta toiseen on tehty järkevästi siten, ettei kaikkea tarvitse raahata joka paikkaan. Jos globaaleja muuttujia on käytetty, niiden käyttö on perusteltu.
Moduulien käyttö¶
- huono: Moduuleja ei ole käytetty lainkaan, minkä takia ohjelma ei edes toimi toivotulla tavalla. Nollan pisteen arvoinen suoritus on myös käyttää pelkästään
from import
ia vaikkei siinä olisi mitään järkeä. - hyvä: Tarvittavat moduulit on löydetty ja niitä on osattu käyttää.
- erinomainen: Ohjelmassa on osattu käyttää moduulien hieman kehittyneempiä ominaisuuksia (esim. time-moduulin muotoilufunktiot) tai on käytetty jotain uutta moduulia lisäominaisuuden tekemiseen. Oma koodi on jaettu moduuleihin, jos se on tarpeen (tiiviin koodin tapauksessa yleensä ei ole!)
Virheenkäsittely¶
- huono: Ohjelmassa ei ole lainkaan virheenkäsittelyä, joten aina kun jotain menee pieleen käyttäjälle heitetään Pythonin virheilmoitusräjähdys. Ohjelma ei muutenkaan selviä virhetilanteista hajoamatta, mikä voi kaatumisen lisäksi ilmetä sellaiseen tilaan joutumisella, että siitä ei päästä pois.
- hyvä: Virheet on pääasiassa käsitelty joitain eksoottisia tapauksia lukuunottamatta. Käyttäjällä on jonkinlainen haju siitä miten tulee toimia, ettei ohjelma hajoile. Virheenkäsittelymenetelmät eivät aina ole sieltä optimaalisimmasta päästä.
- erinomainen: Virheenkäsittelymenetelmät on valittu järkevästi siten, että käyttäjälle saadaan aina mahdollisimman hyvää tietoa vikatilanteessa. Pääasiassa
try
-lohkot sisältävät hyvin minimaalisen määrän koodia. Ohjelma osaa käsitellä eksoottisetkin ongelmatapaukset.
Tiedostojen käyttö¶
- huono: Tiedostoja ei ole käytetty tai tiedostojen luku tehdään jollain hyvin kyseenalaisella tavalla (jota ei ole kurssilla edes opetettu). Vaihtoehtoisesti koodissa on pelkästään tiedostoihin kirjoittamista, eikä lainkaan lukemista.
- hyvä: Tiedostoja kirjoitetaan ja luetaan jollain tavalla siten, että tilastointivaatimus täyttyy. Vaihtoehtoisesti pelissä on jokin muu tapa käyttää tiedstoja, esim. tallentaminen ja lataaminen.
- erinomainen: Tiedostoja on käytetty älykkäästi siten, että kuka tahansa pystyy pelkästään tiedostoa katsomalla päättelemään, millainen lukija sitä varten pitäisi koodata.
Erikoismaininnat¶
Näitä voi pitää eräänlaisina ylimääräisinä saavutuksina:
- Luettavuus: Koodin luettavuus on erittäin hyvä. Tämä tarkoittaa sitä, että nimet, välilyönnit yms. ovat kurssin ohjeistuksen mukaiset. Lisäksi koodia on kommentoitu siellä, missä kommentteja tarvitaan. Kommentit on myös sijoiteltu koodiin nätisti (esim. pääasiassa funktioiden dokumentaatiomerkkijonoon).
- Bugittomuus: Myönnetään, jos ohjelmaa testaava assistentti ei saa ohjelmaasi hajoamaan tai toimimaan väärin (esim. sääntöjen vastaisesti) millään tavalla.
- Pelattavuus: Tämä maininta myönnetään pelille, jota pelatessa ei tarvitse kiroilla käyttöliittymän kanssa. Pelattavuuden pitäisi olla siis sujuvaa, ja pelitilanteen esityksen selkeä. Esim. siirron tekeminen pitäisi onnistua yhdellä tai kahdella lyhyellä syötteellä.
- Lisäominaisuus: Voidaan myöntää mm. hienosta lisäominaisuudesta, kurssilla esittämättömän työkalun järkevästä käytöstä tai vaikka jostain hauskasti toteutetusta ominaisuudesta.
Palautus¶
Arvostelutilaisuus¶
Kurssin hyväksymiseen vaaditaan, että opiskelija on käynyt työn tarkastaneen assistentin kanssa n. 15 minuutin pituisen keskustelun lopputyön tekemisestä kurssin viimeisellä viikolla. Ajanvaraus julkaistaan myöhemmin.