Sinun UserID: 0
Ilmoittaudu missä ryhmässä (live/zoom/video) katsot demojen vastaukset (huom joka viikolla oma ilmoittautuminen)
Please
to interact with this component. Please
to interact with this component. Please
to interact with this component. Please
to interact with this component. Please
to interact with this component.
Alla demotilanteesi.
- Pisteet eivät päivity tähän automaattisesti, vaan aina pienellä viiveellä.
- Värit: Punainen: Minimit ei täyty. Vihreä: vähintään 5p joista 2p tähtitehtävistä.
Ohjelmointi 1, s 2023 / Demo 7
Jos haluat harjoitella vastaavilla tehtävillä, joihin saat myös mallivastaukset, niin katso:
HUOM! Joka kerta on saatava vähintään 2p tähtitehtävistä! Alle 5p tehneillä on huono ennuste loppukurssissa.
Demot palautetaan viimeistään ma 23.10 klo 11:00 mennessä. Voit palauttaa osan tai kaikki tehtäväsi etukäteenkin ja täydentää vastauksia määräaikaan mennessä. Alla mainitut mallivastaukset näkyvät vasta kun demojen palautustilaisuudet on pidetty.
- huomaa että Answer-linkistä pääset katsomaan muiden vastauksia kun palautusaika on ummessa
- mallivastaukset
- muiden vastaukset
Oppimistavoitteet
Klikkaile ruksit niihin kohtiin jotka olet oppinut. Työkirja-sivulla näet yhteenvedon kaikista demoista.
Demokerran päätteeksi kirjoita arvio tällä viikolla käyttämästäsi työmäärästä. Laske työmäärään mukaan kaikki tällä viikolla käyttämäsi aika: lähiopetukseen (tai zoom) osallistuminen, oppimateriaalin lukeminen, demotehtävien tekeminen, luentovideon katsominen, demojen palautustilaisuuteen osallistuminen ja niin edelleen. Voit päivittää lukua viikon edetessä, se voi helpottaa arvion tekemistä. Huom! Siis tähän ei laiteta kurssin alusta kaikkia tunteja yhteensä, vaan vain tämän viikon tunnit. Tästä annettava 0.25 näkyy Pisteet-sivun demokerran summassa. Kirjoita pelkkä luku esim tyyliin 13.5
Ajankäyttösi tällä viikolla:
Please
Kun tehtävien vastaukset on julkistettu (esim demopalautuksissa), pitää jokaisen korjata omat vastauksensa niin, että ainakin Tauno ja perustehtävät 1-6 tuottavat vähintään 1p kukin. Eli demon palautuksen jälkeen pitää demosivun näyttää vähintään 7 p.
Siis esim. ennen demo 2 tehtävien aloittamista pitää demoista 1 tulla vähintään mainittu pistemäärä.
Voit saada demopisteitä indeksoimalla luento/demovideoita, ks: Videoiden hakemisto aihepiireittäin 23 Lisää em. videosivulle vähintään 3-linkkiä ja kirjoita alla olevaan laatikkoon, mitkä linkit lisäsit. Joka demokerralle voi merkitä aina vähintään 3:sta linkistä yhden demotehtävän.
Testaamisesta
Tämän kerran tehtävät vaikuttavat pitkiltä, mutta itse asiassa vastausten itse kirjoitettujen rivien lukumäärä tulee olemaan kurssin lyhimpiä. Eli lue tehtävät huolella ja keskity, tehtävät eivät ole niin vaikeita kuin tehtävien pituudesta voisi päätellä. Tehtävät 5, 6, ja B1 ovat muuten kanssa helppoja tehtäviä.
Muista tarvittaessa monisteen täydennyssivut! (ylälinkissä kohdassa lisämateriaali).
Kysely 1
Käy lukemassa mitä demo 6:sta kerättiin kurssin palautteeseen palaute-sivulta ja osallistu siellä keskusteluun.
Jos et vastannut demo 6:ssa, niin vastaa kurssin välikyselyyn (ei kesän kurssilla). Kopioi kyselystä kohta Analysoi omia vaikeuksiasi tai tarkenna edellisiä alla olevaan laatikkoon. Muista painaa return aina kun rivi tulee täyteen ettei tule yli 65 merkkiä pitkiä rivejä. Tai paina wrap
aina välillä. Jos kirjoitit jotakin uutta, jota ei ole palaute-sivulla käsitelty, niin kopioi vastauksesi tai osa siitä palaute-sivulle
Pisteen tästä tehtävästä saavat merkitä ne, jotka eivät käyttäneet sitä demo 6:n vastaavassa kohdassa.
Ville 1
Muista että jos et tykkää Villestä, näitä ei ole pakko tehdä.
Tee Ville-tehtävät: 5.9-5.13,9.8 Villen käyttöohje
Pitääkö täyttää edellisen demokerran tehtävät, jos tauno + perustehtävistä sai sen 7 pistettä?
VL: jos se on valmiiksi vihreä ja >=7p, niin ei muuta tarvii. Toki kannattaa katsoa jos ei ole kaikkia perustehtäviä tehnyt.
—Onko muilla Haka kirjautumisen kanssa tullut ongelmaa? "The request cannot be fulfilled because the message received does not meet the security requirements of the login service."
VL: On! Turkuun on lähetetty kysely...
VL: Nyt ainakin minä pääsin Villeen!
—Jeliot 1
Tämäkään ei ole pakollinen, mutta voi olla hyvä havainnollistus jollekin! Vajaasta 30:stä tässä (syksy 2018) demossa kokeilleelta on tullut palautetta että oli hyötyä!
Ota itsellesi Jeliot.jar, eli ota tuo ja käynnistä Jeliot.jar. Copy/Paste koodialueelle Kutsuminen.java (vertaa Kutsuminen.cs, jollet ole nähnyt kutsunäytelmää, niin katso se samalla kun teet tätä). Nyt sinun on tarkoitus Jeliotilla katsella sama asia parametrin välityksestä, mikä oli kutsunäytelmässä. Kun koodi on koodialueella, paina Compile ja sen jälkeen lähde ajamaan ohjelmaa askel kerrallaan ja mieti ajatuksen kanssa mitä missäkin kohti tapahtuu. Vaikka esimerkkikoodi on Javaa, kaikki tapahtuu täsmälleen samalla tavalla C#:issa. Kerro mitä opit tästä ja/tai kutsunäytelmästä.
Pohjatiedosto varsinaisille tehtäville
Pohjana käytetään tiedostoa Kuvaaja.cs
. Tehtävät 1-4 perustuvat tämän muuttamiseen ja täydentämiseen. Tehtävät 1, 2 ja 3 pystyy tekemään suoraan TIMissäkin, mutta ainakin tehtävä 4 vaatii Riderissa tai vastaavassa Kuvaaja.cs
:n muokkaamista.
Voit ottaa pohjan GIT:istä normaalin kurssin esimerkkien hakemistapaan:
seuraava tehdään komentoriviltä, eli mene ensin komentorivillä hakemistoon johon haluat esimerkit ja pohjat ladata ja
git clone https://gitlab.jyu.fi/tie/ohj1/2023s/esimerkit.git .
Jos olet jo hakenut esimerkit aikaisemmin tai haluat hakea mahdolliset muutokset myöhemmin, niin tee silloin:
git pull
tuo vaatii vajaan 30 MB tilaa ja jos sinulla ei ole tilaa, niin voit ottaa tuolta:
- joko pelkkä demo7 zippinä
- tai https://gitlab.jyu.fi/tie/ohj1/2023s/esimerkit/-/tree/main/demopohjat
download
-kuvakkeen kohdaltaDownload this directory
jazip
. - siten purat
zip
jonnekin (vajaa 5 MB).
kun tavara haettu, kopioi hakemisto
demopohjat/demo7
johonkin uuteen hakemistoon ja siten siellä- Mene
demo7
kansioon ja avaademo7.sln
- Mene
solutionissa on monta projektia. Muista aina valita minkä projektin haluat ajaa (pitää näkyä boldina).
tällä tavalla saat myös Taunot ja AngryLegot pohjaksi samalla vaivalla.
Kokeile ajaa Kuvaaja
-ohjelmaa. Sen pitäisi piirtää koordinaatisto, jossa hiirtä klikkaamalla sininen piste siirtyy klikattuun kohtaan. Lue huolella Kuvaaja.cs
:n koodi ja mieti mitä kaikkea siinä on ja miksi.
Begin
-metodissa on rivi
// IsFullScreen = true;
Tämä siksi, että jos ohjelma kaatuu, tai sitä haluaa debugta, niin näyttö menee sekaisin FullScreenissä.
Kokeilin ladata noita ensimmäistä kertaa, mutta sain tällaisen ilmoituksen. Mitä pitäiisi tehdä?
$ git clone https://gitlab.jyu.fi/tie/ohj1/2023s/esimerkit.git . fatal: destination path '.' already exists and is not an empty directory.
VL: Oliko se hakemisto varmasti tyhjä mihin olit kloonaamassa?
—Sain ajettua Kuvaaja-ohjelman kerran, ja se toimi. Tämän jälkeen kun ohjelmaa yrittää ajaa tulee seuraavat: [ALSOFT] (EE) Failed to check format support: 0x80040154 [ALSOFT] (EE) Failed to initialize audio client: 0x80070006
VL: Käyttöjärjestelmä?
Windows
VL: toimiiko enää mikään jypeli-ohjelma?
—Kun yritän ajaa komentoriviltä Kuvaaja.cs, saan:
Unhandled exception. System.PlatformNotSupportedException: GLFW is not supported on this platform.
Sama Jypeleillä. Hankin uuden koneen (Windows) kesken kurssia ja mielestäni tein kaikki kurssille vaadittavat asennukset. Mikäköhän ois probleema?
JK: Ongelma on todennäköisesti näytönohjaimen ajureissa. Ootko näillä ohjeilla kokeillut jo: https://tim.jyu.fi/view/kurssit/tie/ohj1/tyokalut/rider#glfw ?
Ongelma ratkaistu ohjeilla. Kiitos paljon avusta!
—Tauno 1
Kohdassa b toteuta a-kohdassa Taunolla tekemäsi koodin pohjalta funktioaliohjelma
MuutaYli(int[] t, int raja, int miksi)
joka muuttaa taulukosta kaikki annetun rajan ylittävät alkiot miksi
-parametrissa annetuksi arvoksi ja joka palauttaa muutettujen alkioiden lukumäärän.
mitkä ovat maximi pisteet?
VL: Yksi tehtävänumero on aina 1p jos ei erikseen sanota. Silloin kaksi osatehtävää sisältävä tehtävä on 0.5p/kpl ellei muuta erikseen sanota. Sulla vikana on että et ole huomioinut aliohjelmalle tulevia parametreja ja se aina muuttaa samalla tavalla vaikka testeissä on muitakin haluttuja muutosarvoja.
—Tauno 2
Matriisin sisätulo: kerrotaan kahden matriisin vastinalkiot keskenään ja lasketaan tulot yhteen. Tässä tehtävässä lasketaan maskimatriisin ja varsinaisen matriisin osamatriisin sisätulo. Alla olevassa kuvassa hvainnollistettu tilannetta, jossa varsinaisesta matriisista otetaan indeksin [2,1]
ympärillä oleva maskin kokoinen osamatriisi.
Tässä voi olla myös hyötyä tehdä valmiiksi etukäteen Demo 8:n B1 tehtävä, tätä varten katso avuksi videot:
Matriisi, kohdan [2,1] ympärillä oleva 3x3 osamatriisi merkitty vihreallä:
Maski:
Yllä olevan kuvan tapauksessa sisätulo olisi:
35*1 + 50*1 + 60*1 +
50*1 + 90*1 + 102*0 +
20*0 + 34*1 + 44*1 = 363
Kun yllä olevassa kuvassa laitat maskin johonkin kohti, näet missä indekseissä olevat luvut kerrotaan keskenään ja summataan. Huomaa että maskin indeksit eivät riipu siitä, mihin kohti matriisissa se laitetaan.
Tätä tehtävää ei tehdä oikealla Taunolla, mutta periaatteessa samalla idealla. Ongelmana on tällä kertaa matriisin sisätulon laskeminen. Eli lyhyesti sanottuna otetaan kahden matriisin vastaavissa paikoissa olevat alkiot ja kerrotaan ne keskenään ja lasketaan näiden tulojen summa. Itse asiassa Sopulipelin ja sen harjoittelutehtävän naapurien määrän laskeminen olivat sisätuloja, joissa maski-matriisina olivat
1 1 1 0 1 0
1 0 1 1 0 1
1 1 1 0 1 0
Tee alla olevan aliohjelman tehtävä taunomaisesti, eli käyttäen vain vakionumeroita (lisättävä 6 riviä valmiiseen koodiin). Tehtävänä siis laskea mallimatriisin pisteen
[2,1]
ympärille tulevan 3x3 osamatriisin ja maskin sisätulo, eli kertoa vastinalkiot keskenään ja laskea tulot yhteen. Vrt. Demo 6 Tauno 2. Huom. Nyt "keskipiste" ei ole mikään erikoistapaus.Kohtaan Tauno 2.2 muuta vastauksesi niin, että käytät hyväksesi indeksejä
ix
,iy
vakioiden sijaan niin, että minkä tahansa ei-reunassa olevan osamatriisin sisätulo voidaan laskea. Eli aloita vaihtamalla[2,1]
tilalle[iy+0,ix+0]
ja muihin vastaavasti.(Vapaaehtoinen) koita tehdä sama silmukalla
Muuta vielä edellistä vastausta niin, että saat kaikki rivit muotoon
summa += luvut[iy + y, ix + x] * maski[y+1, x+1]; x++;
Tehtävä 1*. Pisteet taulukossa
Jos yhtään vaikeuksia, katso: tehtävä jolla voi harjoitella.
Huomaa että vaihtoehtoisesti tehtävät 1-4 voi tehdä tehtävinä E1-E4 jolloin ei tarvita grafiikkaa.
Vaikka tehtävät 1-3 voikin tehdä suoraan TIMissä, suositellaan niiden tekoon ehdottomasti Riderin tms käyttöä. Pohjamateriaaleissa tehtävät on merkitty TODO:-kommenteilla.
Huomasithan ottaa ensin pohjatiedostot! Tehtäviin 1-4 kannattaa malliksi katsoa luennolla 14 tehty LaskeMatka.cs . Tässä tehdään nimenomaan Kuvaajat.cs
, ei Pisteet.cs
!
M: 15. Taulukot.
Täydennä Kuvaaja.cs
:n aliohjelma LuoPisteet
toimivaksi niin, että se piirtää (=lisää) parametrina tuodun pisteet
-taulukon koordinaattipisteitä (=vektoreita, eli Jypelin X,Y
-lukupareja) vastaaviin paikkoihin mustat pikkupallot näytölle (=peliin).
Yritä ensin piirtää vaikka vain taulukon paikassa 0 olevaan pisteeseen pallo ja kun se onnistuu, niin sulje tuo piirto silmukkaan, joka käy kaikki pisteet taulukon pisteet läpi.
Esimerkiksi paikassa 2 olevan pisteen (vektorin) kohdalle saisit keltaisen pallon valmiilla alempana olevalla funktiolla:
LuoPallo(game,pisteet[2],r,Color.Yellow);
Kun tehtävä on tehty, "peliin" pitäisi tulla 4 mustaa pistettä (koska tehtävän 2 ArvoPisteet
toistaiseksi "arpoo" vain 4 pistettä) kun sen ajaa.
Katso muistin virkistämiseksi vanhoja PiirraPallo aliohjelmia. Begin
metodissa on esimerkki kahden pallon luomisesta origoon.
Monella ongelma näyttää olevan seuraava: On opeteltu etsimään maitopurkkihyllystä (int[]
) suurin purkki. Samoin on katsottu mallia miten löydettäisiin suurimman purkin paikka piimäpurkkihyllystä (double[]
). Kun pitäisi löytää suurimman purkin paikka mehupurkkihyllystä (Vector[]
), niin meneekin sormi suuhun eikä keksitä yhtään mitä pitäisi tehdä.
Nyt ei kannata ajatella liian monimutkaisesti. Jos pitäisi tulostaa taulukossa luvut
reaaliluvut, niin se olisi aivan analoginen tehtävän 1 ongelman kanssa. Tehtävässä pitää "tulostaa" taulukossa pisteet
olevat pisteet (eli piirtää pallo jokaisen pisteen kohdalle).
Miten tulostettaisiin taulukossa double[] luvut
olevat luvut? Esimerkiksi
for (int i=0; i<luvut.Length; i++)
{
double luku = luvut[i];
Console.WriteLine(luvut[i]);
}
Jos tuo olisi ollut tehtävänä, vinkkinä olisi voinut olla, että paikassa 2 olevan luvun voit tulostaa:
Console.WriteLine(luvut[2]);
tai toisaalta myös seuraava toimisi:
double luku = luvut[2];
Console.WriteLine(luku);
Nyt tehtävän vinkkinä on, että paikassa 2 olevan pallon voi "tulostaa" keltaisena (eli piirtää) kutsumalla omaa valmista aliohjelmaa LuoPallo
(ks. alempana Kuvaaja.cs
-tiedostossa:
LuoPallo(game,pisteet[2],r,Color.Yellow);
tai edellisen WriteLine
esimerkin kanssa analogisesti myös:
Vector piste = pisteet[2];
LuoPallo(game,piste,r,Color.Yellow);
Voit toki aloittaa tehtävän tekemisen niin, että se piirtää ensin vain ne 4 taulukossa olevaa palloa (mallissa keltaisella, oikeasti haluttiin mustia palloja):
LuoPallo(game,pisteet[0],r,Color.Yellow);
LuoPallo(game,pisteet[1],r,Color.Yellow);
LuoPallo(game,pisteet[2],r,Color.Yellow);
LuoPallo(game,pisteet[3],r,Color.Yellow);
Sitten kun tämä toimii, muutat sen vastaavaksi silmukaksi.
Analogiat ovat siis:
reaaliluku- Vector-
taulukko taulukko selitys
=====================================================================
double <=> Vector - yhden alkion tyyppi
double[] <=> Vector[] - taulukon tyyppi
luvut <=> pisteet - taulukon nimi
luku <=> piste - taulukon yksi alkio
int i <=> int i - indeksi on aina kokonaisluku
luvut[i] <=> pisteet[i] - taulukon i:s alkio.
WriteLine <=> LuoPallo - "tulostaminen"
=====================================================================
Kannattaisiko luotujen pallojen eli pisteiden olla GameObject-tyyppisiä? Nyt PhysicsObject-tyyppisiä pisteitä pystyy esim. tönimään klikkaamalla pisteitä viereen. Vaihtoehtoisesti PhysicsObject.CreateStaticObject ja CollisionIgnoreGroup.
VL: Joo, ilman muuta jos tuo häiritsee.
—Tehtävä 2*. Arvo pisteet
Jos yhtään vaikeuksia, katso: tehtävä jolla voi harjoitella.
Korjaa Kuvaaja.cs
:n funktioaliohjelma ArvoPisteet
, joka luo parametrin n arvon kokoisen taulukon ja arpoo tason pisteitä taulukkoon (Vector[] pisteet
). Arvo RandomGen-luokan NextDouble
-funktiota käyttäen x
ja y
-koordinaatit ja luo aina vastaava uusi Vector. (Esimerkki käytöstä oli mm: Pallot.cs). Nyt ohjelman ajossa pitäisi koordinaatistoon tulla 20 pistettä satunnaisiin paikkoihin.
HUOM: Tässä tehtävässä tarvitset Tehtävässä 1 tekemääsi LuoPisteet
-aliohjelmaa. Kopioi aliohjelman toteutus edellisestä tehtävästä tämän tehtävän koodiin
Huomio: TIMin tehtäväkentän aliohjelman Arvopisteet esittelyrivi eroaa pohjatiedostona olevan Kuvaaja cs:n vastaavasta. Kuvaaja.cs:ssa esittelyrivi muotoa: public static Vector[] ArvoPisteet(int n, double ax1, double ay1, double ax2, double ay2)
Riderissa jos tekee ja saa siellä toimimaan niin esittelyriviä tai aliohjelmakoodia pitää muokata, että aliohjelma pelaa myös TIMin puolella.
VL: Joo, muutin noita x1 => ax1 (alueen x1) koska Rider suuttui nimistä x1 jne koska ne olivat jo muualla käytössä. Vaikka ovatkin lokaaleja muuttujia, niin ne peittävät silloin "globaalimman" muuttujan. Koitan muutella täällä TIMissä ne paikat mitä löytyy. En kyllä heti keksi miksi Riderissa tehty koodi ei toimisi TIMissä?
—Vinkki: Tutki ensin aliohjelman nykyistä toteutusta (tekee väkisin 4 vektoria) ja mieti miten sama tehdään silmukassa.
Tehtävä 3. Lähin piste
Jos yhtään vaikeuksia, katso: tehtävä jolla voi harjoitella.
M: 15. Taulukot, 16. Silmukat.
Täydennä funktioaliohjelma LahimmanIndeksi
, joka etsii annettua pistettä lähimmän taulukon alkion indeksin.
Mikäli haluat tehdä pelkän pääohjelman ja LahimmanIndeksi
-funktion Riderissa testaamista varten, niin Vector
-luokan taulukoita voi luoda esimerkiksi:
Vector[] pisteet = { new Vector(1,2),new Vector(3,4),
new Vector(5,2),new Vector(5,5) };
Samaa voi soveltaa myös testeissä. Itse funktion kutsu voisi olla esimerkiksi:
Vector piste = new Vector(5.1,2.5);
int indeksi = LahimmanIndeksi(pisteet,piste);
// esimerkin taulukolla indeksi olisi 2
Demossa 6 etsittiin reaalilukutaulukon lähintä lukua. Sen idea sopii täysin, nyt vaan pitää palauttaa lähimmän indeksi (eli paikka taulukossa) eikä itse lähin. Demo 6:ssa alkion tyyppinä oli double
, nyt Vector
. Vastaavasti Kutsunäytelmässä Matti etsi taulukon suurimman luvun indeksin. Ja tuosta seuraavalla luennolla erotettiin jopa tuo etsiminen omaksi funktiokseen SuurimmanPaikka.
Mikä tässä kuvassa on sinistä pistettä lähimmän pisteen indeksi? Entä mikä on sen koordinaatti? miten se koordinaatti saadaan pisteet
-taulukon ja indeksi
-muuttujan avulla?
Voit miettiä alla olevalla Taunolla mitä aputietoja sinun pitää tallettaa jos etsit annettua lukua lähimmän paikan (ei itse lukua).
Etäisyyden voit laskea joko Demo 6 Etaisyys-funktiolla (se 2D-versio) tai jopa helpommin Jypelin Vector-luokasta löytyvällä funktiolla kahden vektorin (=pisteen) välisen etäisyyden laskemiseksi (etsi dokumentaatiosta ko. funktio). Huomaa että tämä on esimerkki ongelmasta, jota EI voi ratkaista foreach
-silmukalla. Miksi?
Tätä funktiota ei vielä kutsuta tässä ohjelmassa. Kutsu tulee tehtävässä 4.
Pisteiden (Jypelissä Vector
) p1
ja p2
välisen etäisyyden voi laskea joko Demo 6:n Etaisyys
-funktiolla tai vielä helpommin Jypelin Vector
-luokan Distance
-funktiolla:
double d = Vector.Distance(p1,p2);
Näissä tehtävissä ei ole Näytä koko koodi
, koska tarvitaan tulevien tehtävien vastauksia. Koodin ympärillä on kuitenkin valmiiksi tarvittavat luokat ja puuttuvat aliohjelmat, eli vastauslaatikkoon tulee vain LahimmanIndeksi
-funktion toteutus, kommentit ja testit. Ei pääohjelmaa tms.
Kun tämän tehtävän ajaa TIMissä, arvotaan aluksi 20 mustaa pistettä. Sitten arvotaan siniselle pisteelle satunnainen paikka. Sitten etsitään sinistä pistettä lähimmän pisteen paikka ja sen päälle laitetaan punainen piste.
Kysymys: Pääteohjauksessa ei saatu selville miksi tämä aliohjelma palauttaa yhtä suuremman indeksin kuin on vastaus. Ensimmäisessä testissä:
Expected: 1 But was: 2
SW: Laitoin sulle sähköpostilla selityksen, miksi tuo ratkaisu ei toimi, ja miten se voidaan jatkojalostaa toimivaksi.
—Tehtävä 4. Lähimmän merkitseminen
Nyt metodi (se on metodi, koska se tarvitsee muitakin peli-olion asioita kuin parametrina tuodut) public void SiirraMerkkipisteet(Vector p)
jota kutsutaan kun hiirtä klikataan (ks. Mouse.Listen
-rivit), siirtää vain sinisen pisteen (klikattuPiste
) hiirellä klikattuun kohtaan. Täydennä metodia siten, että se etsii pisteet
-taulukosta lähimmän koordinaatin indeksin ja siirtää punaisen merkkipisteen tätä indeksiä vastaavaan koordinaattiin.
pisteet
-taulukko näkyy metodille, koska taulukko on peli-luokan attribuuttina. Siksi sitä ei ole tässä tapauksessa tuotu parametrina kuten on tehty staattisissa metodeissa. Tätä metodia ei siksi voisi kutsua muista ohjelmista ilman peliluokan olemassaoloa. Samoin SiirraMerkkipisteet
-metodi näkee myös attribuutit klikattuPiste
ja merkkipiste
.
HUOM: Tätä tehtävää et voi tehdä pelkästään TIMissä, vaan tätä varten pitäisi hakea pohjatiedostot Rideriin (tai vastaavaan) muokattavaksi. Ks. Ohjeet
Ole rehellinen, että et ota pisteitä jos ohjelma ei toimi oikein Riderissä!
Tehtävä 5. Kirjainten laskeminen
Jos yhtään vaikeuksia, katso: tehtävä jolla voi harjoitella.
M: 16. Silmukat. Tee funktio LaskeKirjaimet
, joka laskee merkkijonossa olevien annetun kirjaimen esiintymien lukumäärän.
Funktiota voitaisiin kutsua muodossa
int kMaara = LaskeKirjaimet("kissa", 's');
Kirjoita funktiolle myös ComTest-testit
String
-käyttäytyy kirjainten char
suhteen kuten taulukko, eli yhden kirjaimen saa samalla tavalla kuin taulukostakin saisi yhden alkion.
En ymmärrä miksi testit eivät toimi. Apua? "Compile error kirjaintenlaskeminen.cs => kirjaintenlaskeminenTest.cs ok kirjaintenlaskeminenTest.cs(16,39): error CS0839: Argument missing001 using System;" #- Ymmäränpäs: Lainausmerkit ("", '') puttuivat testeissä annetuista arvoista.
—Tehtävä 6. Matriisien summa
Jos yhtään vaikeuksia summassa, katso: tehtävä jolla voi harjoitella.
Jos yhtään vaikeuksia matriisin palauttamisessa, katso: tehtävä jolla voi harjoitella.
M: 15.5 Moniulotteiset taulukot, 16. Silmukat. Tee funktioaliohjelma, joka summaa yhteen kaksi matriisia vastinalkioittain. Funktio siis joutuu ensin luomaan oikeankokoisen tulosmatriisin. Mitä on syytä olettaa parametrimatriiseilta? Dokumentoi kommentteihin oletuksesi. Sitten funktio laskee tulosmatriisiin komponenteittain summan.
Funktioaliohjelmaa voitaisiin käyttää esimerkiksi näin:
public static void Main(String[] args)
{
double[,] mat1 = {{1,2,3},
{2,2,2},
{4,2,3}};
double[,] mat2 = {{9,2,8},
{1,2,5},
{3,19,-3}};
double[,] mat3 = Summa(mat1, mat2);
}
Ja tässä summamatriisi mat3
näyttäisi tältä:
{{10, 4, 11},
{ 3, 4, 7},
{ 7, 21, 0}}
Summamatriisi voitaisiin tulostaa myös Demo 6 Jonoksi
funktion avulla seuraavalla ohjeella.
Lue lisää matriisien testaamisesta.
Yksi tapa testata on testata muutamaa kriittistä alkiota tyyliin:
mat3[0,0] ~~~ 10;
mat3[2,2] ~~~ 0;
Auttavasti voidaan testata myös niin, että matriisi muutetaan merkkijonoksi seuraavalla tempulla:
String.Join(" ",mat3.Cast<double>()) === "10 4 11 3 4 7 7 21 0";
Mikäli kahdessa matriisissa on samat alkiot, mutta eri määrillä rivejä ja sarakkeita, saadaan tällä toki väärä tulos.
Nykyisin toimii jopa:
Summa(mat1, mat2) === new double[,]{{10,4,11}, {3,4,7}, {7,21,0}};
Ymmärsinkö jotain väärin, vai eikös tässä pysty testaamaan ihan vaan Summa(mat1, mat2) === tulos;. Mun kokeilujen mukaan se osaa ihan oikein verrata kahden matriisin vastinalkioita keskenään.
VL: Joo, nykyisessä C#:issa toimii noin kunhan tulos on 2-ulotteinen matriisi
—Kuuluuko tässä tehtävässä ottaa huomioon, että molemmilla matriiseilla voi olla eri määrä rivejä ja sarakkeita?
VL: Tuota voit itse määritellä ja kommenteissa todeta miten toimii.
—B1. Lukujen erottaminen merkkijonosta
Merkkijonojen pilkkominen: Tee funktioaliohjelma ErotaLuvut(String jono)
, jonka ansiosta seuraava pääohjelma
public static void Main(String[] args)
{
double[] luvut = ErotaLuvut("2.23 3 4 5 k 9 ;5");
Console.WriteLine(String.Join(" ", luvut));
}
tulostaisi
2.23 3 4 5 0 9 5
Huom! Tehtävää ja sen testaamista voi vaikeuttaa se, että eri maissa ja koneiden asetuksissa käytetään eri desimaalimerkkiä. TIMissä ajettaessa käytetään desimaalipistettä.
Käytä String.Split
-funktiota ja Taulukot.cs:ssä olevaa ErotaDouble
-funktiota yksittäisen merkkijonon muuttamisessa reaaliluvuksi. Kopioi tämä aliohjelma (sisältöineen) mukaan koodiin. ErotaDouble
toimii vaikka jonoksi annetaan vääränlaisiakin syötteitä ja sille voi valita mitä tällöin palautetaan. Ks. funktion ComTestit
.
Tälle eräs hyötykäyttö on esimerkin Kuvaaja.cs metodissa KysyKoordinaatti
, jota kutsutaan jos painetaan hiiren oikeata nappia. Tällöin kysytään käyttäjältä pisteen koordinaatti ja luodaan uusi vihreä pallo ko. kohtaan. Ohjelman puhelinversiossa sama kysytään kun pyyhkäistään näyttöä ylhäältä alas.
B2. if-lauseiden poisto
M: 13. Ehtolauseet, 15.5 Moniulotteiset taulukot, 16. Silmukat.
Demo 5:n mallivastauksessa Sopulit on funktio LaskeNaapurit
kirjoitettu seuraavasti:
public static int LaskeNaapurit(int[,] sukupolvi, int rivi, int sarake)
{
int summa = 0;
int maxy = Math.Min(sukupolvi.GetLength(0) - 1, rivi + 1);
int maxx = Math.Min(sukupolvi.GetLength(1) - 1, sarake + 1);
for (int iy = Math.Max(0, rivi - 1); iy <= maxy; iy++)
for (int ix = Math.Max(0, sarake - 1); ix <= maxx; ix++)
{
if (iy != rivi || ix != sarake) // itseä ei lasketa naapuriksi
if (sukupolvi[iy,ix] > 0) summa++;
}
return summa;
}
Tarkoituksenahan on mennä periaatteessa edeltävä rivi, oma rivi ja seuraava rivi ja niissä edeltävä sarake, oma sarake sekä seuraava sarake unohtaen kuitenkin oma koordinaatti. Eli jos rivi=2 ja sarake=1, niin pitäisi käydä ruuduissa
(1,0),(1,1),(1,2)
(2,0), (2,2)
(3,0),(3,1),(3,2)
On kuitenkin hieman työlästä kirjoittaa silmukka, jossa jokaista riviä ei käsiteltäisi samalla tavalla, siksi em. esimerkissä käydään silmukoilla myös ruudussa (2,1). Ja jos silmukat tuovat tämän koordinaatin, niin se on if-lauseella ohitettu. Mikäli tutkittava ruutu ei ole reunalla, niin periaatteessa em ruudut saataisiin käytyä läpi seuraavalla alustuksella:
int alkuy = rivi - 1;
int loppuy = rivi + 1;
int alkux = sarake - 1;
int loppux = sarake + 1;
// Tähän rajojen korjaus
for (int iy = alkuy; iy <= loppuy; iy++)
for (int ix = alkux; ix <= loppux; ix++)
{...
Reunojen kanssa on kuitenkin ongelmana indeksialueen ylitys. Siksi mallivastauksessa yläraja maxy
on laskettu niin, että se on pienempi luvuista rivi+1 tai viimeisen rivin indeksi (rivimäärä-1). Sama sarakkeen tapauksessa maxx
. Alaraja on vastaavasti suurempi luvuista rivi-1 tai 0. Pienenä miinuksena mallissa on se, että tuo Math.Max
-funktio kutsutaan jokaisella rivillä uudelleen, vaikka se tuottaa joka kerta saman arvon.
Tehtävä 1: korjaa edellä olevat alkuy
, loppuy
, alkux
, loppux
if-lausetta käyttämällä ennen silmukoita oikeiksi niin, että tuo silmukka voi aina olla:
for (int iy = alkuy; iy <= loppuy; iy++)
for (int ix = alkux; ix <= loppux; ix++)
Mallivastauksen toinen "vika" on se, että ehtolause:
if (iy != rivi || ix != sarake) // itseä ei lasketa naapuriksi
on silmukan jokaisella kierroksella ja sitä tarvitaan vain yhdessä tapauksessa noista yhdeksästä kierroksesta. Jos tutkittavia pistetä on vaikka 100x100, niin suoritetaan 90 000 if-lausetta.
Toisaalta myös toinen if-lause
if (sukupolvi[iy, ix] > 0) summa++;
on turha jos oletetaan että taulukossa on vain lukuja 0 tai 1 (miten tehdään?).
Tehtävä 2: muuta silmukan sisäosa sellaiseksi, että siinä ei ole yhtään if-lausetta, mutta silmukoiden jälkeen korjataan mahdollisesti liian paljoksi lasketut naapurit (ruudun itsensä takia laskettu). Tähänkään ei tarvita if-lausetta em oletuksilla.
B3. Suljettu GameOfLife
Torus on pinta (munkkirinkilän kuori), joka tulee kun esim paperi laitetaan rullalle ja syntyneen sylinterin päät yhdistetään. GameOfLifen matriisi voidaan kuvitella kirjoitetuksi tällaiselle pinnalle.
Tee tehtävään B2 funktio LaskeNaapuritTorus
, joka laskee naapurit niin, että jos mennään reunalta yli, tullaan toiselta laidalta takaisin. Koodi on lähes sama kuin tehtävässä B2, mutta se voidaan tehdä täysin ilman if-lauseita.
Kokeile miltä GameOfLife näyttäisi tällä versiolla.
B4-5. AngryLego
Kun otat pohjatiedostot GITillä ohjeiden mukaan, saat myös AngryLego -pelin.
Mikäli pelialue ei näy kunnolla, niin muuta riviin:
Camera.ZoomToLevel();
sulkuihin sopiva marginaali, esim 100
.
Tehtävänä lisätä peliin:
siirrä kaikki kuvien lataukset olion attribuuteiksi ja siellä missä kuvaa tarvitaan, käytä tätä attribuuttia:
private Image pallonKuva = LoadImage("Igor"); ... pallo.Image = pallonKuva;
näin saat niin, ettei kuvia ladata kuin kerran ja voidaan käyttää samoja kuvia.pallot elävät vain max. 5 sekuntia
pelissä voi pudottaa vain 10 palloa (voitava muuttaa yhdestä paikkaa koodista joksikin muuksikin)
pistelaskuri, pallon osumasta viholliseen saa 100 pistettä ja seinän takia räjähtäneestä vihollisesta 50 pistettä.
välillä syntyykin räjähtäviä Symbian-kännyköitä (paineaalto mukana)
Vinkki: Lue Jypelin ohjeet
Jos teet samoja ominaisuuksia omaan peliin, saat merkitä tämän tehtävän. Vastaavasti G2 ja G3 kohdalla.
H1-2. Harjoitustyöhön joku viikon luentoihin liittyvä ominaisuus
Jatkossa on aina vapaaehtoinen tehtävä H1, jolla voi korvata muita tehtäviä mikäli harjoittelee samaa osaamistavoitetta kuin varsinaisissa tehtävissä tai Bonus-tehtävissä.
Lisää harjoitustyöhösi (se voi olla aluksi hyvinkin tyhjä "lumiukkopohja" jokin kurssiviikon aiheeseen liittyvä ominaisuus. Kommentoi koodiin selvästi missä "viikon" ominaisuutta on käytetty. Tällä viikolla esimerkiksi merkkijonon pilkkominen, silmukat, taulukot ja 2-ulotteiset taulukot.
Jos harjoitustyöhön ei ominaisuutta saa lisättyä, voit tehdä myös pienen muun ohjelman, jossa harjoittelet ko. ominaisuuksia mikäli varsinaisista tehtävistä ei mieleistä vastaavaa harjoittelua löydy.
Pyydetty linkki esim. muodossa:
https://gitlab.jyu.fi/oma_kayttajatunnus/ohj1ht
Mikäli teit toisenkin lisäyksen harjoitustyöhön, laita muutos seuraavaan laatikkoon.
G1. Säännöt taulukkoon
Nyt GameOfLife on säännöillä b3s23 (born 3, stay 2 ja 3, ) eli synnytään 3:lla naapurilla ja pysytään 2:lla tai 3:lla naapurilla. Muuta Sopulit.cs:n SeuraavaSukupolvi
- aliohjelma sellaiseksi, että sille voidaan viedä jonkinlaisena taulukkona säännöt ja silmukoiden sisään ei tule enää yhtään if-lausetta (viisastelijoille: myös ?-lause on if-lause, samoin switch :-)
G2. Osuminen laskeminen
Lisää AngryLegoon:
yksittäinen seinä- tai kattoelementti räjähtää pois, jos siihen tulee 4 osumaa pallosta
Vinkki: Perintä
Minulla näkyy tässä ja G3 tehtävässä mallivastauksena sopulipeli. Löytyykö jostain AngryLegon mallivastaus?
VL: niimpä näytti olevan. Sama AngryLego-koodi oli jo B4-5 mallivastauksessa, mutta laitoin tähän sen diff-osan jota on lisätty tämän ominaisuuden takia ja samlla tavalla seuraavaan.
—G3. Uusi kenttä
Lisää AngryLegoon:
jos kentän kaikki viholliset tuhottu, tulee uusi erilainen kenttä.
Kun 3 kenttää pelattu, peli päättyy ja tulee "TopTen"-lista.
PP1
Tee aliohjelma, joka kopioi annetun taulukon alkioittan uuteen taulukkoon. Tee myös aliohjelma, joka kopioi taulukon alkioit uuteen taulukkoon mutta kääntäen siten, että ensimmäinen alkio menee uuden taulukon viimeiseksi alkioksi, toinen alkio uuden taulukon toiseksi viimeiseksi jne.
Vinkki: Taulukot, M: 15. Taulukot ja M: 16.4 for-silmukka
PP2
Tee funktio(aliohjelma) LaskeMerkkijonot
, jolle annetaan parametrina merkkijonotaulukko, sekä etsittävä merkkijono. Funktio laskee, kuinka monta etsittävää merkkijonoa taulukosta löytyi.
Vinkki: Taulukot, M: 15. Taulukot ja M: 16.4 for-silmukka ja M: 13.2 if-rakenne
Korvaavia tehtäviä jotka ovat ei-pelejä
Tehtävät 1-4 vaativat Jypelin käyttöä. Tähän kerätään vaihtoehtoisia tehtäviä, joissa on sama oppimistavoite, mutta voidaan tehdä tekstuaalisena konsolisovelluksena. Tehtävät ovat ensisijaisesti tarkoitettu niille, jotka eivät halua tai eivät voi käyttää Jypeliä.
Tällä kertaa EI SAA tehdä molempia, eli pitää tehdä joko perustetäviä 1-4 tai näitä E1-E4 tehtäviä.
E1-4 Pisteet*
Tämä tehtävä vastaa perustehtäviä 1-4 ja siinä kannattaa käyttää sen tehtävän ohjeita ja vinkkejä. Erona on se, että tehtävä ei ole graafinen, vaan pisteet tulostetaan näyttöön ja klikkausten sijaan pisteen koordinaatit kysytään käyttäjältä.
Itse tehtävät on kirjoitettu ohjelmakoodiin. Demopisteet tehtävästä on annettava itse sen mukaan kuinka monta saa oikein. Tehtävä 1 ei ole sama kuin harjottelutehtävän tulostaminen, koska tässä samalle riville ei saa tulostaa liian montaa pistettä. Tehtävä 3 pitää olla testattuna jotta sen saa laskea oikeaksi. Tehtävän koko koodissa on minimaalinen Jypelin leikkiversio, josta saadaan satunnaislukugeneraattori ja Vector
-luokka. Näin tehtävä toimii mahdollisimman samalla tavalla kuin perustehtävät 1-4.
Rideria varten tehtävän koodin saa joko tiedostosta Pisteet.cs tai alla olevasta laatikosta kun valitsee ensin Näytä koko koodi
ja sitten Copy
. Jos tehtävän ottaa noin, saa sen Pastella takaisin vastaukseksi.
Pääohjelman näet kun valitset Näytä koko koodi
.
Omaa tuotantoa
Näihin tehtäviin voit palauttaa jonkin oman kurssin tämän hetken oppimistavoitteita vastaavia tehtäviä. Ei kuitenkaan enää jos vastaavat tehtävät on tehty edellä olevissa tehtävissä.
Nämä on tarkoitettu lähinnä niille, joilla ei ole mahdollisuutta tehdä varsinaisia tehtäviä ajallaan esimerkiksi kertausharjoitusten tai sairauden takia. Yleensä jos tulee ajoissa ennakoitavia esteitä, pitäisi tehdä perustehtäviä etukäteen.
Nämä arvostellaan manuaalisesti ja opiskelijan pitää ottaa yhteyttä kurssin opettajiin kun toivoo näitä arvosteltavan. Jos tehtävä on liian lähellä mallivastauksia, ei sitä arvostella tai voidaan pyytää muuttamaan vastaustaan erilaiseksi. Samoin jos tehtävä ei liity viikon oppimistavoitteisiin (vertaa esim tähtitehtävät). Luonnollisesti nuo kaksi ohjelmaa eivät saa olla samanlaisia. Laita ohjelman kommentteihin mitä perustehtäviä nämä korvaisivat ja mikä olisi oma peruste millekin pistemäärälle (se voi olla enemmänkin kuin 1p/tehtävä).
These are the current permissions for this document; please modify if needed. You can always modify these permissions from the manage page.