Luokkien yksi perusajatuksistahan on niiden pohjalta instanssien luominen. Nyt kuitenkin törmäsin ongelmaan instanssien kanssa. Tavallisestihan uusi luokka määriteltäisiin tässä tapauksessa näin: NPC botti=new NPC(); Nyt tarvittava määrä instansseja luokasta tulisikin määritellä ajon aikana skriptitiedoston ohjeiden mukaan.
Minulla on skriptitulkki, joka tulkkaa skriptikielen ja luo sen pohjalta NPCitä peliini. Olen luonut luokan NPC, jonka pelkistetty koodi löytyy alta. Ongelmaksi muodostuu uuden instanssin luominen "vauhdissa". Eli kun kutsutaan SkriptiTulkki-luokan createNPC()-metodia pitäisi pystyä luomann uusi instanssi NPC-luokasta. Miten mahtaa tämä onnistua, sillä eikös tämä ole yksi luokka-ajattelun tärkeimmistä eduista, joten kaipa se Javassakin onnistuu.
public class NPC { static int npcX=0, npcY=0, npcId=0; int[][] npcTaulukko=new int[10][2]; //luodaan taulukko, jonne laitetaan NPC:iden koordinaatteja (muutetaan vektoriksi) public void setX(int NPCKoordX){ //asetetaan NPCn x-koordinaatti npcX=NPCKoordX; } public void setY(int NPCKoordY){ //asetetaan NPCn y-koordinaatti npcY=NPCKoordY; } public void setId(int NPCId){ //asetetaan NPCn Id npcId=NPCId; } public int getX(){ return npcX; //palautetaan NPC:n x-korodinaatti } public int getY(){ return npcY; //palautetaan NPC:n y-korodinaatti } public int getId(){ return npcId; //palautetaan NPC:n id-numero } public boolean exists(int npcKoordX, int npcKoordY){ //metodi palauttaa arvon true jos koordinaateista löytyi NPC if(npcKoordX==npcX && npcKoordY==npcY){ return true; } else return false; } public void addPuhe(String lisättäväPuhe){ //lisätään puhepinkkaan parametrinä annettu puhe //koodi tähän } public String getPuhe(){ //palautetaan puheet //koodi tähän } }
Muoks.
Itse itselleni vastaten mietin vaihtoehdoksi taulukkoa. Eli luodaan taulukko luokasta NPC ja sen avulla saadaan joku rajattu määrä NPCitä yhdelle kartalle.
Mutta onko mitään parempaa keinoa tähän ongelmaan?
Etkö ole törmännyt Javan Collectioneihin? http://java.sun.com/docs/books/tutorial/
Eli listoihin, pinoihin ja muihin?
Tuossa voisi käyttää vaikka java.util.Vector-luokkaa.
Kiitos vastauksesta!
Kyllähän noita vastaan on tullut, ja olen niitä käyttänytkin, mutta kun tuli ongelma yllättäen vastaan eivät Collectionit tulleet heti mieleen. Ehkä vähän hätiköiden tännekin postasin. Tuohan vastaa vähän tuota taulukkotyyliä, jota itse ajattelin. Tietysti Vektori-luokalla homma hoituu ilman rajoituksia.
En kylläkään tähän tarkoitukseen noita Collectioneita ole käyttänyt, tai edes ajatellut asiaa, mutta aina oppii uutta.
Pitää nyt vielä kokeilla implementoida tätä koodiin, mutta toivottavasti onnistuu.
Lyhyesti se voisi mennä näin:
Vector<NPC> npcvektori = new Vector<NPC>(); NPC npc; while ((npc = hae_seuraava_npc()) != null) { npcvektori.add(npc); }
Tässä esimerkissä hae_seuraava_npc() palauttaa NPC-olion ja sitten kun NPC-data on loppunut niin nullin.
Ajattelin tehdä selkeän kokeiluohjelman, joka demonstroisi vektorien toimintaa, mutta nyt vektorin kaikki solut muuttuvat yhtä vaihdettaessa. Tässä vielä linkki jos kokeilla haluaa: http://user.personal.fi/atk/Kaakeliuuni/Container-testi/bin/Vektori.html
Lähdekoodi:
import java.awt.*; import java.awt.event.*; import java.applet.*; import java.util.Vector; public class ContainerTesti extends Applet implements ActionListener{ /** * Pyrkii demonstroimaan vektorien toimintaa */ private static final long serialVersionUID = 1L; Vector<Auto> autoVektori = new Vector<Auto>(); //vektori autoille Auto vehe=new Auto(); //Auto-luokka //GUI Button nappi1=new Button(); Button nappi2=new Button(); Button nappi3=new Button(); TextArea teksti=new TextArea(); //tekstikenttä näyttää arvoja public void init(){ this.setSize(370, 370); //lisätään napit ja asetetaaan niille tapahtumakuuntelijat add(nappi1=new Button("Henkilöauto")); nappi1.addActionListener(this); add(nappi2=new Button("Kuorma-auto")); nappi2.addActionListener(this); add(nappi3=new Button("Urheiluauto")); nappi3.addActionListener(this); add(teksti); //lisätään myös tekstikenttä repaint(); } public void paint(Graphics g){ //piiretään GUI nappi1.setBounds(10, 20, 80, 20); nappi2.setBounds(100, 20, 80, 20); nappi3.setBounds(190, 20, 80, 20); teksti.setBounds(10, 50, 360, 180); } public void actionPerformed(ActionEvent e) { //riippuen napista kutsutaan createAuto-metodia eri parametreillä if(e.getActionCommand().equals("Henkilöauto")){ teksti.setText(""); autoVektori.add(createAtuo("Henkilöauto")); tulostaVektori(autoVektori); } if(e.getActionCommand().equals("Kuorma-auto")){ teksti.setText(""); autoVektori.add(createAtuo("Kuorma-auto")); tulostaVektori(autoVektori); } if(e.getActionCommand().equals("Urheiluauto")){ teksti.setText(""); autoVektori.add(createAtuo("Urheiluauto")); tulostaVektori(autoVektori); } } public Auto createAtuo(String tyyli){ //varmaankin tämän metodin toimintaa pitäisi muuttaa vehe.setMalli(tyyli); return vehe; } public void tulostaVektori(Vector<Auto> vektori){ //tulostaa vektorin int pituus=vektori.size(); for(int i=0; i<pituus; i++){ teksti.setText(teksti.getText()+" "+vektori.get(i).getMalli()); } } }
Auto-luokka:
public class Auto { private String autonMalli; public void setMalli(String malli){ autonMalli=malli; } public String getMalli(){ return autonMalli; } }
No niin tekevät, kun käytät kaikissa samaa Auto-luokan edustajaa, jonka olet luonut muuttujaan vehe. Pitäisi joka kerta createAtuo-funktiossa luoda uusi Auto.
Olio a = new Olio(); Olio b; a.muuttuja = 1; b = a; b.muuttuja = 2; if (a.muuttuja == b.muuttuja) { // Tännehän tässäkin päädytään, koska a ja b viittaavat samaan olioon. }
Tietystihän tuo oli noin.
Kiitokset taas kärsivällisyydestä!
Jos haluat ensin kopioida Auto-olion ja asettaa kopiolle vain osan tiedoista toisiksi, niin voit lisätä kopiokonstruktorin, esim. näin:
public class Auto { private String autonMalli; public Auto(Auto kopioitava) { this.autonMalli = new String(kopioitava.autonMalli); // Ja jos luokalla on muita jäsenmuuttujia, niin nekin tietysti kopioidaan tässä... Siis kopioidaan koko olio muuttujineen, eikä vain viittauksia. } public void setMalli(String malli){ autonMalli=malli; } public String getMalli(){ return autonMalli; } }
Ja tätähän voi sitten käyttää näin:
public Auto createAtuo(String tyyli){ Auto uusiVehe = new Auto(vehe) uusiVehe.setMalli(tyyli); return uusiVehe; }
Jep. Sainkin tuon jo toimimaan niin kuin halusin. Ja tuo laittamasi esimerkkikin oli ihan hyödyllinen.
Aihe on jo aika vanha, joten et voi enää vastata siihen.