ITV0110 2. töö 2017: javascript ja css: erinevus redaktsioonide vahel

Allikas: Lambda
Mine navigeerimisribale Mine otsikasti
Martinv (arutelu | kaastöö)
Resümee puudub
Martinv (arutelu | kaastöö)
Eemaldatud muudatus 14793, mille tegi Martinv (arutelu)
 
1. rida: 1. rida:
[[Pilt:Battleship2.jpg|left|Battleship]]
[[Pilt:minesweeper.gif|left|IT]]


== Mida tuleb teha ==
Sinu ülesandeks on kirjutada [https://en.wikipedia.org/wiki/Minesweeper_(video_game) minesweeperi] mängu brauseris töötav tugevalt lihtsustatud eriversioon, kasutades ainult html-i, css-i ja javascripti.
Loe kõigepealt läbi ülevaade [https://en.wikipedia.org/wiki/Minesweeper_(video_game) wikipediast] ja mängi katseks [https://birrell.org/andrew/minesweeper/ seda varianti ] ja [http://minesweeperonline.com/ seda varianti].
Valmis töö tuleb riputada üles ülikooli serverisse dijkstra sinu kataloogi prax2 alla. Ehk, arvestatakse ainult dijkstra-s olevaid töid.


Selles praksis teed arvuti vastu mängimise variandi, aga kolmandas praktikumis tuleb samale mängule lisada serveripoolset funktsionaalsust, näiteks tulemuste salvestamine ja vaatamine ja statistika, pooliku mängu salvestamine ja hilisem jätkamine ja samuti mäng kahe inimese vahel, mis toimub siis serverirakenduse vahendusel.


<!--
== Detailid ==
== <font color="red"> NB! </font> ==
 
Sa pead realiseerima minesweeperi täpselt alltoodud nõuete järgi: teistmoodi funktsionaalsusega lahendused ei sobi!  
 
Tehnoloogilises mõttes (a la kas kasutada jQueryt, bootstrappi, reacti jne jne) piiranguid ei ole, kuid algajatele on soovitus kõiki lisatööriistu vältida: need on esialgu keerulised ja kulutavad aega,
 
Nõuded siis:


<font color="red">
Sinu programm peab algul mängijale pakkuma
Hetkel on praksiülesanne muutmisel, palun ignoreeri allolevat poolikut teksti!
* valikuna kolme variandi vahel laua suuruse:  6, 9 või 16 ruutu.
</font>
* ja tekstiväljal sisestamiseks pommide arvu N.


-->
Lisaks on näha nupp "Alusta". Lauda esialgu ei kuvata.


== Mida tuleb teha ==
Peale "Alusta" nupule vajutamist kontrollitakse, kas valikud on tehtud. Kui ei, hoiatatakse. Kui jah, kuvatakse tühi laud.


Sinu ülesandeks on kirjutada
Laud kuva valikute alla ja ära neid valikuid ära kustuta: las jäävad näha.
[https://en.wikipedia.org/wiki/Battleship_%28game%29 laevade pommitamise] mängu brauseris töötav lihtsustatud eriversioon, kasutades ainult html-i, css-i ja javascripti.  


Loe kõigepealt läbi ülevaade [https://en.wikipedia.org/wiki/Battleship_%28game%29 wikipediast] ja mängi katseks standardset täisversiooni [http://en.battleship-game.org/ siin] või [http://boomboomboat.com/ siin] või [http://www.superkids.com/aweb/tools/logic/bship/ siin]: see on hea insipiratsioon sinu enda mängu tegemiseks.
Laua disaini ära tee klassikalise pseudo-3d ja varjudega, vaid lihtsalt joontest ruudustikuna.


Ühe mängija asemel mängib sinu programmis arvuti, st programmi kasutaja mängib arvuti vastu.  
Lisaks laua kuvamisele arvuta välja pommide massiiv, paigutades N pommi juhuslikult laiali (selle kohta leiad all näitekoodi).


Valmis töö tuleb riputada üles ülikooli serverisse dijkstra (vaata altpoolt). Ehk, arvestatakse ainult dijkstra-s olevaid töid.
Kui kasutaja vajutab mõnele laua ruudule (avab ruudu) siis:
* Kontrolli, kas tabati pommi, ja kui, siis näita kasutajale, et ta on kaotanud.
* Kontrolli, kas kõik pommivabad ruudud on avatud, ja kui jah, siis näita kasutajale, et ta on võitnud.
* Vastasel juhul (normaalolukord) tee järgmist:
** märgi avatud ruut näiteks teise taustavärviga, rehkenda kokku avatud ruudu kõrvalruutudel olevate pommide arv ning kuva see avatud ruudu sisse. Kõrvalruutusid on ruudul kokku 8, kui ta pole just laua äärel. Kõrvalruutude leidmiseks leiad all näitekoodi.
** kui avatud ruudu sisse kirjutati nullist suurem arv, on käik lõppenud ja oota uut käiku. Ainult avatud ruut sai sel juhul numbri.
** kui avatud ruudu sisse kirjutati 0, siis rehkenda kokku naaberruutudel olevate pommide arvud ja kuva iga naaberrudu sisse. Iga naaberruut saab seega numbri, aga ta ei ole märgitud avatuks,


Selles praksis teed arvuti vastu mängimise variandi, aga kolmandas praktikumis tuleb samale mängule lisada serveripoolset funktsionaalsust, näiteks tulemuste salvestamine ja vaatamine ja statistika, samuti mäng kahe inimese vahel, mis toimub siis serverirakenduse vahendusel.
NB! Järgmised lihtsustused on rangelt nõutud, st nende tavafeatuuride tegemine on keelatud:


== Detailid ==
* Minesweeperi tüüpilist funktsionaalsust - automaatset suure hulga ruutude avamist - ära tee.
* Ruutude äramärkimist lipukesega ära tee.
* Allesjäänud pommide arvu, tehtud käikude arvu, kulunud aega jms ära kuva.


Meie praksiülesande detailid ja erisused standardsest laevade pommitamisest on järgmised:
Laua alla kuva seniste tulemuste loetelu: iga rida selles ütleb, kas kaotasid või võitsid ja mitu käiku kulus. Iga järgmine lõppenud mäng lisab sinna ühe rea.


* Lihtsustus: kasutame ainult ühte tüüpi laeva: kahene horisontaalpaigutusega laev. Ehk, alati kaks kõrvuti horisontaalset ruutu.
Info paigutus ekraanil peab olema stabiilne, tekst/nupud ei tohi hüpata vahel ühte, vahel teise kohta. Leht peab olema selge, arusaadava ja kena disainiga, mõttetut/segast infot ja arusaamist raskendavaid kujunduselemente ära kasuta. Arvesta kindlasti [[htmli kujunduse üldpõhimõtted| selle juhendi soovitustega]].
* Neid standardse pommitamise reegleid tuleb järgida:
** Laevad ei tohi olla üksteisega külgepidi/otsapidi koos. Diagonaali ehk nurgaga puudutamine on ok.
** Lui sina või masin on mõnda ruutu pommitanud, aga läks mööda, peab sinna ilmuma nähtav märge.
** Lui oled laevaruudule pihta saanud, peab sinna ilmuma teistsugune nähtav märge, millest saab aru, et said pihta.
** Kui sina või masin saab laevaruudule pihta, saab ta kohe uuesti pommitada, kuni ta kas võidab või pommitab mööda: alles siis antakse käik teisele üle.
* Sina mängid arvuti vastu, seejuures on ok, kui arvuti käib lihtsalt juhuslikult, kuid ta ei tohi pommitada kohti, mida ta on juba varem pommitanud.
* Mängu alguses pead saama valida maatriksi suuruse: konkreetselt kas 3x3, 4x4, ... või 10x10 ruudustik.
* Mängu alguses peab saama valida laevade arvu: kas 1, 2, 3, ..., 10 laeva. Laevade arv ei tohi olla suurem, kui valitud maatriksi küljepikkus miinus üks: näiteks 4x4 ruudustikul võib olla maksimaalselt kolm laeva. Kui sul ei õnnestu kõiki laevu maatriksile paigutada, siis pole hullu, kui paigutad ühe vähem.
* Laevade algse paigutuse nii sinu maatriksil kui tema enda maatriksil määrab arvuti juhuslikult, arvestades seejuures, et laevad ei tohi külgepidi ega otsapidi kokku puutuda. <b>NB!</b> Juhusliku paigutamise meetodid ja piirangud võid ise valida. Ei pea olema nö "täiesti juhuslik", peaasi, et nö mõistlik juhuslikkus oleks sees. Kui sul praksis kõik nõutud osad valmis, võid lisaks realiseerida ka enda laevade ise-paigutamise: see ei ole kohustuslik ja annab ühe punkti võimalikust 12-st.  
* Lehel peab olema nupp mängu alustamiseks, mida võib vajutada ka käimasoleva mängu korral: sel juhul mäng katkestatakse ja alustatakse nullist uut, koos uute maatriksisuuruse ja laevade arvu valikuga.
* Mängu alustab ehk esimese pommi tulistab inimene.
* Mängu lõppedes pead kuvama, kes võitis ja mitu pommitamist tegid sina ja mitu masin.
* Pead salvestama ja lehel pidevalt kuvama viimase kümne mängu tulemusi ridade kaupa, igal real selline info: maatriksi suurus, laevade arv, sinu pommitamiste arv, masina pommitamiste arv. Vabatahtliku lisana mängu aeg sekundites: see ei ole kohustuslik ja annab ühe punkti 12-st.
* Kujunduslikud ja tehnoloogilised nõuded:
** Kujundus ei tohi olla väga kole. Hea mõte on lähtuda [[htmli kujunduse üldpõhimõtted| sellest juhendist]].
** Erinevad elemendid lehel peavad mängu käigus püsima stabiilsed, ei tohi ringi nihkuda.
** Lehel peavad olema sinu maatriks ja masina maatriks sama suured ja horisontaalis kõrvuti. Mobiilivariandis (kui selle teed) peab masina maatriks aga olema sinu maatriksi kohal.
** Ei tohi kasutada canvast, svg-d, flashi ega java applette. Maatriksi jaoks kasuta kas div-e või tabelit koos css-i ja javascriptiga.
** Nii laevade maatriksi kui seniste tulemuste tabeli võid teha tabeli või div tagidega, aga mujal ei tohi tabeli tagi kasutada.


Kõiki eeltoodud nõudeid tuleb järgida, klassikaline laevade pommitamine praksilahenduseks ei sobi.
Kogu kood peab olema laetud dijkstra serverisse prax2 alamkataloogi. Pealeht olgu nimega index.html.


== Kohustuslikud ja mittekohustuslikud osad ja punktiarvestus ==
== Kohustuslikud ja mittekohustuslikud osad ja punktiarvestus ==


Eeltoodud nõuete punktid peavad arvestamiseks olema täidetud, nad annavad kokku 6 punkti. Lisaks - kuni maksimaalse 12ni - saad teha järgmised osad:
Kokku võid saada 12 punkti, mis jagunevad selliselt:
 
Kui suudad kuvada laua ning käigud töötavad ok (naaberruutude arvud kuvatakse ok), saad praktikumi arvestatud ja kokku 6 punkti.
 
Kui sul on realiseeritud valikud (laua suurus ja pommide arv) ning suudad tuvastada ja kuvada võidu/kaotuse, saad lisaks 2 punkti.
 
Kui realiseerid tulemuste loetelu kuvamise, saad veel lisaks 2 punkti.
 
Kui mängu kujundus on kena ja arusaadav nii tava-arvutis kui mobiilis (ei ole vaja scrollida vasakule-paremale, elemendid ei ole väga väikesed jne), siis saad lisaks 2 punkti.
 


* Kuvad oma laevasid pildina, mitte lihtsalt märgendatud ruutudega: 1 punkt.
== Mobiiliversioon ehk responsive design ==
* Mõõdad ja kuvad tulemuste tabelis mängu peale kulunud aega: 1 punkt.
 
* Laevade ise-paigutamine mängu alguses: 1 punkt (see on veidi keerulisem ja jäta viimaseks!)
Loe kõigepealt läbi [http://www.thesitewizard.com/css/mobile-friendly-responsive-design.shtml see sissejuhatus], siis vaata [http://www.w3schools.com/w3css/w3css_mobile.asp w3schoolsi näiteid] ja jätkuks võid lugeda veel [https://www.smashingmagazine.com/2010/07/how-to-use-css3-media-queries-to-create-a-mobile-version-of-your-website/ media query] kohta.
* Mobiilivariant, mis näeb hea välja ja on mugavalt mängitav: 3 punkti. Selleks pead mobiilivariandis saavutama:
 
** Sisse zoomida ei ole vaja ja parem, kui ei saagi.
Kursuse põhilehel on samuti lisaks linke mõistlikele tutorialitele ja näidetele.
** Paremale-vasakule scrollida ei saa, kõik scrollimine on ülevalt alla.
** Maatriks on enamvähem lehe vasakust äärest parema ääreni.
** Suure display variant ja mobiilivariant on sama lähtekoodiga, mitte kaks täiesti erinevat lehte.
** Suure display paigutus (tavapaigutus) on teistsugune, kui mobiilipaigus, kindlasti ses mõttes, et tavapaigutuses ei raisata liiga palju ruumi, nupud, fondid jne pole liiga suured, maatriksid on kõrvuti (mobiilis üksteise all) ja scrollida pole üldse vaja, ka mitte üles-alla.


== Koodist arusaamine ja plagiaadikontroll ==
== Koodist arusaamine ja plagiaadikontroll ==
70. rida: 76. rida:
Kogu esitatud kood peab jääma prax2 alamkataloogi alles kuni kursuse lõpuni.
Kogu esitatud kood peab jääma prax2 alamkataloogi alles kuni kursuse lõpuni.


Teiste inimeste - ka õppejõu - kirjutatud lahendusi aluseks võtta ei ole OK. Kui juhendaja tuvastab, et sinu koodil on väga suured sarnasused mõne teise koodiga, siis pead töö uuesti kirjutama. Järelkontrollid toimuvad ka pärast töö esitamist.
Teiste inimeste - ka õppejõu - kirjutatud lahendusi aluseks võtta ei ole OK. Samas on nende lahendustega tutvumine igati soovitav (googelda minesweeper javascript).


Kõigist osadest oma koodis pead ise hästi aru saama ja suutma neid juhendajale selgitada, kui ta küsib. Ei ole OK võtta võrgust juppe, mille funktsioneerimisest sa aru ei saa (ehk, kui võtad mõne jupi, siis tee endale kõigepealt selgeks, mida see jupp täpselt teeb).
Kui juhendaja tuvastab, et sinu koodil on väga suured sarnasused mõne teise koodiga, siis pead (parimal juhul) töö uuesti kirjutama. Järelkontrollid toimuvad ka pärast töö esitamist.


== Css-i ja javascripti teegid ja erivariandid javascriptist ==  
Peaasi: kõigist osadest oma koodis pead ise hästi aru saama ja suutma neid juhendajale selgitada, kui ta küsib. Ei ole OK võtta võrgust juppe, mille funktsioneerimisest sa aru ei saa (ehk, kui võtad mõne jupi, siis tee endale kõigepealt selgeks, mida see jupp täpselt teeb).
 
== CSS-i ja javascripti teegid ja erivariandid javascriptist ==  


Väliste teekide, ntx [http://jquery.com/ Jquery] või [http://getbootstrap.com Bootstrap] kasutamine on ok, <b>aga</b> siis sa pead hästi aru saama, mida sinu tehtavad teegi-callid või stiilid teevad.  
Väliste teekide, ntx [http://jquery.com/ Jquery] või [http://getbootstrap.com Bootstrap] kasutamine on ok, <b>aga</b> siis sa pead hästi aru saama, mida sinu tehtavad teegi-callid või stiilid teevad.  
Reaalselt on see praks piisavalt lihtne selleks, et teekide kasutamine vajalik ei oleks. Kui otsustad siiski teeki kasutada, siis väga soovitav on
Reaalselt on see praks piisavalt lihtne selleks, et teekide kasutamine vajalik ei oleks. Kui otsustad siiski teeki kasutada, siis väga soovitav on
valida [http://jquery.com/ jquery] kui suhteliselt lihtne ja domineerivalt populaarseim javascripti teek, kujunduse jaoks aga [http://getbootstrap.com Bootstrap].
valida [http://jquery.com/ jquery] kui suhteliselt lihtne ja domineerivalt populaarseim javascripti teek, kujunduse jaoks aga [http://getbootstrap.com Bootstrap]. [https://facebook.github.io/react/ React] ja  selletaolised suured teegid ja frameworkid on selle praksi jaoks täielik overkill.


Kogu javascript peab olema esitatud minimiseerimata ja nö normaalse taandega, et oleks kergesti loetav.  
Kogu javascript peab olema esitatud minimiseerimata ja nö normaalse taandega, et oleks kergesti loetav.  


Ei ole OK kasutada süsteeme nagu typescript, mis kompileerivad sinu lähtekoodi javascriptiks: see muudaks juhendajate töö liiga raskeks.
Ei ole OK kasutada süsteeme nagu typescript, mis kompileerivad sinu lähtekoodi javascriptiks: see muudaks juhendajate töö liiga raskeks. Peab olema võimalik otse koodi muuta ilma vajaduseta kasutada transpilereid nagu [https://babeljs.io/ babel], pakkijaid nagu [https://en.wikipedia.org/wiki/Webpack webpack] jne.


== Soovitusi htmli ja cssi osas ==
== Soovitusi htmli ja cssi osas ==
88. rida: 96. rida:
Hea mõte on algul jagada lehekülg mitmeks horisontaalseks reaks ja vertikaalseks kõrvuti tulbaks. Kõige lihtsam - ja selle rakenduse jaoks piisav - on seada ridadele ja tulpadele fikseeritud laiused ja kõrgused. NB! Selline fiks laiuste/kõrguste lähenemine ei ole enamiku harilike veebisaitide jaoks päris hea mõte, ja on hoopis halb mobiilile sobiva saidi tegemisel.  
Hea mõte on algul jagada lehekülg mitmeks horisontaalseks reaks ja vertikaalseks kõrvuti tulbaks. Kõige lihtsam - ja selle rakenduse jaoks piisav - on seada ridadele ja tulpadele fikseeritud laiused ja kõrgused. NB! Selline fiks laiuste/kõrguste lähenemine ei ole enamiku harilike veebisaitide jaoks päris hea mõte, ja on hoopis halb mobiilile sobiva saidi tegemisel.  


[http://www.w3.org/Style/Examples/007/center.en.html Siit] ja [http://www.thesitewizard.com/css/center-div-block.shtml siit] leiad tsentreerimise õpetused (point: <tt>margin-left: auto; margin-right: auto;</tt>)
[http://www.w3.org/Style/Examples/007/center.en.html Siit] ja [http://www.thesitewizard.com/css/center-div-block.shtml siit] leiad horisontaalse tsentreerimise õpetused (point: <tt>margin-left: auto; margin-right: auto;</tt>)
 
Vertikaalset tsentreerimist on raskem teha, aga siin on heaks abiks [https://philipwalton.github.io/solved-by-flexbox/demos/vertical-centering/ flexbox]. Flexboxi kohta saad pikemalt lugeda näiteks [https://css-tricks.com/snippets/css/a-guide-to-flexbox/ siit].
 
Tulpade tegemine puhtalt div-dega ei ole ka päris triviaalne.
 
<!--


Tulpade tegemine tabeliga on lihtne, aga puhtalt div-dega ei ole päris triviaalne. Vaata [http://robertnyman.com/2010/02/24/css-display-inline-block-why-it-rocks-and-why-it-sucks/ seda] ja [http://www.quirksmode.org/css/display.html seda] või [http://coding.smashingmagazine.com/2009/10/19/the-mystery-of-css-float-property/ seda] seletust põhimõtete osas. Kogu värgi lehekülje keskele panekuks, headeri ja footeri lisamiseks jne pakuvad ideid ja näiteid need õpetused, alates lihtsamast ja lõpetades põhjalikuga:
Vaata [http://robertnyman.com/2010/02/24/css-display-inline-block-why-it-rocks-and-why-it-sucks/ seda] ja [http://www.quirksmode.org/css/display.html seda] või [http://coding.smashingmagazine.com/2009/10/19/the-mystery-of-css-float-property/ seda] seletust põhimõtete osas. Kogu värgi lehekülje keskele panekuks, headeri ja footeri lisamiseks jne pakuvad ideid ja näiteid need õpetused, alates lihtsamast ja lõpetades põhjalikuga:
<ul>
<ul>
<li>[http://www.w3schools.com/cssref/tryit.asp?filename=trycss_float6 w3cschooli hea väike terviknäide]
<li>[http://www.w3schools.com/cssref/tryit.asp?filename=trycss_float6 w3cschooli hea väike terviknäide]
97. rida: 111. rida:
</ul>
</ul>


Täiendavate ideede ja juhatuste jaoks vaata lihtsalt kursuse lehelt viidatud materjale CSS bloki alt.
-->


Moblale sobiva lehe põhimõtete kohta tasub lugeda [https://developer.apple.com/design/tips/ neid lihtsaid suuniseid Applelt]
== Soovitusi javascripti osas ja kasulikke näiteid ==


== Soovitusi javascripti osas ==
Kuidas käiku teha? Tee iga ruut kas tabeli elemendina või div-na (viimane on keerulisem) ja pane sinna nupule [http://www.w3schools.com/jsref/event_onclick.asp onclick atribuudina] javascripti call, mis kutsub välja käigutegemise funktsiooni näiteks nii:
<pre>
...
function move(x,y) {
...
}
...
<td id="s_3_4" class="gsquare" onclick="move(3,4)"></td>
</pre>


Kui sa ei kasuta mõnda javascripti teeki nagu jquery (algajale mittesoovitav, kuna tekitab lisakeerukusi!) siis on hea mõte töö lihtsustamiseks teha ise väikeseid abifunktsioone,
Igal ruudul peaks olema <b>id</b> mille kaudu saad ruudu sisu muuta. Mõistlik on teha nii, et id leiad kergesti ruudu koordinaatidest.  
näiteks function gid(x) {return document.getElementById(x); } et ei peaks kogu aeg pikalt välja kirjutama.


Debugimiseks on kõige lihtsam panna koodi sisse alert(...), aga mugavam ja parem on kasutada funktsiooni console.log(...) mille võid omakorda panna oma abifunktsiooni a la
Ruudul võiks olla <b>class</b> et kujundust kergesti muuta. Samas saab klassi/stiili anda ka nö üldisemalt tabeli td elementidele (või vastavalt div-dele).
function debug(x) { console.log(x) }. console.log trükib tulemuse brauseri debugeri konsooli (Firefoxis käivita (ja enne installi!) firebug ja vaata firebugi aknast "console" tabi alt, Chromes otsi developer tools või javascript console).


Täiendavate ideede ja juhatuste jaoks vaata lihtsalt kursuse lehelt viidatud materjale javascripti bloki alt.
Üks esimesi asju, mida su javascripti kood peaks tegema, on pommide paigutamine massiivi, näiteks nii: pommivaba element on 0 ja pommiga 1 ja inimese poolt klikatud (pommivaba) ruut on 2.


== Näitekood laevade paigutamiseks ==
Tasub teada, et [http://www.w3schools.com/js/js_arrays.asp javascripti massiivid] on erinevad java ja pythoni massiividest: nad on korraga nagu listid või javascripti [http://www.w3schools.com/js/js_objects.asp objektid] ehk võti-väärtus hashid, neis võivad olla augud ja neid võib suurendada käigu pealt, nö ette valmis tegemata. Mh on kõik array elemendid objekti positsiooni-nimel olevad väärtused, ehk arr.miski on sama, mis arr['miski'].
Sul võib olla huvitav vaadata array meetodeid [http://www.w3schools.com/jsref/jsref_obj_array.asp siit]


Laevade juhuslikul paigutusel ei ole rangeid nõudeid "juhuslikkuse" osas: lihtsalt paigutus peaks igakord "juhuslikult" muutuma, laevad ei tohi olla kõrvuti ja otsapidi koos, suuremal laual peaks olema rohkem laevu.
Mitmemõõtmelise massiivi saad teha ja sinna väärtusi anda näiteks nii:


Siin all on veidi poolik kood, mis paigutab randomiga laevu tabelisse laiusega size. Sa ei pea seda üldse kasutama, aga ta võib olla abiks.  
<pre>
// first create a list of empty sublists
var board=[];
for (var i=0;i<10;i++) {
  board[i] = []; // insert an empty list to position i
}
...


Ta eeldab, et sul on juba olemas javascripti array <b>table</b> kujul (näitena küljepikkuse 3 jaoks)
// now insert new elements to sublists:
<pre>
board[0][1]=0;
[[0,0,0],[0,0,0],[0,0,0]]
board[0][3]=1;
</pre>
...
ja muudab selle table sisu, täites laevaruudud numbritega 1, näiteks selliseks:
<pre>
[[1,1,0],[0,0,0],[0,1,1]]
</pre>
</pre>


Seejuures pannakse igale reale üks laev, vaadates, et ta ei sattuks eelmise rea
Siin on sulle abiks funktsioon, mis ehitab valmis laua massiivi ja paigutab sinna pommid (seda funktsiooni võid soovi korral otse oma praktikumi kopeerida):
laevaga külgepidi kokku.


Kui 20 randomkatsel rea kohta sobivat positsiooni ei leitud  (näiteks kolmese küljepikkusega tabelis ei olegi võimalik teist rida täita!) siis jäetakse see rida
<pre>
lihtsalt tühjaks.


Sul on mõistlik seda koodi edasi arendada selliselt, et:
// returns board as list of lists like [[0,1],[1,0]]
// size is the row/col length, bombs the number of bombs to insert
// NB! This algorithm may become slow if the nr of bombs is close to
// the board area (i.e. almost all the board covered with bombs)
//
// call it like this: var board=makeBoard(10,5);


* ta ei kasutaks alati arrayd nimega <i>table</i> vaid sa saaksid selle array ehk tabeli nime ise ette anda.
function makeBoard(size,bombs) {
* sa saaksid ette anda soovitud laevade arvu: kui soovitud laevu on hulga vähem, kui ridu, siis võiks lihtsalt mõned read randomiga vahele jätta: muidugi, soovitud laevade arv peaks kokku tulema.
  var board=[];
 
  if (bombs>=size*size) throw "too many bombs for this size";
 
  // initialize board, filling with zeros
  for (var x=0; x<size; x++) {
    board[x]=[]; // insert empty subarray
    for (var y=0; y<size; y++) board[x][y]=0;
  }


funktsioon <i>gid</i> on lihtsalt enda tehtud abifunktsioon  <tt>function gid(x) {return document.getElementById(x); }</tt>
  // now fill board with bombs in random positions
  var i=bombs;
  while (i>0) {
    // generate random x and y in range 0...size-1
    x=Math.floor(Math.random() * size);
    y=Math.floor(Math.random() * size);
    // put bomb on x,y unless there is a bomb already
    if (board[x][y]!=1) {
      board[x][y]=1;
      i--; // bomb successfully positioned, one less to go
      //console.log("positioned "+x+", "+y+" yet to go "+i);
    }
  }
 
  return board;
}


<pre>
function fillBoard(size) {
  var r,c,i,foundok,count;
  size=parseInt(size);
  // loop over all the rows, to place one ship to each (most) rows   
  for(i=0;i<size;i++) {
    foundok=false;
    count=0;
    // try different random column positions until OK pos found:
    // if no position OK during 20 tries, give up and
    // do not put a ship on this line at all
    while(!foundok && count<20) {
      c=Math.floor(Math.random()*(size-1));
      console.log("try ship for row "+i+" at col "+c);
      if (i>0) {
        if (table[i-1][c]==1) { foundok=false; }
        else if (c>0 && table[i-1][c-1]==1) { foundok=false; }
        else if (c<size-1 && table[i-1][c+1]==1) { foundok=false; }
        else foundok=true;
      } else {
        foundok=true;
      } 
      count++;
    } 
    if (foundok) {
      console.log("got ship for row "+i+" at col "+c); 
      table[i][c]=1;
      table[i][c+1]=1;
      console.log(table);
    }     
  }   
}
</pre>
</pre>


Järgnev on lihtne näide numbritega 0 ja 1 täidetud andmetabeli (parameeter tbl) kuvamiseks
Samuti võib sulle abiks olla funktsioon, mis tagastab ruudu kõigi naabrite koordinaatide listi (ka seda funktsiooni võid soovi korral otse oma praktikumi kopeerida):
html tabelis, kus iga ruut on id-ga <i>divid+reanr+tulbanr</i> a la "mytable21". Arusaadavalt eeldab see kood, et selliste id-dga html tabel on juba loodud.


<pre>
<pre>


function showBoard(tbl,divid) {
// returns a list of neighbour square coordinate pairs for a board
  var r,c,place;
// with a given size. Examples:
  console.log(tbl);
// neighbours(10,4,4) gives [[3,3],[3,4],[3,5],[4,3],[4,5],[5,3],[5,4],[5,5]]
   for(r=0;r<tbl.length;r++) {
// neighbours(10,0,0) gives [[0,1],[1,0],[1,1]]
     for(c=0;c<tbl.length;c++) {
// neighbours(10,9,9) gives [[8,8],[8,9],[9,8]]
       console.log((divid+r)+c);
 
       place=gid((divid+r)+c);
function neighbours(size,x,y) {
      if (tbl[r][c]==1) {
  var list=[];
         place.innerHTML="s"
   for (var i=-1; i<=1; i++) {  
        place.style.backgroundColor="#666666";
     for (var j=-1; j<=1; j++) {
      } else {
       // square is not a neighbour of itself
        place.innerHTML=""
      if (i==0 && j==0) continue;
        place.style.backgroundColor="#eeeeee";
       // check whether the the neighbour is inside board bounds
       }    
      if ((x+i)>=0 && (x+i)<size && (y+j)>=0 && (y+j)<size) {
         list.push([x+i,y+j]);
       }
     }
     }
   }
   }
}
  return list;
}


</pre>
</pre>


== Dijkstra server ==
== Tehnoloogianõuded ==
 
Kodutööde tarbeks on kasutusel server nimega dijkstra: kindlasti loe [[Dijkstra server|dijkstra kasutusõpetust]].
 
Kõik kodutööd tuleb riputada Dijkstra serverisse, et õppejõud saaks lähtekoode Dijkstra serveris vaadata ja plagiaadituvastus-tarkvara abil kontrollida.


Nõuded kataloogile/failinimedele:
Kogu rakendus peab kasutama ainult html+css+javascripti ja olema üles laetud serverisse staatiliste
lehtedena.


* Teine kodutöö tuleb panna sinu kodukataloogi alamkataloogi <b><tt>public_html/prax2</tt></b> mille pead ise looma.
Ära kasuta lehe struktureerimiseks üksteise sees olevaid tabeleid, vaid div-e ja css-i.  
* Kodutöö html-põhifaili nimi peab olema <tt>index.html</tt>.
* Kodutöö sinu tehtud javascripti-fail fail olgu nimega <tt>prax2.js</tt> ning sinu tehtud css-fail nimega <tt>prax2.css</tt>
* Pildifailide ja mujalt võetud javascripti/css teekide osas mingeid nõudeid ei ole.


Enne failide serverisse riputamist on mõistlik teha kogu süsteem valmis lihtsalt oma arvutis/arvutiklassi arvutis.
Sisuliselt tabeli kujul oleva info (näiteks mängulaud ise) esitamine html tabelina on aga täiesti ok.

Viimane redaktsioon: 18. september 2018, kell 14:39

IT
IT

Mida tuleb teha

Sinu ülesandeks on kirjutada minesweeperi mängu brauseris töötav tugevalt lihtsustatud eriversioon, kasutades ainult html-i, css-i ja javascripti.

Loe kõigepealt läbi ülevaade wikipediast ja mängi katseks seda varianti ja seda varianti.

Valmis töö tuleb riputada üles ülikooli serverisse dijkstra sinu kataloogi prax2 alla. Ehk, arvestatakse ainult dijkstra-s olevaid töid.

Selles praksis teed arvuti vastu mängimise variandi, aga kolmandas praktikumis tuleb samale mängule lisada serveripoolset funktsionaalsust, näiteks tulemuste salvestamine ja vaatamine ja statistika, pooliku mängu salvestamine ja hilisem jätkamine ja samuti mäng kahe inimese vahel, mis toimub siis serverirakenduse vahendusel.

Detailid

Sa pead realiseerima minesweeperi täpselt alltoodud nõuete järgi: teistmoodi funktsionaalsusega lahendused ei sobi!

Tehnoloogilises mõttes (a la kas kasutada jQueryt, bootstrappi, reacti jne jne) piiranguid ei ole, kuid algajatele on soovitus kõiki lisatööriistu vältida: need on esialgu keerulised ja kulutavad aega,

Nõuded siis:

Sinu programm peab algul mängijale pakkuma

  • valikuna kolme variandi vahel laua suuruse: 6, 9 või 16 ruutu.
  • ja tekstiväljal sisestamiseks pommide arvu N.

Lisaks on näha nupp "Alusta". Lauda esialgu ei kuvata.

Peale "Alusta" nupule vajutamist kontrollitakse, kas valikud on tehtud. Kui ei, hoiatatakse. Kui jah, kuvatakse tühi laud.

Laud kuva valikute alla ja ära neid valikuid ära kustuta: las jäävad näha.

Laua disaini ära tee klassikalise pseudo-3d ja varjudega, vaid lihtsalt joontest ruudustikuna.

Lisaks laua kuvamisele arvuta välja pommide massiiv, paigutades N pommi juhuslikult laiali (selle kohta leiad all näitekoodi).

Kui kasutaja vajutab mõnele laua ruudule (avab ruudu) siis:

  • Kontrolli, kas tabati pommi, ja kui, siis näita kasutajale, et ta on kaotanud.
  • Kontrolli, kas kõik pommivabad ruudud on avatud, ja kui jah, siis näita kasutajale, et ta on võitnud.
  • Vastasel juhul (normaalolukord) tee järgmist:
    • märgi avatud ruut näiteks teise taustavärviga, rehkenda kokku avatud ruudu kõrvalruutudel olevate pommide arv ning kuva see avatud ruudu sisse. Kõrvalruutusid on ruudul kokku 8, kui ta pole just laua äärel. Kõrvalruutude leidmiseks leiad all näitekoodi.
    • kui avatud ruudu sisse kirjutati nullist suurem arv, on käik lõppenud ja oota uut käiku. Ainult avatud ruut sai sel juhul numbri.
    • kui avatud ruudu sisse kirjutati 0, siis rehkenda kokku naaberruutudel olevate pommide arvud ja kuva iga naaberrudu sisse. Iga naaberruut saab seega numbri, aga ta ei ole märgitud avatuks,

NB! Järgmised lihtsustused on rangelt nõutud, st nende tavafeatuuride tegemine on keelatud:

  • Minesweeperi tüüpilist funktsionaalsust - automaatset suure hulga ruutude avamist - ära tee.
  • Ruutude äramärkimist lipukesega ära tee.
  • Allesjäänud pommide arvu, tehtud käikude arvu, kulunud aega jms ära kuva.

Laua alla kuva seniste tulemuste loetelu: iga rida selles ütleb, kas kaotasid või võitsid ja mitu käiku kulus. Iga järgmine lõppenud mäng lisab sinna ühe rea.

Info paigutus ekraanil peab olema stabiilne, tekst/nupud ei tohi hüpata vahel ühte, vahel teise kohta. Leht peab olema selge, arusaadava ja kena disainiga, mõttetut/segast infot ja arusaamist raskendavaid kujunduselemente ära kasuta. Arvesta kindlasti selle juhendi soovitustega.

Kogu kood peab olema laetud dijkstra serverisse prax2 alamkataloogi. Pealeht olgu nimega index.html.

Kohustuslikud ja mittekohustuslikud osad ja punktiarvestus

Kokku võid saada 12 punkti, mis jagunevad selliselt:

Kui suudad kuvada laua ning käigud töötavad ok (naaberruutude arvud kuvatakse ok), saad praktikumi arvestatud ja kokku 6 punkti.

Kui sul on realiseeritud valikud (laua suurus ja pommide arv) ning suudad tuvastada ja kuvada võidu/kaotuse, saad lisaks 2 punkti.

Kui realiseerid tulemuste loetelu kuvamise, saad veel lisaks 2 punkti.

Kui mängu kujundus on kena ja arusaadav nii tava-arvutis kui mobiilis (ei ole vaja scrollida vasakule-paremale, elemendid ei ole väga väikesed jne), siis saad lisaks 2 punkti.


Mobiiliversioon ehk responsive design

Loe kõigepealt läbi see sissejuhatus, siis vaata w3schoolsi näiteid ja jätkuks võid lugeda veel media query kohta.

Kursuse põhilehel on samuti lisaks linke mõistlikele tutorialitele ja näidetele.

Koodist arusaamine ja plagiaadikontroll

Kogu esitatud kood peab jääma prax2 alamkataloogi alles kuni kursuse lõpuni.

Teiste inimeste - ka õppejõu - kirjutatud lahendusi aluseks võtta ei ole OK. Samas on nende lahendustega tutvumine igati soovitav (googelda minesweeper javascript).

Kui juhendaja tuvastab, et sinu koodil on väga suured sarnasused mõne teise koodiga, siis pead (parimal juhul) töö uuesti kirjutama. Järelkontrollid toimuvad ka pärast töö esitamist.

Peaasi: kõigist osadest oma koodis pead ise hästi aru saama ja suutma neid juhendajale selgitada, kui ta küsib. Ei ole OK võtta võrgust juppe, mille funktsioneerimisest sa aru ei saa (ehk, kui võtad mõne jupi, siis tee endale kõigepealt selgeks, mida see jupp täpselt teeb).

CSS-i ja javascripti teegid ja erivariandid javascriptist

Väliste teekide, ntx Jquery või Bootstrap kasutamine on ok, aga siis sa pead hästi aru saama, mida sinu tehtavad teegi-callid või stiilid teevad. Reaalselt on see praks piisavalt lihtne selleks, et teekide kasutamine vajalik ei oleks. Kui otsustad siiski teeki kasutada, siis väga soovitav on valida jquery kui suhteliselt lihtne ja domineerivalt populaarseim javascripti teek, kujunduse jaoks aga Bootstrap. React ja selletaolised suured teegid ja frameworkid on selle praksi jaoks täielik overkill.

Kogu javascript peab olema esitatud minimiseerimata ja nö normaalse taandega, et oleks kergesti loetav.

Ei ole OK kasutada süsteeme nagu typescript, mis kompileerivad sinu lähtekoodi javascriptiks: see muudaks juhendajate töö liiga raskeks. Peab olema võimalik otse koodi muuta ilma vajaduseta kasutada transpilereid nagu babel, pakkijaid nagu webpack jne.

Soovitusi htmli ja cssi osas

Hea mõte on algul jagada lehekülg mitmeks horisontaalseks reaks ja vertikaalseks kõrvuti tulbaks. Kõige lihtsam - ja selle rakenduse jaoks piisav - on seada ridadele ja tulpadele fikseeritud laiused ja kõrgused. NB! Selline fiks laiuste/kõrguste lähenemine ei ole enamiku harilike veebisaitide jaoks päris hea mõte, ja on hoopis halb mobiilile sobiva saidi tegemisel.

Siit ja siit leiad horisontaalse tsentreerimise õpetused (point: margin-left: auto; margin-right: auto;)

Vertikaalset tsentreerimist on raskem teha, aga siin on heaks abiks flexbox. Flexboxi kohta saad pikemalt lugeda näiteks siit.

Tulpade tegemine puhtalt div-dega ei ole ka päris triviaalne.


Soovitusi javascripti osas ja kasulikke näiteid

Kuidas käiku teha? Tee iga ruut kas tabeli elemendina või div-na (viimane on keerulisem) ja pane sinna nupule onclick atribuudina javascripti call, mis kutsub välja käigutegemise funktsiooni näiteks nii:

...
function move(x,y) {
 ...
}
...
<td id="s_3_4" class="gsquare" onclick="move(3,4)"></td>

Igal ruudul peaks olema id mille kaudu saad ruudu sisu muuta. Mõistlik on teha nii, et id leiad kergesti ruudu koordinaatidest.

Ruudul võiks olla class et kujundust kergesti muuta. Samas saab klassi/stiili anda ka nö üldisemalt tabeli td elementidele (või vastavalt div-dele).

Üks esimesi asju, mida su javascripti kood peaks tegema, on pommide paigutamine massiivi, näiteks nii: pommivaba element on 0 ja pommiga 1 ja inimese poolt klikatud (pommivaba) ruut on 2.

Tasub teada, et javascripti massiivid on erinevad java ja pythoni massiividest: nad on korraga nagu listid või javascripti objektid ehk võti-väärtus hashid, neis võivad olla augud ja neid võib suurendada käigu pealt, nö ette valmis tegemata. Mh on kõik array elemendid objekti positsiooni-nimel olevad väärtused, ehk arr.miski on sama, mis arr['miski']. Sul võib olla huvitav vaadata array meetodeid siit

Mitmemõõtmelise massiivi saad teha ja sinna väärtusi anda näiteks nii:

// first create a list of empty sublists
var board=[];
for (var i=0;i<10;i++) {
  board[i] = []; // insert an empty list to position i
}
...

// now insert new elements to sublists:
board[0][1]=0;
board[0][3]=1;
...

Siin on sulle abiks funktsioon, mis ehitab valmis laua massiivi ja paigutab sinna pommid (seda funktsiooni võid soovi korral otse oma praktikumi kopeerida):


// returns board as list of lists like [[0,1],[1,0]]
// size is the row/col length, bombs the number of bombs to insert
// NB! This algorithm may become slow if the nr of bombs is close to
// the board area (i.e. almost all the board covered with bombs)
//
// call it like this: var board=makeBoard(10,5);

function makeBoard(size,bombs) {
  var board=[]; 
  
  if (bombs>=size*size) throw "too many bombs for this size";
  
  // initialize board, filling with zeros
  for (var x=0; x<size; x++) {
    board[x]=[]; // insert empty subarray
    for (var y=0; y<size; y++) board[x][y]=0;
  }

  // now fill board with bombs in random positions
  var i=bombs;
  while (i>0) {
    // generate random x and y in range 0...size-1
    x=Math.floor(Math.random() * size);
    y=Math.floor(Math.random() * size);
    // put bomb on x,y unless there is a bomb already
    if (board[x][y]!=1) {
      board[x][y]=1;
      i--; // bomb successfully positioned, one less to go
      //console.log("positioned "+x+", "+y+" yet to go "+i);
    }
  }
  
  return board;
}

Samuti võib sulle abiks olla funktsioon, mis tagastab ruudu kõigi naabrite koordinaatide listi (ka seda funktsiooni võid soovi korral otse oma praktikumi kopeerida):


// returns a list of neighbour square coordinate pairs for a board 
// with a given size. Examples:
// neighbours(10,4,4) gives [[3,3],[3,4],[3,5],[4,3],[4,5],[5,3],[5,4],[5,5]]
// neighbours(10,0,0) gives [[0,1],[1,0],[1,1]]
// neighbours(10,9,9) gives [[8,8],[8,9],[9,8]]

function neighbours(size,x,y) {
  var list=[];
  for (var i=-1; i<=1; i++) {    
    for (var j=-1; j<=1; j++) {
      // square is not a neighbour of itself
      if (i==0 && j==0) continue;
      // check whether the the neighbour is inside board bounds
      if ((x+i)>=0 && (x+i)<size && (y+j)>=0 && (y+j)<size) {
        list.push([x+i,y+j]);  
      }
    }
  }
  return list;
}  

Tehnoloogianõuded

Kogu rakendus peab kasutama ainult html+css+javascripti ja olema üles laetud serverisse staatiliste lehtedena.

Ära kasuta lehe struktureerimiseks üksteise sees olevaid tabeleid, vaid div-e ja css-i.

Sisuliselt tabeli kujul oleva info (näiteks mängulaud ise) esitamine html tabelina on aga täiesti ok.