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

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


== 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].
<!--
== <font color="red"> NB! </font> ==


Valmis töö tuleb riputada üles ülikooli serverisse dijkstra sinu kataloogi prax2 alla. Ehk, arvestatakse ainult dijkstra-s olevaid töid.
<font color="red">
Hetkel on praksiülesanne muutmisel, palun ignoreeri allolevat poolikut teksti!
</font>


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 ==
== Mida tuleb teha ==


Sa pead realiseerima minesweeperi täpselt alltoodud nõuete järgi: teistmoodi funktsionaalsusega lahendused ei sobi!
Sinu ülesandeks on kirjutada
[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.


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,
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.


Nõuded siis:
Ühe mängija asemel mängib sinu programmis arvuti, st programmi kasutaja mängib arvuti vastu.


Sinu programm peab algul mängijale pakkuma
Valmis töö tuleb riputada üles ülikooli serverisse dijkstra (vaata altpoolt). Ehk, arvestatakse ainult dijkstra-s olevaid töid.
* 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.
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.


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


Laud kuva valikute alla ja ära neid valikuid ära kustuta: las jäävad näha.
Meie praksiülesande detailid ja erisused standardsest laevade pommitamisest on järgmised:  


Laua disaini ära tee klassikalise pseudo-3d ja varjudega, vaid lihtsalt joontest ruudustikuna.
* Lihtsustus: kasutame ainult ühte tüüpi laeva: kahene horisontaalpaigutusega laev. Ehk, alati kaks kõrvuti horisontaalset ruutu.
* 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.


Lisaks laua kuvamisele arvuta välja pommide massiiv, paigutades N pommi juhuslikult laiali (selle kohta leiad all näitekoodi).
Kõiki eeltoodud nõudeid tuleb järgida, klassikaline laevade pommitamine praksilahenduseks ei sobi.
 
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 [[htmli kujunduse üldpõhimõtted| selle juhendi soovitustega]].
 
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 ==


Kokku võid saada 12 punkti, mis jagunevad selliselt:
Eeltoodud nõuete punktid peavad arvestamiseks olema täidetud, nad annavad kokku 6 punkti. Lisaks - kuni maksimaalse 12ni - saad teha järgmised osad:
 
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 ==
* Kuvad oma laevasid pildina, mitte lihtsalt märgendatud ruutudega: 1 punkt.
 
* Mõõdad ja kuvad tulemuste tabelis mängu peale kulunud aega: 1 punkt.
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.
* Laevade ise-paigutamine mängu alguses: 1 punkt (see on veidi keerulisem ja jäta viimaseks!)
 
* Mobiilivariant, mis näeb hea välja ja on mugavalt mängitav: 3 punkti. Selleks pead mobiilivariandis saavutama:
Kursuse põhilehel on samuti lisaks linke mõistlikele tutorialitele ja näidetele.
** Sisse zoomida ei ole vaja ja parem, kui ei saagi.
** 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 ==
76. rida: 70. 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. Samas on nende lahendustega tutvumine igati soovitav (googelda minesweeper javascript).
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.


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.
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).


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 ==  
 
== 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]. [https://facebook.github.io/react/ React] ja  selletaolised suured teegid ja frameworkid on selle praksi jaoks täielik overkill.
valida [http://jquery.com/ jquery] kui suhteliselt lihtne ja domineerivalt populaarseim javascripti teek, kujunduse jaoks aga [http://getbootstrap.com Bootstrap].


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. 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.
Ei ole OK kasutada süsteeme nagu typescript, mis kompileerivad sinu lähtekoodi javascriptiks: see muudaks juhendajate töö liiga raskeks.


== Soovitusi htmli ja cssi osas ==
== Soovitusi htmli ja cssi osas ==
96. rida: 88. 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 horisontaalse 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 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.
 
<!--


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:
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:
<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]
111. rida: 97. 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:
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,
<pre>
näiteks function gid(x) {return document.getElementById(x); } et ei peaks kogu aeg pikalt välja kirjutama.
...
function move(x,y) {
...
}
...
<td id="s_3_4" class="gsquare" onclick="move(3,4)"></td>
</pre>


Igal ruudul peaks olema <b>id</b> mille kaudu saad ruudu sisu muuta. Mõistlik on teha nii, et id leiad kergesti ruudu koordinaatidest.  
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
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).


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).
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'].
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.
Sul võib olla huvitav vaadata array meetodeid [http://www.w3schools.com/jsref/jsref_obj_array.asp siit]


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.


Ta eeldab, et sul on juba olemas javascripti array <b>table</b> kujul (näitena küljepikkuse 3 jaoks)
<pre>
<pre>
// first create a list of empty sublists
[[0,0,0],[0,0,0],[0,0,0]]
var board=[];
</pre>
for (var i=0;i<10;i++) {
ja muudab selle table sisu, täites laevaruudud numbritega 1, näiteks selliseks:
  board[i] = []; // insert an empty list to position i
<pre>
}
[[1,1,0],[0,0,0],[0,1,1]]
...
</pre>


// now insert new elements to sublists:
Seejuures pannakse igale reale üks laev, vaadates, et ta ei sattuks eelmise rea
board[0][1]=0;
laevaga külgepidi kokku.
board[0][3]=1;
...
</pre>


Siin on sulle abiks funktsioon, mis ehitab valmis laua massiivi ja paigutab sinna pommid (seda funktsiooni võid soovi korral otse oma praktikumi kopeerida):
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
lihtsalt tühjaks.


<pre>
Sul on mõistlik seda koodi edasi arendada selliselt, et:


// returns board as list of lists like [[0,1],[1,0]]
* ta ei kasutaks alati arrayd nimega <i>table</i> vaid sa saaksid selle array ehk tabeli nime ise ette anda.
// size is the row/col length, bombs the number of bombs to insert
* 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.
// 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) {
funktsioon <i>gid</i> on lihtsalt enda tehtud abifunktsioon  <tt>function gid(x) {return document.getElementById(x); }</tt>
  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
<pre>
   var i=bombs;
function fillBoard(size) {
   while (i>0) {
   var r,c,i,foundok,count;
     // generate random x and y in range 0...size-1
  size=parseInt(size);  
     x=Math.floor(Math.random() * size);
   // loop over all the rows, to place one ship to each (most) rows   
    y=Math.floor(Math.random() * size);
  for(i=0;i<size;i++) {  
    // put bomb on x,y unless there is a bomb already
    foundok=false;
    if (board[x][y]!=1) {
    count=0;
      board[x][y]=1;
     // try different random column positions until OK pos found:
       i--; // bomb successfully positioned, one less to go
    // if no position OK during 20 tries, give up and  
       //console.log("positioned "+x+", "+y+" yet to go "+i);
     // 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);
  return board;
      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>


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):
Järgnev on lihtne näide numbritega 0 ja 1 täidetud andmetabeli (parameeter tbl) kuvamiseks
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>


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


</pre>
</pre>


== Tehnoloogianõuded ==
== Dijkstra server ==
 
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.


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


Ära kasuta lehe struktureerimiseks üksteise sees olevaid tabeleid, vaid div-e ja css-i.  
* Teine kodutöö tuleb panna sinu kodukataloogi alamkataloogi <b><tt>public_html/prax2</tt></b> mille pead ise looma.
* 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.


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

Redaktsioon: 18. september 2018, kell 14:35

Battleship
Battleship



Mida tuleb teha

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

Loe kõigepealt läbi ülevaade wikipediast ja mängi katseks standardset täisversiooni siin või siin või siin: see on hea insipiratsioon sinu enda mängu tegemiseks.

Ühe mängija asemel mängib sinu programmis arvuti, st programmi kasutaja mängib arvuti vastu.

Valmis töö tuleb riputada üles ülikooli serverisse dijkstra (vaata altpoolt). 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, samuti mäng kahe inimese vahel, mis toimub siis serverirakenduse vahendusel.

Detailid

Meie praksiülesande detailid ja erisused standardsest laevade pommitamisest on järgmised:

  • Lihtsustus: kasutame ainult ühte tüüpi laeva: kahene horisontaalpaigutusega laev. Ehk, alati kaks kõrvuti horisontaalset ruutu.
  • 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. NB! 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 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.

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:

  • Kuvad oma laevasid pildina, mitte lihtsalt märgendatud ruutudega: 1 punkt.
  • 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!)
  • 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.
    • 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

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.

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.

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.

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 tsentreerimise õpetused (point: margin-left: auto; margin-right: auto;)

Tulpade tegemine tabeliga on lihtne, aga puhtalt div-dega ei ole päris triviaalne. Vaata seda ja seda või 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:

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

Moblale sobiva lehe põhimõtete kohta tasub lugeda neid lihtsaid suuniseid Applelt

Soovitusi javascripti osas

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, 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 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.

Näitekood laevade paigutamiseks

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.

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.

Ta eeldab, et sul on juba olemas javascripti array table kujul (näitena küljepikkuse 3 jaoks)

[[0,0,0],[0,0,0],[0,0,0]]

ja muudab selle table sisu, täites laevaruudud numbritega 1, näiteks selliseks:

[[1,1,0],[0,0,0],[0,1,1]]

Seejuures pannakse igale reale üks laev, vaadates, et ta ei sattuks eelmise rea 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 lihtsalt tühjaks.

Sul on mõistlik seda koodi edasi arendada selliselt, et:

  • ta ei kasutaks alati arrayd nimega table vaid sa saaksid selle array ehk tabeli nime ise ette anda.
  • 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.

funktsioon gid on lihtsalt enda tehtud abifunktsioon function gid(x) {return document.getElementById(x); }

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); 
    }      
  }     
}

Järgnev on lihtne näide numbritega 0 ja 1 täidetud andmetabeli (parameeter tbl) kuvamiseks html tabelis, kus iga ruut on id-ga divid+reanr+tulbanr a la "mytable21". Arusaadavalt eeldab see kood, et selliste id-dga html tabel on juba loodud.


function showBoard(tbl,divid) {
  var r,c,place;
  console.log(tbl);
  for(r=0;r<tbl.length;r++) {
    for(c=0;c<tbl.length;c++) {
      console.log((divid+r)+c);
      place=gid((divid+r)+c);
      if (tbl[r][c]==1) {
        place.innerHTML="s"
        place.style.backgroundColor="#666666";
      } else {
        place.innerHTML=""
        place.style.backgroundColor="#eeeeee";
      }      
    }
  }  
}

Dijkstra server

Kodutööde tarbeks on kasutusel server nimega dijkstra: kindlasti loe 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:

  • Teine kodutöö tuleb panna sinu kodukataloogi alamkataloogi public_html/prax2 mille pead ise looma.
  • Kodutöö html-põhifaili nimi peab olema index.html.
  • Kodutöö sinu tehtud javascripti-fail fail olgu nimega prax2.js ning sinu tehtud css-fail nimega prax2.css
  • 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.