Kuten otsikko sanoo: voiko metodin nimessä olla kutsuttaessa esim: int muuttujaa, jotta voisi "skrollata" metodeita...
public class luokka { public static void metodi1() { //toiminto } public static void metodi2() { //toiminto } public static void metodi3() { //toiminto } public static void main(String[] args) { int i; for (i = 1; i < 4; i++) { metodi+i(); } }
Tyyliin? voiko jotenkin noin tehdä? ihan mikä vaan tapa, jolla voi tehdä noin, käy...
Ei onnistu tuo Javassa, ainakaan muuten kuin reflektiolla. Joissakin dynaamisesti tyypitetyissä kielissä tuo voi onnistua (esim. PHP:ssa onnistuu).
Miksi yrität tehdä noin?
Lopulta olisi järkevää opetella nimeämään jokainen metodi yksilöllisesti. Jos koodiaan katsoo yhtään myöhemmin uudestaan, on yllättävän hankalaa saada kiinni ajatuksenjuoksustaan jo yksinkertaisissa ohjelmissa.
Ehdottamasi ajatus on käynyt kai sitten muidenkin aloittelevien ohjelmoivien kuin minun mielessäni. :> Tuo reflektio vaikuttaa pikavilkaisulla turhankin edistyneeltä – jos välttämättä haluat käydä epäintuitiivisesti nimettyjä metodeja läpi silmukassa, sopisiko tilanteeseen kätevä pieni switch–case?
public class luokka { public static void metodi(int i) { switch (i) { case 1: metodi1(); break; case 2: metodi2(); break; case 3: metodi3(); break; } } public static void metodi1() { //toiminto } public static void metodi2() { //toiminto } public static void metodi3() { //toiminto } public static void main(String[] args) { for (int i = 1; i < 4; i++) { metodi(i); } } }
Nimet metodi1, metodi2 jne. eivät tosiaankaan kerro mitään metodin tarkoituksesta, joten missään todellisessa ohjelmassa ei pitäisi olla tarvetta tehdä noin. Tässä artikkeli siitä, miten muuttujat/metodit/luokat kannattaa nimetä: http://tottinge.blogsome.com/meaningfulnames/
Tarvitsisin noita siihen ASCII-peliin, jota olen tekemässä, sillä kun tein siitä liikkumisesta sen metodin, en saa mentyä seuraavaan kenttään vain kirjoittamalla liikkumiseen taso1(); tai taso2(); yms... joten ajattelin, olisiko tuommoista tapaa olemassa. keksin juuri kylläkin toisen tavan, joka tosin vie enemmän rivejä, mutta toimii yhtä hyvin...
Metodit sitäpaitsi eivät tee muuta tuossa pelissä, kuin ovat kenttiä, joten nimi "taso1" ja "taso2" yms kertovat kaiken tarvittavan.. no, katson nyt miten tuon teen... :)
Ps: olen lukenut tuon "meaningfulnames" monta kertaa :D
Mutta eihän liikkumismetodi voi olla riippuvainen kentän tasosta mitenkään? Ja muutoinkin eihän tuollaisella ohjelmoinnilla pääse puusta pitkään, koska joudut tekemään siis jokaiselle tasolle oman metodin, joka on oleellisilta osiltaan identtinen.
en joudu, teen sen tällä rakenteella:
liikkumismetodi { } taso1() { taulukko yms { } liikkuminen() } taso2() { taulukko yms { } liikkuminen() }
yms...
ja keksin jo tavan, minne sinne laitan ja miten sen tasonvaihdon :D
Edit: laitan siis sinne maalivertailun sisään, toisen vertailun, että onko esim taso1()=mennään tasoon2() ja niinpoispäin...
Edit: saako niitä hippatekoälyjä enää mistään ladattua, kun ajattelin katsoa mallia niistä, jos tekisin itseään seuraavan vihollisen? enkä itse osaa suoraan...
Millä tavalla nuo kaksi metodia ovat erilaisia, kun minusta ne ovat aivan identtiset, jos nimeä ei lasketa.
niissä on erilainen taulukko, sillä koko pelihän toimii talukossa, taulukko on vain erilainen/kokoinen, eri elementit ja kaikki.
No miksi niille taulukoille sitten tarvitaan omat funktiot?
Mikset tee vain yhtä funktiota, ja syöttele sille noita taulukoita parametrina?
Entä jos tekisi yhden oikein hyvän kenttäfunktion, joka osaa lukea tiedostosta kenttien speksit? Tällöin riittäisi tosiaan yksi kentän latausfunktio.
/* Kentän speksit */ vihu|12857|16859|30|61.7|8 vihu|9584|3257|68|81.9|3 kentta|25000|40000 maali|26354|37854
Yllä oleva on pätkä kenttätiedostoa, jonka pohjalta uusi kenttä voidaan ladata. Esimerkiksi vihu 12857 16859 30 61.7 8 voisi tarkoittaa, että luodaan vihu luokasta uusi olio, joka on kentällä pisteessa 12857 16859 hänellä on 30 % energiaa hänellä on 61.7 % todennäköisyys osua, sekä hänellä on 8 kutia lippaassa. Loput lienevät selviä?
Latausfunktio voisi toimia jotenkin seuraavasti
<?php $taso = file("taso1.txt"); $riveja = count($taso); for($i = 0; $i < $maara; $i++){ $tiedot = explode("|", $taso[$i]); if($tiedot[0] == 'vihu'){ Vihut[] = new Vihollinen($tiedot[1], $tiedot[2], $tiedot[3], $tiedot[4], $tiedot[5]); }else if($tiedot[0] == 'kentta'){ $kentta->asetaKoko($tiedot[1], $tiedot[2]); }else if($tiedot[0] == 'maali'){ $kentta->asetaMaali($tiedot[1], $tiedot[2]) } } ?>
öhöm?? väärä kieli :D ja sen tason taulukon pitää olla _juuri_ tietynlainen...
Javan standardikirjastosta löytynee vastaavat funktiot tuolle. Millä tavalla taulukon pitää olla tieynlainen?
esim: taso1() = tällainen:
######### # # # # # # # # # # # # # # # # # # # # # # # # # # #########
ja en oikeastikaan välttämättä jaksaisi laittaa kaikkea mahdollista hienoa sinne peliin, kun se toimii ihan yhtä hyvin omalla tavallanikin..
Et välttämättä nyt halua, mutta joskus voi tulla halua ja silloin tuolla periaatteella tehtynä jotkut muutokset voivat olla paljon helpompia, kuin tuosssa sinun versiossasi.
Jos välttämättä haluat taulukoida ne, niin mikset tee niistä taulukoista taulukkoa, jolloin voit valita oikean tason valitsemalla taulukosta oikean alkion?
Ruutu[][][] tasot = new Ruutu[][][]{ // Alustukset... };
Mutta silti tiedosto(i)sta lukeminen olisi merkittävästi fiksumpi tapa tehdä tuo ja sinunkin pitäisi jo osata toteuttaa se (esim. Scanner + switch/if).
P.S. Mitä väliä sillä on millä kielellä Teuro antaa esimerkkinsä, kun tarkoituksena ei ole välittää valmista toimivaa koodia, vaan idea siitä kuinka asian voisi toteuttaa. Tähän tarkoitukseen esim. C, C++, PHP, Java, pseudokoodi tai jokin basic-variantti kävisivät kaikki aivan yhtä hyvin.
Koskaan ei ole tarvetta valita metodia parametrin perusteella, sillä on aina mahdollista määritellä yksi metodi tekemään täysin eri asiat parametrin perusteella, jolloin tulos on sama.
Intuitiivisesti väitän myös että väite "With that caveat in mind, reflection is a powerful technique and can enable applications to perform operations which would otherwise be impossible." on virheellinen.
Java on yleiskäyttöinen kieli ilman reflektiotakin, ja sillä on mahdollista toteuttaa mikä tahansa missä tahansa konekielessä mahdollinen algoritmi. Se voi olla työlästä, mutta koska konekielikäskyjä on rajallinen määrä, on myös mahdollista toteuttaa miten tahansa muokattavissa oleva Java-koodin pätkä perus-Javalla. En siis väitä, etteikö reflektio olennaisesti lyhentäisi tarvittavaa Java-koodia jossain tilanteessa.
Monissa frameworkeissa reflektion käyttö on pakollista. Ajattele vaikka, miten JUnit voisi löytää suoritettavat testit ilman reflektiota. Tai miten Javan serialisaatio, ORM-frameworkit (esim. Hibernate), DI-frameworkit (esim. Guice) ynnä muut pitäisi toteuttaa, jos kielessä ei olisi reflektiota. Se vaatisi frameworkin käyttäjältä älyttömästi itseään toistavan koodin kirjoittamista tai esim. käännösaikaista koodin generointia.
Ja sitten kun reflektio ei enää riitä, niin lisäavuksi otetaan tavukoodin analysointi, generointi ja manipulointi. Joissain muissa kielissä (esim. Lisp) on parempi tuki ohjelman rakenteen muuttamiselle, mutta Javassa joudutaan käsittelemään tavukoodia.
En osaa lukea tiedostoista. ja tuo switch if-juttu?
Sami taisi tarkoittaa vain, että käyttäisit Scannerin kaverina switch–casea tai if-lausetta.
Kelpaisiko sinulle Arto Wiklan Java-kursseilla käytettävä materiaali? Sieltä löytyy myös perusasiaa tiedostoista.
Tommittaja kirjoitti:
En osaa lukea tiedostoista. ja tuo switch if-juttu?
No opetetaanpa...
File tiedosto = new File("tiedosto.txt"); try { Scanner skanneri = new Scanner(tiedosto); // Ja sitten vaan käytät sitä skanneria... } catch (FileNotFoundException e) { System.err.println("Tiedosto hukassa."); }
Tietääkseni olet jo opetellut käyttämään Scanner-luokkaa, joten tiedoston lukeminen ei eroa millään tavalla merkkijonojen parsimisesta (paitsi että tiedoston lukeminen voi epäonnistua).
kiitos tuosta! olen jo pitkään seissyt paikallani tässä opettelussa, sillä ei kirjaa, vaikkakin koko arto wiklan materiaalin saa netistä ;D... voisin kyllä ostaa sen kirjan jostain huuto.netistä, etten ihan jumiin jää.
muuten, kun se tiedosto, josta luetaan, on samassa kansiossa, kun se .class-tiedosto, niin eihän pathia tarvitse olla(siis muutakuin sen tiedoston nimi)?
PS: mikä hyöty on kirjoittaa esim:
catch (FileNotFoundException e)
kun voi kirjoittaa vain
catch (Exception e)
?
Tommittaja kirjoitti:
PS: mikä hyöty on kirjoittaa esim:
Jotta voi käsitellä erilaiset virheet eri tavalla ja vaikka tulostaa suomenkieliset virheilmoitukset ("tiedostoa ei löydy", "virhe tiedoston lukemisessa" jne.).
Tommittaja kirjoitti:
PS: mikä hyöty on kirjoittaa esim:
catch (FileNotFoundException e)kun voi kirjoittaa vain
catch (Exception e)?
No ei mitään hyötyä, jos ohjelma toimii oikein. Mutta pyydystämällä vain ne poikkeukset, joita odotetaan, huomataan jos tuleekin muita, sellaisia joita ohjelmoija ei ole odottanut. Jos niitä tulee, on koodissa virhe, joka voisi peittyä, jos kaikki poikkeukset käsitellään tavalla, joka on tarkoitettu vain tiettyä tilannetta varten. Esim. joku poikkeus ei jossain tilanteessa aiheuta mitään toimenpiteitä, mutta se koskee vain sitä odotettua poikkeusta.
juu, periaatteessa, itse laitan aina vain
catch (Exception e) {System.out.println("Virhe");}
voi olla myöskin, että en aina tiedä, mitä virheitä metodi voi tuottaa.
Edit: Sisuaski sanoi tuolla alussa, että "Mikset tee vain yhtä funktiota, ja syöttele sille noita taulukoita parametrina?"
miten? sillä sama parametri voisi olla hieman hankala tehdä, jos kerran jokaisen taulukon piirtoon tarvitsee erilaisen while-silmukan. jos tuo on mahdollista, neuvokaa vain, niin _yritän_ :)
Jos haluaa enempi tietoa poikkeuksesta,
e.printStackTrace();
Miksi taulukon piirtoon tarvitsisi erilaisen silmukan?
for (int i = 0; i < t.length; ++i) { for (int j = 0; j < t[i].length; ++j) { System.out.print(t[i][j]); } System.out.println(); }
oho. kun olen saanut apua tuohon taulukon piirtoon, olen vain käyttänyt sitä semmoisenaan, joten ei ole tullut mieleenkään laittaa sinne taulu.length :D olen vain laittanut jotenkin oudosti...
Tuskin olet tehnyt oudosti, mutta olet ehkä käyttänyt staattisia taulukon kokoja.
mitä tarkoitat staattisilla taulukon kooilla?
Taulukoissani siis lukee näin:
while (elamat > 0) { for (int i=0; i<10; ++i) { for (int j=0; j<11; ++j) { System.out.print(taulu[i][j]); if (j == 11-1) System.out.print("\n"); } } liikkuminen(taulu); }
kun en itse ole tehnyt näitä, tämä on aika omituinen tapa tehdä... mutta toimii. tarkoititko noilla staattisilla taulukon kooilla noita
for (int i=0; i<10; ++i) { for (int j=0; j<11; ++j) {
että se ei ole
for (int j=0; j<taulu.length; ++j)
PS: voisiko mitenkään laittaa tabulaattorit toimimaan viesteissä? inhottavaa kun ei toimi..
Tommittaja kirjoitti:
mitä tarkoitat staattisilla taulukon kooilla? tarkoititko noilla staattisilla taulukon kooilla noita
for (int i=0; i<10; ++i) { for (int j=0; j<11; ++j) {
Juurikin tuota tarkoitin, että olet "kovakoodannut" ne taulukon koot ohjelmaan.
Tommittaja kirjoitti:
juu, periaatteessa, itse laitan aina vain
catch (Exception e) {System.out.println("Virhe");}voi olla myöskin, että en aina tiedä, mitä virheitä metodi voi tuottaa.
Silloin ei tietysti tapahdu mitään vahinkoa, jos jokainen poikkeus on virhetilanne, joka edellyttää koodin korjaamista. Silloin saat noinkin tiedon siitä, että jotain on pielessä. Tarkempaa tietoa siitä, mitä on tapahtunut, saa myös metodilla getMessage, siis vaikka System.out.println("virhe: "+e.getMessage());.
Mutta useinhan try-catch pannaan siksi, että niiden välissä olevassa koodissa on jokin tarkistettava poikkeus, siis try-catch on pakko sinne laittaa, ellei metodi heitä poikkeusta ylemmälle tasolle. Ja silloin kai laitat virheilmoitukseen, että on tapahtunut odottamasi virhe, vaikkapa "tiedostoa ei ole olemassa". Jos pyydystät kaikki poikkeukset, tulee tuo ilmoitus myös silloin, kun tapahtuu jokin muu poikkeus, jota et ole osannut odottaa.
Jos koodissa tapahtuu vaikka nollalla jako, niin silti tulee ainoa määrittelemäsi virheilmoitus, että tiedostoa ei löydy. Ja se voi olennaisesti vaikeuttaa virheen löytämistä, koska etsit väärää ongelmaa. Jos virhe tulee vain harvoissa tilanteissa, voi olla ettet löydä sitä lainkaan, vaikka se on kerran tapahtunut, mutta ei toistu pian, ja oletat sen olevan eri tyyppinen.
Poikkeus ei valmiissa ohjelmassa yleensäkään ole ohjelman päättävä virhe, vaan tilanne, joka käsitellään tietyllä tavalla. Jos nappaat kaikki poikkeukset ja käsittelet ne tavalla, jolla odotettu poikkeus käsitellään, käy huonosti jos koodissasi on virhe, ja tapahtuukin jokin muu poikkeus.
Taulukkoajattelu pelialueesta on kieltämättä yksi vaihtoehto, mutta kokeilin tuota edellä mainitsemaani tapaa, jossa tiedostosta luetaan kentän tiedot, joiden pohjalta luodaan tarvittavat elementit kentälle. Kokeilun perusteella voisin jopa aika varmasti suositella kyseistä tapaa tällaisille peleille, joissa on seiniä ja esineitä, joita poimitaan kentältä.
Tommittajalla oli muistaakseni joku pelikin, jossa poimittiin hedelmiä kentältä? Tämä tapa sopisi minusta paremmin kyseiseen peliin. Tässä siis luodaan Kentta luokasta olio, joka lataa parametrinä annetun tiedoston muistiin, josta se siis luo uusia esimerkiksi seinäolioita. Kenttää voi vaihtaa helpolla antamalla uuden kentän ladattavaksi kenttäoliolle. Itse pelin tynkä on kirjoitettu c++ kielellä käyttäen allegron grafiikkakirjastoa apuna.
Tämä on lisäksi jossain määrin laajennettava järjestelmä, joten esimerkiksi uusia elementtejä on melko helppo lisätä järjestelmään. Käytännössä tämä vaatii tarvittavan luokan luomisen ja kenttätiedostoon kirjoittaa alustukset, sekä latausfunktioon rutiinit luomiselle.
Tällaisen järjestelmän haittana on tietysti se, että näkyvää ei saa aikaan kovinkaan nopeasti, koska tässä pitää tehdä aika paljon enemmän työtä. Mikäli jollekin heräsi kiinnostusta asiasta voin laittaa tuota jakoonkin jonnekin.
Nyt on julkastu uus versio siitä mun pelistä "Quest of ASCII"... liikkumismetodi on, uusi kenttä valmistui :D aion tehdä pari kenttää varmaan tänään vielä :)
Vieraskirja on uudistettu, ja nyt KAIKKI voivat kirjoittaa sinne :).. ennen piti rekisteröityä sinne mun sivulle.
Edit: nyt siellä on tapahtumakalenterikin! siellä lukee kaikki, mitä on tapahtuu...
Edit: ehkä yhden kentän sittenkin teen(tänään siis), sillä pitää tehdä muitakin muutoksia ja juttuja :) paitsi että kesällä on aikaa aina tehdä näitä; osa kylläkin pitää tätä ohjelmointia lähes työnä(vapaa ajalla), vaikkakin minä teen sitä ihan mielelläni :D
Julkaisin nyt sen 6-tasoisen version.. en viitsinyt laittaa vilkkuvia vihollisia liikaa, sillä pelkään sen hidastavan koodia hirveästi :D no, seuraavaksi uskallan... saatan kyllä olla laiskakin :P
Aihe on jo aika vanha, joten et voi enää vastata siihen.