1. Johdanto 1.1. Tehtävä Lausekielinen ohjelmointi (Laki) -kurssin toisena harjoitustyönä ohjelmoidaan Java-kielellä 2048-pelin [1, 2] tekstipohjainen muunnelma. Pelissä on kenttä, jolla liikutellaan tiiliä tavoitteena yhdistää samanarvoisia tiiliä siten, että lopulta saadaan tuotettua 2048 pisteen arvoinen tiili. Peliä voi jatkaa vielä tämän tiilen jälkeen. Tiilet yhdistetään siirtämällä kaikki kentän tiilet annettuun suuntaan, jolloin tiilet kerääntyvät kentän vastakkaiseen reunaan. Kenttää siis tavallaan kallistetaan, jolloin tiilet liukuvat alempana olevaan reunaan. Siirron yhteydessä tiilien väliset tyhjät paikat katoavat. Jos siirtosuuntaa vastaan tarkastellen löydetään peräkkäisten samanarvoisten tiilien muodostamia pareja, nämä parit yhdistetään uusiksi, arvokkaammiksi tiiliksi. Yhdistämisestä saadaan pisteitä parin arvojen summan verran. Siirron seurauksena mahdollisesti saatuja uusia tiilipareja ei yhdistetä samalla siirrolla. Nämä tiilet yhdistetään vasta, kun käyttäjä kohdistaa niihin uuden yhdistämisen aiheuttavan siirron. Tiiliä voidaan siirtää vaakasuunnassa (vasemmalle ja oikealle) ja pystysuunnassa (ylös tai alas.) Ohjelma sijoittaa kentän satunnaisesti valittuun vapaaseen paikkaan uuden tiilen, jos kenttään kohdistettu siirto muutti vähintään yhden tiilen paikkaa tai vähintään yksi tiilipari yhdistyi. Lähtötilanteessa kentälle sijoitetaan kaksi tiiltä. Näin kentälle saadut uudet tiilet ovat kahden pisteen arvoisina aina vähiten arvokkaita. Pelin idean saa helposti selville kokeilemalla Gabriele Cirullin alkuperäistä 2084- peliä [1]. Huomaa, että harjoitustyössä tehtävä peliversio ei vastaa kaikin osin alkuperäistä peliä. Muun muassa pelimerkit esitetään eri tavoin: pieni ja iso a- kirjain vastaavat kahden pisteen tiiltä, iso b-kirjain vastaa neljän pisteen tiiltä, iso c-kirjan vastaa kahdeksan pisteen tiiltä ja niin edelleen. Iso k-kirjain on 2084 pisteen arvoinen ja suurin arvo 67108864 on isolla z-kirjaimella. Peli loppuu, kun pelaaja päättää lopettaa pelin tai siirto ei muuta kentän tilannetta. Jälkimmäisessä tapauksessa loppu tulee viimeistään, kun kentällä on Z-tiiliä, koska näitä ei enää yhdistetä suuremmiksi tiiliksi. 1.2. Pelikenttä Peliä pelataan n n -kokoisella kentällä (n 4), joka esitetään ohjelmassa vastaavan kokoisena kaksiulotteisena taulukkona, jonka alkiot vastaavat kentän paikkoja ja alkioiden arvot paikkojen sisältöä. Kentän paikkoihin viitataan jatkossa taulukon alkioiden tapaan kahdella nollasta alkavalla indeksillä. Kentän ensimmäinen paikka (0, 0) on kentän vasemmassa yläkulmassa. Viimeinen paikka (n - 1, n - 1) on puolestaan kentän oikeassa alakulmassa. Luontevin valinta alkion tyypiksi char, koska harjoitustyössä paikkojen sisältö esitetään merkeillä. Pelikentällä on pisteellä ('.') piirretty yhden merkin levyinen reuna. Sisäpaikoissa on tiiliä vastaavia pelimerkkejä ja kentän taustaa. Tiilet esitetään englanninkielisen suuraakkoston kirjaimilla (A Z) lukuun ottamatta kentälle arvottuja uusia tiiliä, jotka esitetään aina pienellä a-kirjaimella. Tämä kirjain muuttuu suureksi Lausekielinen ohjelmointi Syksy 2014 Jorma Laurikkala 1 / 12
kirjaimeksi, kun merkkejä siirretään. Tausta esitetään välilyönnillä (' '). Tiili- tai taustamerkki ei saa olla reunalla eikä uutta tiilimerkkiä saa sijoittaa tiilimerkin päälle. Kuvassa 1a on esitelty eräs pelin lähtötilanne 6 6 -kokoisella pelikentällä. Ohjelma on sijoittanut kaksi pienellä a-kirjaimella esitettyjä aloitustiiltä kentälle (kuva 1a). Pelaaja aloittaa siirtämällä tiilet vasemmalle ja ohjelma sijoittaa kentälle uuden tiilen (kuva 1b). Siirron seurauksena aloitustiilten merkit vaihtuvat isoiksi a-kirjaimiksi. Pelaaja siirtää seuraavaksi alas, jolloin a-tiili kasvaa A- tiileksi, toisessa sarakkeessa olevat A-tiilet päätyvät peräkkäin ja yhdistyvät samanarvoisina B-tiileksi ja ohjelma sijoittaa kentälle uuden tiilen (kuva 1c). Pelaaja jatkaa siirtämällä alas ja ylös (kuvat 1d ja 1e). Oikealle siirrettäessä yhdistettävät tiilet valitaan oikeasta reunasta aloittaen. Näin paikkojen (1, 4) ja (1, 3) A-tiilistä muodostuu B-tiili (kuva 1f). Paikan (1, 2) A- tiiltä ei huomioida yhdistämisessä, koska yhdistettävät parit ovat erillisiä. Jotta tämä tiili voitaisiin yhdistää, sillä tulisi olla parina välittömästi vasemmalla puolella oleva A-kirjain. Kun käyttäjä siirtää yhdistämisen jälkeen kahdesti oikealle (kuvat 1g ja 1h), kenttä muuttuu jälkimmäisen siirron seurauksena ainoastaan siten, että kentälle arvotun tiilen merkki vaihtuu suureksi. Tästä syystä kuvassa 1h esitetylle kentälle ei sijoiteta uutta tiiltä. Pelaaja peruuttaa jälkimmäisen turhan siirron, jolloin kuvassa 1i palataan kuvan 1g tilanteeseen. Pelaaja siirtää vielä tiilet alas, jolloin toiseksi viimeisen sarakkeen A-tiilistä muodostuu B-tiili (kuva 1j). Yhdistämisprosessia ei jatketa, vaikka uudesta B-tiilestä ja yhdistettyjä merkkejä seuraavasta B-tiilestä saataisiin C-tiili. Yhdistämällä muodostettuja uusia tiiliä voi yhdistää toisin tiiliin, vasta yhdistämistä seuraavalla siirrolla. Pelaaja ei kuitenkaan jaksa pitemmälle ja päättää pelin. (a) (b).a a..a. (c).b A. (d).b AA. (e).baaa. (f). BAB. (g).abab. (h).abab. (j). B..ABAB. Kuva 1: a) kenttä lähtötilanteessa, b) pelaaja on siirtänyt vasemmalle, c) pelaaja on siirtänyt alas, jolloin A-tiilet (lihavoitu b-kuvassa) ovat yhdistynet, d) pelaaja on siirtänyt alas, e) pelaaja on siirtänyt ylös, f) siirto oikealle tuottaa uuden B-tiilen, g) pelaaja on siirtänyt oikealle, h) pelaaja on siirtänyt turhaan oikealle, i) pelaaja on peruuttanut edellisen siirron, j) pelaaja on yhdistänyt A-kirjaimet siirtämällä alas ja lopettaa pelin. (i).abab. Lausekielinen ohjelmointi Syksy 2014 Jorma Laurikkala 2 / 12
1.3. Siirto on merkkijono-ongelma Yksittäisen rivin tai sarakkeen siirto ja merkkien yhdistäminen on hankala tehdä suoraan taulukkoa käsittelemällä. On kenties helpompaa palauttaa siirto ja yhdistäminen merkkijono-ongelmasi siten, että rivin tai sarakkeen sisäpaikkojen merkeistä muodostetaan merkkijono, jota hyödyntäen laskenta on helpompaa. Uusi merkkijono sijoitetaan takaisin rivin tai sarakkeen merkeiksi. Esimerkiksi kuvan 1b sarakkeen { '.', 'A', ' ', 'A', ' ', '.' } sisäpaikkojen merkit voidaan kerätä merkkijonoksi "A A " ja muokata muotoon " B", joka puolestaan on helppo sijoittaa takaisin sarakkeen merkeiksi. Merkkijonojen käytöllä voidaan vähentää myös koodin monistamiseen vaaraa, koska siirrossa ja yhdistämisessä tarvitaan lopulta merkkijonon lisäksi vain tieto siitä, onko siirron suunta jonon lopun vai alun suuntaan. Ohjelmassa ei saa olla metodeja jokaiselle neljästä siirtosuunnasta, koska tällöin on hyvin todennäköistä, että koodia toistetaan pienin muutoksin. Erilliset vaaka- ja pystysuuntaiseen siirtoon liittyvät metodit ovat mahdollisia. Suotavinta olisi tehdä siirto yhdellä metodilla. Yksi 13. harjoituskerran tehtävistä avaa taulukon rivin ja sarakkeen ja merkkijonon välistä ideaa. Tehtävän mallivastauksessa esitetään kuinka rivi- ja sarakesuuntaisen toiminnallisuuden voi toteuttaa tässä yhteydessä yhdellä metodilla. Suositellusta poikkeavat lähestymistavat ovat mahdollisia ja sallittuja. Jos ongelman ratkaisee toisin, on tekijän itse oltava täysin varma, että vaihtoehtoinen lähestymistapa toimii varmasti. Kurssin opettajilla ei valitettavasti ole aikaa opastaa kuinka vaihtoehtoisen ratkaisu korjataan toimivaksi, jos jo ratkaisuideassa on perustavanlaatuinen valuvika. Erityisesti ohjelmoinnin tällä kurssilla aloittaneet opiskelijat saavat todennäköisesti työn helpoiten valmiiksi merkkijonojen avulla. Huomaa, että ohjelmassa ei saa käyttää muita tietorakenteita kuin taulukkoja. Esimerkiksi listaa ei saa käyttää oli kyseessä Javan API:n valmis luokka (esimerkiksi ArrayList) tai itse toteutettu koodi. 1.4. Valmiin koodin käytöstä Kurssin verkkosivuilla on apuluokka, jota käytetään uusien a-arvoisten tiilien sijoittamiseen pelikentälle (luku 3.2). Näitä tiiliä ei saa tuottaa muilla tavoin, jotta oma ohjelman a-tiilet saadaan kentälle samassa järjestyksessä kuin malliratkaisussa. Harjoitustyön teossa saa käyttää kurssin verkkosivuilla julkaistuja mallivastauksia joko sellaisenaan tai muokattuna. Huomaa, että osa viikkoharjoituksen tehtävistä ja niiden mallivastauksista on tarkoitettu avuksi harjoitustyön teossa. Javan API:n tietorakenneluokkia ei saa käyttää; ainoa sallittu tietorakenne on taulukko. Javan API:n taulukkojen käsittelyyn liittyvät metodit on myös kielletty. Esimerkiksi Arrays-luokan palvelut ovat kieltolistalla. Tiedustele harjoitustyön ohjaajaan mielipidettä, jos Javan API:sta sattuu löytymään palvelu, jolla harjoitustyö ratkeaa kovin helposti. Harjoitustyön ohjaajaan kannattaa ottaa yhteyttä muutenkin, mikäli on epävarma siitä mitä saa tehdä ja mitä ei. Lausekielinen ohjelmointi Syksy 2014 Jorma Laurikkala 3 / 12
Harjoitustyö tehdään itse omalla ajalla. Kaverien kanssa saa keskustella, mutta suora kopiointi eli plagiointi on kiellettyä. Verkosta löytyviä ja harjoitustyötä muistuttavia ohjelmia saa ajaa, mutta niiden koodia ei saa kopioida. Muualta kuin kurssisivuilta poimitun koodin käyttö katsotaan plagioinniksi. Kurssisivuilla mahdollisesti julkaistavan mallivastauksen tavukoodin purkaminen lähdekoodiksi on plagiointia. 1.5. Pakollisuus ja korvaavuudet Harjoitustyö on pakollinen. Ainoa poikkeus tähän sääntöön ovat harjoitustyön korvanneet opiskelijat. Harjoitustyön voi korvata: A) Muiden oppilaitosten opinnoilla. B) Edellisellä Laki-kurssilla hyväksytyllä toisella harjoitustyöllä, jos kurssi jäänyt kesken esimerkiksi ase- tai siviilipalveluksen tapaisesta pakottavasta syystä. Kurssin kotisivuilla on annettu tarkempia tietoja osasuorituksista. C) Edellisten kohtien tapaisella painavalla syyllä. Kohdan A perusteella on annettu kaikki opintokoordinaattorin (Heli Rikala) kurssin vastuuopettajalle (Jorma Laurikkala) esittämät korvaavuudet. B ja C-kohtien osalta on tärkeintä muistaa, että harjoitustyö korvautuu vain, jos ottaa yhteyttä kurssin vastuuopettajaan. Tähän mennessä tulleet yhteydenotot ja sopimukset on kirjattu ylös eikä uusia yhteydenottoja näiltä osin tarvita. 2. Ohjelman toiminnot Seuraavassa esitellään ohjelman toiminnallisuutta pienten esimerkkien avulla. Laajempia esimerkkiajoja julkaistaan kurssin kotisivujen Harjoitustyöt Harjoitustyö 2 -kohdassa. Tietojen lukemiseen näppäimistöltä käytetään In-luokan operaatiota. Myös In-luokka löytyy kurssin sivuilta. Huomaa, että harjoitustyössä syötteiden lukuun ei saa käyttää muita keinoja (esimerkiksi Scanner-luokkaa sellaisenaan), jotta töiden automaattinen tarkistus (luku 6) onnistuisi paremmin. Ohjelmassa on komennot tiilien siirtoon kentän vasempaan, oikeaan, ylä- tai alareunaan (luku 2.4), siirron peruuttamiseen (luku 2.5) ja ohjelma lopettamiseen (luku 2.6). Virheelliset komennot ohitetaan (luku 2.3). Tehtävän helpottamiseksi oletetaan, että ohjelmalle annetaan aina syöte sitä luettaessa ja että syöte on aina oikean tyyppinen (char). 2.1. Ohjelman käynnistys Ohjelma käynnistetään kahdella kokonaislukuarvoisella komentoriviparametrilla [3], jotka ovat järjestyksessä vasemmalta oikealle satunnaislukugeneraattorin siemenluku ja kentän sivun pituus, johon lasketaan myös kentän reunat. Siemenluku tarvitaan, jotta harjoitustyön apuluokka (luku 3) osaa valita a- arvoisten tiilien paikat tietyssä satunnaisessa järjestyksessä. Ilman siemenlukua Javan satunnaislukugeneraattori tuottaisi jokaisella ohjelman ajokerralla täysin satunnaisen jonon lukuja, jolloin ratkaisun ja mallivastauksen toimintaa ei voitaisi Lausekielinen ohjelmointi Syksy 2014 Jorma Laurikkala 4 / 12
vertailla. Apuluokka arpoo uusia a-arvoisia tiiliä kentälle kaikissa ohjelmissa samalla tavalla, kun satunnaislukugeneraattori alustetaan tietyllä siemenluvulla. Ohjelmalle annetaan esimerkiksi siemenluku 5 ja ohjelmaa käsketään luomaan 6 6 -kokoinen kenttä seuraavasti: java M2048 5 6 Uudelleenohjausta käytettäessä komento voi olla esimerkiksi: java M2048 5 6 < syote_tehtanto_5_6.txt > tulos.txt Ohjelman tulostaa tervehdyksen (luku 2.2) jälkeen virheilmoituksen "Invalid command-line argument!" ja jäähyväiset (luku 2.5), jos komentoriviparametreissa on virhe tai kentän sivun pituus on virheellinen. Komentoriviparametrit voivat olla väärän tyyppisiä tai niitä voi olla väärä määrä. Sivun pituuden tulee olla vähintään neljä merkkiä. Jos ohjelmalle annetaan esimerkiksi väärän tyyppinen komentoriviparametri (x): java M2048 1 x ohjelma tulostaa: ----------- 2 0 4 8 ----------- Invalid command-line argument! Bye, see you soon. 2.2. Tervehdystekstin tulostaminen Käynnistyessään ohjelma tulostaa näytölle miinusmerkeillä (ꞌ - ꞌ ) ja kahdella putkimerkillä (ꞌ ꞌ ) kehystetyn viestin: ----------- 2 0 4 8 ----------- Tämä teksti tulostetaan vain kerran. 2.3. Komennon lukeminen Heti tervehdysrivien jälkeen tulostetaan pisterivi "Points: x.", missä x on tiilten yhdistämisistä toistaiseksi saatu pistemäärä. Pelin pisteitä on nolla. Välittömästi pisterivin jälkeen tulostetaan kenttä (luku 1.2). Lähtötilanteessa kentän kahdessa sisäpaikassa on pienellä a-kirjaimella esitetty tiilimerkki, jotka sijoitetaan kentälle apuluokan metodilla (luku 3.2). Kentän tulostamisen jälkeen tulostetaan omalle rivilleen ohjerivi "" ja jäädään odottamaan käyttäjän komentoa seuraavalla rivillä. Esimerkki lähtötilanteesta, kun siemenluvuksi on annettu viisi ja kentän sivun pituudeksi kuusi: Lausekielinen ohjelmointi Syksy 2014 Jorma Laurikkala 5 / 12
----------- 2 0 4 8 ----------- Points: 0. Virheelliset komennot jätetään huomiotta. Kentälle ei sijoiteta uutta a-tiiltä, jos komento virheellinen. Ohjelma reagoi tuntemattomaan komentoon tulostamalla uudelleen pisterivin, kentän ja ohjerivin: U Points: 0. 2.4. Tiilien siirtäminen Tiiliä voidaan siirtää neljään suuntaan: vasemmalle ('l'), oikealle ('r'), ylös ('u') tai alas ('d'). Siirretään ohjelman lähtökentälle arpomat a-tiilet vasempaan reunaan: l Points: 0..A a..a. Tiilet muuttuvat siirron seurauksena A-tiiliksi. Ohjelma sijoittaa kentälle siirron jälkeen yhden a-tiilen. Tämän tiili saadaan kentälle aloitustiilien tapaan apuluokkaa käyttäen (luku 3.2). Siirretään seuraavaksi alas: d Points: 4..B A. Lausekielinen ohjelmointi Syksy 2014 Jorma Laurikkala 6 / 12
Toisen sarakkeen A-tiilet yhdistyvät B-tiileksi ja käyttäjä saa 2 + 2 = 4 pistettä. Toinen uusi merkki saadaan ohjelmalta: kentälle ilmaantuu taas a-tiili. Siirretään uudestaan alas: d Points: 4..B AA. ja sitten ylös: u Points: 4..BAAA. Yhdistetään toisen rivin kaksi oikean puoleisinta A-tiiltä siirtymällä oikealle: r Points: 8.. BAB. Pisteet kasvavat kahdeksaan pisteeseen (4 + 2 + 2= 8) ja oikeaan reunaan ilmestyy uusi B-tiili. Seuraavaksi siirrytään oikealle: r Points: 8..aBAB. ja uudelleen oikealle: Lausekielinen ohjelmointi Syksy 2014 Jorma Laurikkala 7 / 12
r Points: 8..ABAB. Koska tiilet eivät liikkuneet tai yhdistyneet, ohjelma ei sijoita kentälle uutta a- tiiltä. Pelkästään viimeisimmän a-tiilen muutos A-tiileksi ei ole riittävä syy sijoittaa uutta a-tiiltä kentälle. 2.5. Siirron peruminen Perutaan viimeisin siirto selvänä vikatikkinä pienellä z-kirjaimella (ꞌzꞌ), jolloin palataan ennen virhesiirtoa valinneeseen tilanteeseen. Peruutus palauttaa myös vanhat pisteet. Pisteet eivät kuitenkaan nyt muutu, koska turhalla siirrolla ei saavutettu mitään. Peruutus palauttaa vain edellisen tilanteen: peruutuskomentoa välittömästi seuraava uusi peruutuskomento jätetään virheellisen komennon tapaan huomiotta (luku 2.3). z Points: 8..aBAB. 2.6. Pelin lopettaminen Pelaaja yhdistää vielä toiseksi viimeisen sarakkeen A-tiilet liikkumalla alas. Palkkioksi saadaan taas neljä (2 + 2) pistettä ja kokonaispisteet kasvavat 12 pisteeseen. d Points: 12.. B..ABAB. Tässä vaiheessa pelaaja päättää tehdä muuta ja lopettaa pelin antamalla komennoksi pienen q-kirjaimen ('q'). Peli tulostaa ennen pysähtymistä omalle rivilleen lyhyet jäähyväiset "Bye, see you soon." (Ohjeriviä ei tulosteta, koska komentoja ei enää lueta.) Lopetetaan peli edellisessä kuvassa jäätyyn tilanteeseen: Lausekielinen ohjelmointi Syksy 2014 Jorma Laurikkala 8 / 12
q Bye, see you soon. Ohjelma toimii yllä kuvatulla myös, kun tiiliä täynnä olevaan kenttään kohdistettu siirtokomento ei siirrä yhtäkään tiiltä tai yksikään tiilipari ei yhdisty. Alla annetussa tilanteessa tiilien siirto ylös ei muuttaisi kenttää muuten kuin a-tiilen osalta, joka muuttuisi A-tiileksi. Tästä syystä ohjelma pysäyttää itsensä: d Points: 92..BaAA..CBBC..BCCA..ABBB. u Bye, see you soon. 3. Koodista 3.1. Yleistä Ohjelma kirjoitetaan tuttuun tapaan main-operaation sisältävään luokkaan. Ensimmäisestä harjoitustyöstä poiketen ohjelma on kuitenkin jaettava metodeihin. Metodien lukumäärä riippuu ohjelmoijasta, mutta ohjelmaan ei saa kirjoittaa liian pitkiä metodeja. Ohjelmassa on vältettävä saman koodin kopioimista eri paikkoihin, koska koodista voi kirjoittaa asianomaisista paikoista kutsuttavan metodin. Erityisesti on vältettävä tiilien liikutteluun liittyvää toistuvaa koodia. Kullekin suunnalle ei saisi olla omia metodeja, jotka ovat pieniä eroja lukuun ottamatta samaa koodia. Oikeaan ja vasempaan tapahtuvan liikuttelun voi yhdistää vaakasuunnasta vastaavaan metodiin. Samoin ylös ja alas liikuttelu voisi olla pystysuunnasta vastaavassa metodissa. Merkkijonojen avulla tapahtuvan liikuttelun ja merkkien yhdistämisen (luku 1.3) voi toteuttaa yhdellä metodilla suuremmin koodia toistamatta. Muista noudattaa hyvää ohjelmointitapaa: sisennä koodia johdonmukaisesti luettavuuden parantamiseksi, kommentoi riittävästi ja oikeissa paikoissa, liitä jokaiseen metodiin yleisluonteinen kommentti, nimeä vakiot, muuttujat ja metodit järkevästi, käytä vakioita, pidä rivit riittävän lyhyinä, käytä välejä lauseiden sisällä ja erota loogiset kokonaisuudet toisistaan väliriveillä, pidä metodit järkevän mittaisia metodin tulisi mahtua yhdelle A4-kokoiselle sivulle ja vältä attribuutteja. Lausekielinen ohjelmointi Syksy 2014 Jorma Laurikkala 9 / 12
Voit palauttaa hyvän ohjelmointitavan mieleen lukemalla luentomateriaalin 13. ja 24. luvut [4, 5]. Tarpeettomien attribuuttien käyttöä tulee välttää. Erityisesti parametrilistojen kautta tapahtuvaa tiedonvälitystä ei saa korvata järjestelmällisesti attribuuteilla, koska tällöin rikotaan karkeasti modulaarisuusperiaatetta. Modulaarisessa ohjelmoinnissa on tavoitteena jakaa koodi helposti ymmärrettäviin ja hallittaviin kokonaisuuksiin, jotka kommunikoivat ympäristönsä kanssa selkeästi määritellyn liittymän (parametrilista ja paluuarvo) kautta. Attribuutit näkyvät kaikkiin metodeihin, jolloin ohjelman tietoja voidaan muuttaa missä tahansa moduulien liittymät ohittaen. Harjoitustyössä saa käyttää yhtä normaalia attribuuttia, joka ei kuitenkaan saa olla taulukko. Final-määreellä esiteltyjä vakioituja attribuutteja (eli luokkavakioita) sen sijaan saa käyttää vapaasti, koska vakioarvoisen attribuutin arvoa ei voida muuttaa metodeissa. Sisennä koodi välilyönnein. Älä käytä sisentämiseen tabulaattoria, jotta koodisi näkyisi samanlaisena myös ohjaajan editorissa. Erityisesti välilyöntejä ja tabulaattorimerkkejä ei saa käyttää sekaisin, koska tällöin on varmaa etteivät sisennykset näy ajatellulla tavalla. Ohjelman nimen tulee olla M2048, jolloin lähdekoodi on M2048.java nimisessä tiedostossa. Ohjelman saa jakaa luokkiin, jos kaikki luokat ovat M2048.javatiedostossa. 3.2. Tiilien tuottaminen apuluokalla Kurssin verkkosivuilta on annettu Automaatti-luokka, joka on tarkoitettu a-tiilien tuottamiseen. Luokalla on kaksi julkista metodia (luokan 4. kohta): kaynnista-metodi on tarkoitettu satunnaislukugeneraattorin alustamiseen. Anna String-tyyppisestä komentoriviparametrista kokonaisluvuksi muunnettu siemenluku metodin parametriksi. Metodia voi kutsua missä tahansa metodissa, jossa siemenluku on saatavilla. Tärkeintä on, että metodia kutsutaan ennen sijoita-metodia ja että metodia kutsutaan vain kerran. Uudelleenkutsu tuottaa ohjelman pysäyttävän poikkeuksen. Metodiin on rakennettu miina, koska uudelleen alustettaessa siemenlukuun liittyvä satunnaislukujen jono alkaa alusta, vaikka käytettäisiin samaa siemenlukua. sijoita-metodi sijoittaa parametrinaan saamaansa pelikenttään pyydetyn lukumäärän verran a-tiilen merkkejä, jos kentässä riittävästi vapaita taustapaikkoja. Metodin kutsu tuottaa poikkeuksen, jos satunnaislukugeneraattoria ei ole alustettu alusta-metodia kutsumalla. Kaikkien vanhojen tiilimerkkien tulee olla kentällä metodia kutsuttaessa, jotta uutta tiiltä ei sijoiteta vahingossa jonkin vanhan tiilen paikkaan. Metodeihin on syytä tutustua tarkemmin lukemalla metodien otsikot ja metodien yleiset kommentit. Molemmat metodit ovat static-määreellä esiteltyjä luokkametodeja, joita kutsutaan In- ja Math-luokkien metodien tapaan luokan nimen kautta. Esimerkiksi käynnistä metodin kutsu voisi olla: Automaatti.kaynnista(siemenluku); Lausekielinen ohjelmointi Syksy 2014 Jorma Laurikkala 10 / 12
Yllä siemenluku on siemenluvun sisältävä muuttuja. 13. harjoituksissa on tehtävä, jossa apuluokan metodeja kutsutaan esimerkinomaisesti. Älä käytä muita menetelmiä a-tiilien tuottamisen, jotta ohjelmasi toimii varmasti samalla tavoin kuin malliratkaisu. Älä muuta Automaatti-luokkaa millään tavalla. Älä kopioi luokan metodeja ohjelmaasi. Harjoitustyöohjelmaa suoritettaessa ja käännettäessä on pidettävä huolta siitä, että Java-kääntäjä ja -tulkki löytävät apuluokan. Helpointa on kopioida Automaattiluokka (Automaatti.java-tiedosto) In-luokan tapaan samaan hakemistoon, jossa ohjelmasi on. 4. Dokumentointi Harjoitustyöstä kirjoitetaan dokumentti, jonka tulee sisältää seuraavat asiat: 1. Kansilehdellä tekijän nimi, opiskelijanumero, sähköpostiosoite, yksikkö ja tutkinto-ohjelma. Sivun keskellä tulisi olla suuremmalla fontilla dokumentin nimi. Kurssin kotisivuilla julkaistaan esimerkinomainen kansilehti. 2. Lyhyt kuvaus ohjelman toiminnasta. Voit kuvailla ohjelman toimintaa joko täysin vapaamuotoisena tekstinä (korkeinaan puoli sivua) tai pseudokoodina (korkeintaan kaksi sivua). Pseudokoodissa olisi hyvä olla operaatioita ja muuttujia. Huomaa, että käytit kumpaa lähestymistapaansa hyvänsä, niin tärkeintä on ohjelman keskeisen logiikan hahmottelu yleisellä tasolla. 3. Omia ajatuksia. Esimerkiksi: Oliko työ helppo, sopiva vai vaikea? Jos helppo tai vaikea, niin miksi? Mitä uutta opittiin? Oliko työstä mitään hyötyä tekijälleen? Montako tuntia työn tekemiseen meni? Dokumentin leipäteksti kirjoitetaan 12 pisteen fontilla ja yhdellä rivinvälillä. Valmiin tekstin lukeminen pariin otteeseen ei ole huonompi idea. Dokumentin kirjoitus tekstinkäsittelyohjelmalla sekä ohjelmasta löytyvän oikolukutoiminnon käyttäminen tekstin tarkistamiseen on myös suotavaa. Dokumentti on palautettava PDF-muodossa. Muut tiedostomuodot eivät kelpaa. Luvussa 6 ja kurssin verkkosivuilla kerrotaan tarkemmin dokumentin ja koodin palauttamisesta. 5. Harjoitustyön ohjaus Harjoitusryhmien vetäjät vastaavat pääsääntöisesti ryhmäläistensä töiden ohjauksesta ja tarkistuksesta. (Tuntiopettajat tarkistavat kurssin vastuuopettajan ryhmäläisten harjoitustyöt.) Apua saa sekä sähköpostitse että henkilökohtaisesti. Ohjaajat ovat tavattavissa yliopistolla kurssin verkkosivuilla myöhemmin julkaistavina aikoina. Kurssin vastuuopettaja auttaa harjoitustyöongelmissa myös muitakin kuin oman ryhmänsä opiskelijoita. Pyri kuitenkin ottamaan ongelmatilanteissa yhteys ensin oman harjoitusryhmän vetäjään, koska vastuuopettajalla on toisinaan kiire. Muista myös, että tehtävänantoon ja Javan piirteiden käyttöön liittyvissä epävarmoissa tilanteissa kannattaa aina kysyä ohjaajalta. Lausekielinen ohjelmointi Syksy 2014 Jorma Laurikkala 11 / 12
6. Harjoitustyön palautus Ohjelma ja dokumentti täytyy palauttaa viimeistään tiistaina 20.1.2015 klo 16.00 WETO-järjestelmään. Tarkemmat palautusohjeet julkaistaan myöhemmin kurssin verkkosivuilla. Harjoitustöiden toiminnallisuuden tarkistamiseen käytetään WETO-järjestelmää, joka vertailee automaattisesti mallivastauksen ja opiskelijoiden ratkaisujen tulosteita. Tästä syystä edellä annettuja tulostemäärittelyjä on seurattava merkilleen. Automaattinen vertailu vähentää rutiininomaista testaustyötä, jolloin opettajille jää enemmän aikaa mielekkäämpään työhön eli ohjelman rakenteen ja tyylin tutkimiseen. Opiskelijat hyötyvät tästä perusteellisempien kommenttien muodossa. Lisäaikaa työn tekoon voi saada muutaman päivän vain hyvästä syystä. Lisäajasta on sovittava harjoitusryhmän vetäjän kanssa ajoissa eli viimeistään päivää tai paria ennen palautuksen takarajaa. Ennen palautusta on syytä varmistaa, että dokumentissa on mukana kaikki edellä mainitut kohdat. Lisäksi kannattaa tarkistaa, että ohjelma toimii varmasti oikein viimeisten muutosten jälkeen. 7. Harjoitustyön arvostelu Harjoitustyö arvostellaan asteikolla hyväksytty/hylätty. Hylkäyksen perusteena voi olla esimerkiksi ohjelman virheellinen toiminta, hyvän ohjelmointitavan noudattamatta jättäminen, ohjelman rakenne (erityisesti koodin monistaminen ja liian pitkät metodit), huono dokumentti ja/tai plagiointi. Plagiointiin liittyy sanktio, joka koskee molempia opiskelijoita. (Toiselta opiskelijalta tämän tietämättä kopioidun koodin käyttö johtaa kopioijan koko kurssisuorituksen hylkäämiseen.) Hylätty työ on korjattava pääsääntöisesti viikon sisällä hylkäyksestä. Lähteet [1] G. Cirulli: 2048, http://gabrielecirulli.github.io/2048/ (Luettu viimeksi 3.12.2014.) [2] Wikipedia-yhteisö: http://en.wikipedia.org/wiki/2048_(video_game) (Luettu viimeksi 3.12.2014.) [3] J. Laurikkala: Lausekelinen ohjelmointi -kurssin luentorunko, luku 23, http://www.sis.uta.fi/~laki/luennot/luento14/ (Luettu viimeksi 3.12.2014.) [4] J. Laurikkala: Lausekelinen ohjelmointi -kurssin luentorunko, luku 13, http://www.sis.uta.fi/~laki/luennot/luento08/ (Luettu viimeksi 3.12.2014.) [5] J. Laurikkala: Lausekelinen ohjelmointi -kurssin luentorunko, luku 24, http://www.sis.uta.fi/~laki/luennot/luento14/ (Luettu viimeksi 3.12.2014.) Lausekielinen ohjelmointi Syksy 2014 Jorma Laurikkala 12 / 12