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 hiirellä ruudukosta yhden ruudun 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 (eli se on tyhjä), 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¶
Toimivan toteutuksen tulee osoittaa kurssin asioiden hallintaa. Seuraavasta listasta voit tarkistaa mitä työltä vaaditaan, jotta se hyväksytään:
- Peli toteuttaa yllä kuvatut miinaharavan säännöt
- Peli toimii käyttäjän valitsemilla dimensioilla - testaa erityisesti, että muutkin kuin neliöt (leveys = korkeus) toimivat!
- 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ä).
- Pelissä on alkuvalikko, josta voi valita uuden pelin, lopettamisen ja tilastojen katsomisen - huom! valikko voi olla tekstipohjainen, ainoastaan itse peli-ikkunan tulee olla graafinen.
Näiden puuttuminen tai niissä olevat virheet pompauttavat työn takaisin täydennyksiä/korjauksia varten.
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 ja grafiikkana käytettävät kuvat yllä olevista linkeistä. Kuvat laitetaan oletuksena spritet-nimiseen kansioon projektikansiosi sisälle - kyseessä on siis pakattu kansio, älä pura sitä erikseen spritet-kansioon koska silloin saat spritet/spritet hakemistoksi. 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ä. Halutessasi voit ladata myös alta skriptin, jolla zipin kuvat on generoitu (vaatii PyCairon asentamisen).
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 (max ryhmäkoko: 3). 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ä.
Kaikki koodit ajetaan samankaltaisuutta nuuskivan työkalun läpi, ja jos ryhmien välillä löytyy suuria samankaltaisuuksia, asiasta pyydetään ryhmiltä kommentit, joiden perusteella päätetään miten edetään.
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.
Työtä ei nykyään pisteytetä, mutta alla ovat edelleen nähtävissä aiemmin käytetyt koodin laatuun liittyvät pisteytyskriteerit joita apuna käyttäen voi miettiä onko koodi sellaista, että sitä kehtaa näyttää muillekin.
Koodin laatu¶
Hyvän yleiskuvan koodin laadusta saa Pylint-tarkistuksella. Alla lisäksi muutamia muita huomioita.
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 voi olla 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ä. Kaikki nimet ovat samaa kieltä.
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.
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.