Tikumängu ülesanne
Allikas: Lambda
Praktikumitöö tuleb teha vastavalt siin failis
antud täpsustustele. Kõigepealt seletan,
kuidas tikumäng käib, siis seda, kuidas
seal võita, ning seejärel annan
juhendid ja soovitused programmeerimiseks.
Kuidas tikumängu mängitakse
---------------------------
Vaatame kõigepealt hästi lihtsat
varianti, siis kirjeldame selle väikest
üldistust, st natuke keerulisemat varianti.
Lihtsas variandis on algseisus laual kümme tikku:
| | | | | | | | | |
Kaks mängijat võtavad vaheldumisi laualt tikke
ära. Kumbki võib võtta kas ühe, kaks või kolm
tikku. Võtmata jätta ei tohi ja üle kolme võtta
ei või.
Kes võtab viimase tiku, on võitnud.
Näiteks võib mäng käia nii:
Mängija A võtab kaks tikku. Lauale jääb kaheksa:
| | | | | | | |
Mängija B võtab kolm tikku. Lauale jääb viis:
| | | | |
Mängija A võtab ühe tiku. Lauale jääb neli:
| | | |
Mängija B võtab ühe tiku. Lauale jääb kolm:
| | |
Mängija A võtab kõik kolm tikku, lauale ei
jää enam ühtegi ja mängija A on võitnud.
Keerukamas variandis on põhimõte sama, kuid:
- Laual võib algseisus olla suvaline arv tikke
(st päris palju, kasvõi sada)
- Maksimaalne võetav tikkude arv ei pruugi olla kolm,
vaid võib olla suvaline number kahest alates.
Keerukamas mänguvariandis on seega vaja enne mängu
algust kokku leppida:
- Algseisus olevate tikkude arv N
- Maksimaalne võetavate tikkud arv M.
Näiteks, M võib olla kaks - siis tohib võtta
kas ühe või kaks tikku. Kui M on viis, tohib
võtta kas 1,2,3,4 või 5 tikku.
Mängu käigus loomulikult M-i ei muudeta,
M lepitakse kokku enne mängu algust.
Kuidas tikumängus võita
-----------------------
Üks viis tikumängus võitmiseks oleks
mõelda ette oma võimalikud käiguvariandid,
vastase võimalikud käiguvariandid, seejärel
tekkivad oma käiguvariandid jne jne, justnagu
males või kabes.
Õnneks on tikumängu võimalik võita ka palju
lihtsamini: nii, et üldse pole vaja midagi
ette mõelda!
Vaatame näiteks lihtsat tikumängu: 10 tikku
algseisus (N=10) ja maksimaalselt kolm võetavat
tikku (M=3). Selge, et kui vastasel on tema
käigukorra ajal ees neli tikku:
| | | |
siis on vastane kindlas kaotusseisus: mina
saan igal juhul viimase tiku.
Kuidas teha nii, et vastasele jääks ette neli
tikku? Kui vastasel on ees kaheksa tikku:
| | | | | | | |
siis saan ma igal juhul tekidada olukorra,
kus peale tema käiku ja seejärel minu käiku
on temal ees neli tikku, ning seega saan
lõpuks võita.
Üldpõhimõte on järgmine:
- mängija on kaotusseisus, kui
jääk(N/(M+1))=0
see tähendab: kui jagan laual olevate
tikkude arvu arvuga M+1 ja võtan jäägi
(näiteks, 5/3 annab jäägi 2), siis seis
on kaotusseis, kui jääk on 0.
- igal muul juhul on mängija võiduseisus ning
võidukäigu saab ta arvutada sama põhimõtte
järgi:
võidukäik=jääk(N/(M+1))
Kuidas tikumängu praktikumis programmeerida
===========================================
Kõigepealt, sinu programm peab vastama järgmistele
nõuetele:
- Programm läheb käima käsurealt ja trükkimine ning
käikude lugemine toimub samuti lihtsalt käsurea
viisil, st mingeid eraldi aknaid programm ei tee.
- Programm suudab võiduseisust alati võita.
- Kaotusseisus teeb programm juhusliku reeglitega
lubatud käigu (näiteks, lihtsas tikumängus valib
programm nelja tikuga seisus käiguks juhuslikult
kas 1, 2 või 3).
- Enne mängu algust peab programm kasutajalt küsima
ja endale meelde jätma:
- algseisus olevate tikkude arvu N
- maksimaalse võetavate tikkude arvu M
- mängu alustaja (masin või inimene)
- Programm peab ise mängima vastavalt reeglitele
ja ei tohi lubada vastasel teha keelatud
käike (vastane ei tohi saada võtta 0
tikku või rohkem tikke, kui M). Kui vastane
proovib teha keelatud käiku, siis programm teatab,
et see pole lubatud käik ja küsib käiku uuesti.
- Programm peab inimmängijale arusaadavalt iga
oma käigu juures trükkima välja
- kõigepealt, laual olevate tikkude arvu
- seejärel oma käigu
- seejärel lauale jäävate tikkude arv
- seejärel küsima kas inimmängija käiku või
teatama oma võidust.
- Programm peab aru saama, kui programm või
inimmängija on võitnud ning selle info ilusti
välja trükkima.
- Kui mäng saab läbi, siis peab programm küsima
inimmängijalt, et kas too tahab veel mängida või
ei. Kui mängija ei taha rohkem mängida, siis
programm lõpetab töö.
- Programmi java koodis peab taande kasutamine
olema mõistlik ja ilus, samuti peab seal olema
mõistlikus koguses mõistlikke kommentaare!
Ilma kommentaarideta ja/või nõmeda taandega
programmi ei pruugi praktikumijuhendaja vastu võtta.
Järgnevalt mõned soovitused programmeerimiseks
==============================================
Alusta programmeerimist sellest, et kirjuta ise või
kopeeri endale HelloWorld programm, kompileeri
ja lase käima:
public class HelloWorld {
// A program to display the message
// "Hello World!" on standard output
public static void main(String[] args) {
System.out.println("Hello World!");
}
} // end of class HelloWorld
Seejärel kopeeri see fail "päris" tikumängu
failiks nimega Tikumang.java ja asenda tema
sees klassi nimi "HelloWorld" nimega "Tikumang".
NB! Jutumärke ära muidugi pane, täpitähti ära
kasuta, ning arvesta, et faili nimi ja
klassi nimi peavad olema samad (välja arvatud
.java lõpp) ja suured/väikesed tähed on erinevad.
Kompileeri see uus fail ka ära ja pane käima.
Nüüd hakka programmi kirjutama "main" funktsiooni
sisse, kus esialgu on ainult rida
System.out.println("Hello World!");
(selle rea võid ära ka kustutada).
Mingeid muid funktsioone pole vaja teha.
Programmi saab kokku panna lihtsalt if-dest,
tsüklitest, arvutustest, lugemisest ja
trükkimisest.
Kuidas trükkida:
----------------
Kasuta lihtsalt System.out.println
funktsiooni. Sellega saad trükkida nii
stringe kui arve.
Kui tahad, et trükitava lõpuks poleks
reavahet, kasuta hoopis
System.out.print funktsiooni (nime
lõpus puudub ln).
Kuidas lugeda inimmängija käike ja algseisu jne
-----------------------------------------------
Loe kõigepealt Ecki õpikust peatükk
2.4 (URL: http://math.hws.edu/javanotes/c2/s4.html)
Seal on õpetus, kuidas seda mugavalt teha.
Sinul läheb vaja funktsiooni TextIO.getInt(),
muid polegi otseselt vaja.
NB! Selleks, et kasutada TextIO.getInt()
funktsiooni, peab sinu arvutis sellesamas
kataloogis, kus on tikumängu programmi fail,
asuma Ecki kirjutatud programmifail
TextIO.java. Selle faili saad võrgust
tõmmata URL-ilt
http://math.hws.edu/javanotes/source/TextIO.java
ning ta oma kataloogi kirjutada.
Proovi ta ära ka kompileerida. Käima see
TextIO programm ise ei lähe, sest tal pole
main funktsiooni sees.
Idee selles, et kui Java kompilaator/mootor näeb
funktsiooni TextIO.getInt(), siis ta asub
otsima faili TextIO, kust seda funktsiooni leida
võiks. Otsib ta faili kõigepealt sealtsamast kataloogist,
kus sinu programmifail asub.
NB! AK arvutiklassides kasuta nii kompilaatori javac kui
interpretaatori java jaoks lisaparameetrit -cp .
(javac -cp . minuprogramm.java), muidu ei leita .class
faile sinu hetkekataloogist üles.
Kuidas hoida hetkeseisu, vastase tehtud käiku jne?
--------------------------------------------------
See on väga lihtne: iga selline info on lihtsalt
üks täisarv ja teda saab hoida ühes täisarvu
tüüpi muutujas.
Näiteks, mänguseisu saabki hoida muutujas nimega n.
Deklareeri programmi algul:
int n;
ja hiljem muuda seda n-i. Las n sisaldab
alati laual olevate tikkude arvu.
NB! Muutujate nimedes (nagu ka mujal) on väikesed
ja suured tähed erinevad asjad.
Mulle endale meeldib aga kasutada pikemaid
muutujate nimesid, sest siis saan muutujat
nähes alati aru, mis seal sees peaks olema.
Mina kasutaksin mänguseisu hoidmiseks pigem
näiteks muutujat nimega table. Näiteks nii:
int table;
table=10;
Muuseas, soovitan kirjutada programmi sees
muutujate nimed, kommentaarid jms alati inglise
keeles! See on hea edaspidises päris-töös,
kus väga tihti on vaja teha koostööd inimestega,
kes eesti keelt ei mõista. Programmi koodi
loetavus on programmeerimise-alase koostöö
jaoks hädavajalik.
Kuidas jäägiga jagada
----------------------
Nagu C keeles, nii ka javas on olemas täisarvude
jäägiga jagamise tehe % (protsendimärk).
Näiteks, 8 % 3 annab tulemuseks kahe: kaheksa
jäägi kolmega jagamisel.
Kuidas arvutada juhuslikku arvu
-------------------------------
Juhusliku arvu leidmiseks on Java teegis spetsiaalne
funktsioon juba olemas:
Math.random()
See funktsioon annab juhusliku suurusega, komaga
arvu 0-i ja 1-e vahel. (0 võib tulla, 1 ei tule).
Kuidas saada juhuslik täisarv 1-e ja X-i vahel
(st lubatud väärtused oleks 1,2,...,X):
korruta Math.random() tulemus arvuga X
(siis saad arvu vahemikus 0,...,X kus X ei
saa siiski tulla) liida tulemusele 1 (et
ei tuleks 0 ja saaks tulla X) ja võta saadud
arvust täisosa tüübiteisendust tegeva
nn "cast"-i (int) abil:
tulemus = (int)((Math.random()*X)+1)
Kuidas programmi kirjutamisega hakkama saada
--------------------------------------------
Kui asi tundub veidi keeruline, siis järgi neid
põhimõtteid, mis on programmeerimise juures
alati abiks (eriti veel suuremate ja tõsisemate
programmide puhul, kus nende põhimõtete eiramine
viib üldiselt fiaskoni):
- Ära proovi kõike kohe valmis kirjutada.
Selle asemel kirjuta algul hoopis lihtne
variant programmist, näiteks lihtne tikumäng,
kus alati N on algul 10, M on alati 3,
inimmängija käike ei kontrollita, mäng
toimub ainult ühe korra (uuesti ei alustata).
Proovi see lihtsam programm korralikult
käima saada.
Kui selle lihtsama programmi kirjutamine läheb
kah aeglaselt, siis tee hakatuseks veel lihtsam:
Tee algul näiteks programm, kus arvuti võtab
alati ühe tiku ja vastane üldse ei käi. Selge,
et kümne käiguga on siis masin võitnud. Las
programm trükib iga sammu järel oma käigu
ja seisu ka. Kui see programm töötab, alles
siis asu lisama vastase käigu lugemist. Ära
kontrolle esialgu kohe peale pane ja ära esialgu
pane arvutit juhuslikku käiku arvutama (las
võtab alati ühe tiku). Enne, kui programmiga
edasi lähed, kompileeri ja pane käima ja testi,
et lisandusega lihtne variant käib OK.
- Kui see lihtsam programm käib OK, alles siis
asu lisandusi tegema:
- juhusliku käigu leidmine
- M ja N valik,
- inimmängija käikude kontroll,
- inimmängija võidu / kaotuse tuvastamine
ja väljatrükk
- mängu uuesti alustamine
- jne
ning iga lisanduse järel kompileeri ja paranda
ja testi, kuni see lisandus töötab OK. Alles
seejärel asu programmeerima uut lisandust!
- Küsimus inimmängija käigu kontrollimisest.
Kuna inimmängija võib püüda vale käiku teha
mitte ainult ühe korra, vaid näiteks sada
korda järjest, siis kuidas seda kontrollida?
Vastus: inimmängija käigu lugemine tuleb panna
omaette väikesesse tsüklisse, mis lõpeb siis,
kui anti OK, reeglipärane käik.
- Küsimus mängu uuesti alustamisest: kuidas
päris algusse tagasi minna?
Mängu enda tsükli ümber tuleb teha veel
üks tsükkel, kus iga tsükli kord tähendab
ühte täismängu. Tsükkel lõpeb siis, kui
inimmängija enam uut mängu mängida ei taha.
NB! Kui olemasoleva tsükli ümber uue paned,
siis ära unusta sisemise programmiteksti
taanet igal pool kenasti paremale nihutamast!
Disclaimer
==========
Kui mõni soovitus või nõuanne siin tekstis tundub
mitte aitavat või tundub otseselt vale, siis
seda nõuannet ei pea arvestama! Lõppkokkuvõttes
loeb ainult see, et programm oleks
tehtud vastavalt alguses toodud nõuetele ja
töötaks OK. Vajadusel eksperimenteeri ja
katseta ise, loe õpikut ja juhendeid, vaata
näiteid jne.