Luin tuosta Microsoft Press: Microsoft Visual Basic 6.0 Ohjelmoijan käsikirja-kirjasta, että:
Muuttujataulukot ovat aina yhtäjaksoisia; toisin kuin ohjausobjektitaulukoista, muuttujataulukoista et voi poistaa
tai ladata elementtejä keskelle.
Ohjelmani lukee tekstitiedostosta tietoa tehtaista, joita voi olla
tuntematon määrä, ja jokaisesta tehtaasta se ottaa tietoja tähän tyyliin:
Type tTehdas nimi As String sijainti As String tyopaikat As Long tyontekijoita As Long palkka As Long verotus As Long End Type Public tehdas() as tTehdas
Ja sitten koodissa luetaan tietoa:
Open App.Path & "\Tekstit\" & yhtion_nimi & ".amt" For Input As #1 Dim i As Integer Do While Not EOF(1) i = i + 1 ReDim Preserve Tehdas(1 To i) Input #1, Tehdas(i).nimi Input #1, Tehdas(i).sijainti Input #1, Tehdas(i).tyopaikat Input #1, Tehdas(i).tyontekijoita Input #1, Tehdas(i).palkka Input #1, Tehdas(i).verotus Loop Close #1
Ongelma on se, että minkälaista koodia tulisi kirjoittaa
kun pelaaja (käyttäjä) sulkee yhden tehtaan, niin
miten sen voi poistaa taulukosta?
Ja sitten se taulukko pitäisi vielä järjestää niin, että siinä ei ole tyhjiä elementtejä.
Sitten pitäisi vielä pystyä perustamaan uusi tehdas.
Tapoja on useita. Jos tehtaiden järjestyksellä ei ole väliä, voit lisätä tyyppiin muuttujan "varattu As Boolean", jonka arvo on True silloin, kun sen kohdalla on toiminnassa oleva tehdas. Kun lisäät uuden tehtaan, käy taulukkoa läpi, kunnes vastaan tulee ensimmäinen vapaa kohta. Siihen merkitään tehtaan tiedot ja varattu-muuttujan arvoksi tulee True. Kun poistat tehtaan, merkitse varattu-muuttujan arvoksi False. Kun näytät kaikki pelaajan tehtaat, älä ota niitä tehtaita lukuun ollenkaan, joiden varattu-muuttuja on False.
muok: Tämä siis muuttumattoman kokoisella taulukolla.
Taulukkoon lisääminen onnistuu juuri tuolla jo käyttämälläsi ReDim-systeemillä, tehtaan tiedot vain otetaan eri paikasta.
Poistamisessa ehkä helpoin tapa on se, että siirrät viimeisen tehtaan sen poistettavan paikalle ja pienennät taulukkoa ReDimillä (kai niin voi tehdä?).
Toki noita voi pitää muunkin laisissa rakenteissa kuin taulukossa. En sitten tiedä, miten ne toimivat VB:ssä. Itse pidän linkitetystä listasta, kun silloin saa helposti lisättyä ja poistettua keskeltäkin. Taulukko voi kuitenkin olla helpompi ymmärtää ja VB:ssä möys käsitellä.
Eikös boolean tietotyypin oletusarvo ole False?
Jo vain. (Asia on myös helppo tarkistaa. ;)
Yksi onglema tuli. Kun minä lisään nuiden tehtaitten nimi-ominaisuudet tuohon listaan. Sitten siinä vieressä on semmoinen nappula josta voi poistaa tehtaan. Niin kun
aiemmin minulla oli koodissa:
For i = Lbound(tehdas) to Ubound(tehdas) Step 1
If tehdas(i).suljettu = False Then
list1.Additem tehdas(i).nimi
End If
Next
Ja sitten koodissa tuo nappula tunnistaa mikä tehdas
halutaan sulkea näin:
Tehdas(list1.listindex + 1).suljettu = True
Ei sitten enään toimi tuo kun ei enään kirjoita listalle
kaikkia tehtaita, niin tuo listindex + 1 ei vastaa
tehdas()-taulukon indexiä ja menee ihan sekaisin
sen toiminta.
Eikä sekään toiminut se otetaan viimeinen elementti ja
kirjoitetaan se poistettavan päälle, ja sitten
lyhennetään taulukkoa yhdellä elementillä.
Valitti: Type Mismatch
Tosiaan suoraan ListIndexin käyttö ei tule kysymykseen. Voit kuitenkin käyttää apuna ItemData-ominaisuutta, jolloin jokaiselle listan riville voi määrittää oman paikasta riippumattoman tunnusnumeron. Kun lisäät uuden rivin listalle, määritä siis heti perään sen ItemData-ominaisuus oikeaksi. Sitten voit poistaa rivin listalta ListIndexin perusteella mutta taulukosta ItemDatan perusteella.
Antti Laaksonen kirjoitti:
Jo vain. (Asia on myös helppo tarkistaa. ;)
Tarkistinpa tuon muuten ihan huvin vuoksi Printillä, jolloin se tulosti formille Booleanin arvosta riippuen "Tosi" tai "Epätosi" ihan suomeksi. Kumma juttu, sillä käyttikseni on ihan englanninkielinen, ja VB samoin. :)
Lokalisaatio se iskee joka paikkaan. Ärsyttää, kun kaikki installerit kattoo, että "Haa! maa-asetuksena on Suomi, toi haluaa varmaan lukee suomee, vaikka käyttiksen kieli on englanti" ja tarjoilee jotain kökkösuomennosta.
Mun käyttis on suomeks ja kuitenkin antaa false tai true. kumma juttu.. :)
Mulla on kans suomeksi ja true ja false tulee englanniksi.
Voisko tuossa hunajavohvelin tilanteessa tehdä näin:
Dim a as boolean
a = epätosi
Lumi-ukkeli kirjoitti:
Mulla on kans suomeksi ja true ja false tulee englanniksi.
Voisko tuossa hunajavohvelin tilanteessa tehdä näin:
Dim a as boolean
a = epätosi
En nyt oikein käsitä, mitä ajat takaa. Eihän se minua tietenkään haittaa, vaikka se tulostaisikin suomeksi, kun tulostin sen vain testimielessä. Tuo koodi vain asettaisi aan arvoksi saman, joka on epätosi-nimisessä muuttujassa.
Miten tuo ongelma olisi tarkoitus ratkaista, kun en minä osaa käyttää sitä ItemDataa?
Menee niin monimutkaiseksi, ettei tuosta ymmärrä.
Vähän esimerkkiä?
Tässä tulee esimerkki, jossa lomakkeella on lista (List1). Aluksi listalle lisätään neljä nimeä, joiden tiedot tallennetaan myös taulukkoon. Kun nimen kohdalta painetaan, se katoaa listalta ja taulukosta. Tätä voinet soveltaa myös omassa pelissäsi.
' nimien maksimimäärä Const NIMIMAARA = 50 ' nimet sisältävä taulukko Dim nimet(NIMIMAARA) As TNIMI ' nimitaulukon tyyppi Private Type TNIMI nimi As String varattu As Boolean End Type ' tyhjentää koko nimitaulukon Sub TyhjennaNimet() Dim i As Integer ' muutetaan kaikki nimet vapaiksi For i = 0 To NIMIMAARA nimet(i).varattu = False Next End Sub ' lisää nimen taulukkoon ja listalle Sub LisaaNimi(nimi As String) Dim i As Integer ' käydään läpi taulukkoa For i = 0 To NIMIMAARA ' jos paikka on vapaa... If Not nimet(i).varattu Then ' muutetaan se varatuksi ja pannaan siihen nimi nimet(i).varattu = True nimet(i).nimi = nimi ' lisätään nimi listalle List1.AddItem nimi ' kirjoitetaan ItemDataan vastaava kohta taulukossa List1.ItemData(List1.ListCount - 1) = i Debug.Print nimi & " lisätty." ' poistutaan aliohjelmasta Exit Sub End If Next Debug.Print "Nimi ei mahtunut taulukkoon!" End Sub ' poistaa nimen taulukosta Sub PoistaNimi(tunnus As Integer) ' muutetaan nimen paikka vapaaksi nimet(tunnus).varattu = False Debug.Print nimet(tunnus).nimi & " poistettu." End Sub Private Sub Form_Load() ' lisätään listalle neljä nimeä LisaaNimi "Erkki" LisaaNimi "Liisa" LisaaNimi "Pauli" LisaaNimi "Pentti" End Sub Private Sub List1_Click() ' poistetaan nimi taulukosta PoistaNimi List1.ItemData(List1.ListIndex) ' poistetaan nimi listalta List1.RemoveItem List1.ListIndex End Sub
Debug-alkuiset rivit kirjoittavat tietoja Debug-ikkunaan. Ne voit poistaa lopullisesta koodista. Mutta määritä taulukko niin suureksi, että tila ei lopu kesken!
hunajavohveli kirjoitti:
Lumi-ukkeli kirjoitti:
Mulla on kans suomeksi ja true ja false tulee englanniksi.
Voisko tuossa hunajavohvelin tilanteessa tehdä näin:
Dim a as boolean
a = epätosiEn nyt oikein käsitä, mitä ajat takaa. Eihän se minua tietenkään haittaa, vaikka se tulostaisikin suomeksi, kun tulostin sen vain testimielessä. Tuo koodi vain asettaisi aan arvoksi saman, joka on epätosi-nimisessä muuttujassa.
Siis tarkoitin että jos tuo olisi niin kuin tavallisesti, niin sehän menisi
Dim a as boolean
a = False
mutta ajattelin, että jos sinulla käy tuo sama myös suomeksi, niin menisi näin
Dim a as boolean
a = epätosi
Eikä se epätosi mikään muuttuja ole.
Ei käy, tuo suomennos vaikuttaa (jos vaikuttaa) vain siihen, jos printtaat boolean-tyyppisen muuttujan johonkin.
Esim.
Dim a As Boolean a = False Print a 'Printtaa "False" tai "Epätosi"
Aihe on jo aika vanha, joten et voi enää vastata siihen.