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 tTehdasJa 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 #1Ongelma 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 SubDebug-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.