Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: QB: Tallentaminen QBasicissa

Sivun loppuun

cool-driver [09.02.2009 10:39:49]

#

Eli voisiko joku kertoa miten koodataan QBasicissa tallentaminen.

Grez [09.02.2009 10:42:34]

#

Dim Talletettavateksti As String

Open "Talletus.txt" For Output As #1
Print #1, Talletettavateksti
Close #1

Juhko [09.02.2009 11:15:36]

#

Binary tallennus: https://www.ohjelmointiputka.net/koodivinkit/23392-qb-binary-tallennus
Kätevämpi,jos tallennat pelkkiä lukuja.

cool-driver [09.02.2009 11:28:12]

#

Haluaisin tallentaa tilanteen pelissä.

Metabolix [09.02.2009 11:34:58]

#

Silloin joudut tallentamaan kaikki tilanteen kannnalta olennaiset muuttujat sellaisessa muodossa, että pystyt myös lukemaan ne takaisin samassa järjestyksessä.

cool-driver [09.02.2009 13:25:00]

#

Metabolix kirjoitti:

Silloin joudut tallentamaan kaikki tilanteen kannnalta olennaiset muuttujat sellaisessa muodossa, että pystyt myös lukemaan ne takaisin samassa järjestyksessä.

Eli?

Metabolix [09.02.2009 13:35:44]

#

Kokeile seuraavaa koodia, lue se tarkasti ja käytä runsaasti aikaa omatoimiseen ajatteluun, jotta saisit itse sovellettua sitä ongelmaasi. Jos asia tuntuu ylivoimaiselta, jatka helpompien asioiden tekemistä ja palaa aiheeseen myöhemmin.

Dim UkkoX As Integer
Dim UkkoY As Integer

UkkoX = 10
UkkoY = 33

Print UkkoX
Print UkkoY

Open "peli.txt" For Output As #1
Print #1, UkkoX
Print #1, UkkoY
Close #1

UkkoX = 0
UkkoY = 0

Print UkkoX
Print UkkoY

Open "peli.txt" For Input As #1
Input #1, UkkoX
Input #1, UkkoY
Close #1

Print UkkoX
Print UkkoY

Juhko [09.02.2009 16:03:12]

#

Tuo on itse asiassa aika huono tapa, mutta silti sopiva aloittelijoille. Jos/kun ymmärrät tuon, opettele tämä tapa:

'alustetaan muuttujat
DIM UkkoX AS INTEGER
DIM UkkoY AS INTEGER

CLS

'--------- TALLENNUS ---------

'tämä koodinpätkä luo tiedoston, voit kopioida sen sellaisenaan koodiisi
OPEN "peli.sav" FOR OUTPUT AS #1
CLOSE #1

UkkoX = 10 'asetetaan muuttujien arvot
UkkoY = 33

PRINT "Muuttujat on luotu."
PRINT "UkkoX:"; UkkoX
PRINT "UkkoY:"; UkkoY
PRINT

OPEN "peli.sav" FOR BINARY AS #1 'avataan tiedosto binäärimuodossa
'Kirjoitetaan arvot. Muista jättää toinen parametri tyhjäksi.
PUT #1, , UkkoX
PUT #1, , UkkoY
CLOSE #1 'suljetaan tiedosto

'--------- LATAUS ----------

'tyhjennetään muuttujat
UkkoX = 0
UkkoY = 0

PRINT "Muuttujat on tyhjennetty."
PRINT "UkkoX:"; UkkoX
PRINT "UkkoY:"; UkkoY
PRINT

OPEN "peli.sav" FOR BINARY AS #1
'Luetaan arvot.
GET #1, , UkkoX
GET #1, , UkkoY
CLOSE #1

PRINT "Muuttujat on luettu."
PRINT "UkkoX"; UkkoX
PRINT "UkkoY"; UkkoY
PRINT

On myös mahdollista käyttää MKI$ ja CVI ym. -funktioita, mutta en ehkä suosittele niitä aloittelijoille.

Metabolix [09.02.2009 16:38:53]

#

Juhko kirjoitti:

Tuo on itse asiassa aika huono tapa, mutta silti sopiva aloittelijoille.

Jälkimmäinen lienee tässä tapauksessa tärkeämpi kriteeri. :) Jos (kun) koodiin tulee ensimmäisellä yrityksellä vakavia bugeja ja pitää miettiä, mikä on vikana, on paljon helpompi katsoa tiedostoa, jossa on jotain ymmärrettävää luettavaa.

Pienissä peleissä tekstimuotoinen tallennusformaatti ei muutenkaan ole välttämättä pahitteeksi. Huijarit pilaavat huijauksillaan lopulta vain oman ilonsa, ja tekstimuotoisia tallennuksia voi myös helpommin siirtää järjestelmästä toiseen. (Tämä etu ei tietenkään koske QB:tä.)

Jos dataa on paljon, binaaritallennus on tietenkin käytännöllisempää.

Juhko [09.02.2009 20:47:34]

#

Ja cool-driver: https://www.ohjelmointiputka.net/hak/?kieli­=QBasic

cool-driver [10.02.2009 21:01:02]

#

Eli tarkennan vielä ongelmani koska en tuolta sitä löytänyt. Tekstipeliin tarvitsen tallennus ja latauskoodi pätkän.

Metabolix [10.02.2009 21:07:30]

#

Tarkennan vielä vastausta: Tallenna ja lataa jokainen muuttuja (kuten esimerkkikoodeissa UkkoX ja UkkoY). Ei ole olemassa mitään yleispätevää "tallennus- ja latauskoodia".

Grez [10.02.2009 21:51:45]

#

Toisaalta ei jokaista muuttujaa tarvitse tallentaa erikseen. Jos toi QB ei olisi niin onneton romu, niin voisi melkeinpä suositella tekemään pelitiltanteesta tyypin ja tallentaa / ladata sen seuraavaan tyyliin:

TYPE peli
        Pelaaja AS STRING * 50
        Pisteet AS LONG
        SijaintiX AS LONG
        SijaintiY AS LONG
END TYPE

DIM Tilanne AS peli

Tilanne.Pelaaja = "Jorma"
Tilanne.Pisteet = 4838
Tilanne.SijaintiX = 33
Tilanne.SijaintiY = -3

'Tallennus
OPEN "peli.sav" FOR BINARY AS #1 LEN = LEN(peli)
PUT #1, , Tilanne
CLOSE #1

'Lataus
OPEN "peli.sav" FOR BINARY AS #1 LEN = LEN(peli)
GET #1, , Tilanne
CLOSE #1

Suurin ongelma mielestäni on, että tyypissä ei (luullakseni) voi QB:ssä olla taulukoita. Eli esimerkiksi seikkailupelissä mielellään pitäisi kirjaa pelaajan mukana olevista esineistä jonkinlaisessa Esineet(500) as integer taulukossa. Tokihan tuohon tyyppiin voi kirjoittaa 500 esinettä, joka toisaalta on joissakin kohti koodia selkeämpikin (Tilanne.EsineKultaraha = Tilanne.EsineKultaraha + 152), kuin taulukko. Ongelmaksi muodostuu moneen kohtaan tuleva copy&paste -koodi, jota ei tarvittaisi taulukon tapauksessa.

neau33 [11.02.2009 16:46:32]

#

Heippa taas!

tuo Grez'n esittämä systeemi on toimiva ja sitä voisikin laajentaa...

TYPE olio
  p AS STRING * 20
  pt AS STRING * 10
  x AS STRING * 4
  y AS STRING * 4
END TYPE

DIM SHARED xdim As Integer

xdim = 10 'esmes.

REDIM SHARED peli(1 TO xdim) As olio

DIM pelaaja AS STRING
DIM pisteet AS INTEGER
INPUT; "PELAAJA: ", pelaaja

IF LEN(pelaaja) > 20 THEN
   pelaaja = LEFT$(pelaaja, 20)
END IF

'...
pisteet = 1000000

peli.p = "pelaaja" + STRING$(20 - LEN(pelaaja), " ")
peli.pt =  LTRIM$(STR$(pisteet)) + STRING$(10 - LEN(LTRIM$(STR$(pisteet))), " ")
peli.x  = LTRIM$(STR$(UkkoX)) + STRING(4 - LEN(LTRIM$(STR$(UkkoX))), " ")
peli.y  = LTRIM$(STR$(UkkoY)) + STRING(4 - LEN(LTRIM$(STR$(UkkoY))), " ")

reclen% = Len(olio.p) + LEN(olio.pt) + LEN(olio.x) + LEN(olio.y)

'jos taulukon kokoa haluaa kasvatella lennossa pitää luoda
'tilapäinen taulukko jolle annetaan uudet rajat ja johon sit
'pukataan ensin vanhan taulukon kamat ja sit uudet kamat...
'---
REDIM temppi(1 TO UBOUND(peli) + 1) AS olio
FOR l = 1 TO UBOUD(temppi)
   SELECT CASE i
      CASE IS < UBOUND(temppi)
         temppi.p = peli.p
         'jne..
      CASE ELSE
         temppi.p = pelaaja + STRING$(20 - LEN(pelaaja), " ")
         'jne...
   END SELECT
NEXT i
peli() = temppi(): ERASE temppi
KILL "peli.sav"
'---

'Tallennus
OPEN "peli.sav" FOR RANDOM ACCESS WRITE AS #1 LEN = reclen% * UBOUND(peli)
FOR i = 1 TO UBOUND(peli)
   PUT #1, i * reclen%, peli(i)
NEXT i: CLOSE #1

'Lataus
OPEN "peli.sav" FOR RANDOM ACCESS READ AS #1 LEN = reclen% * UBOUND(peli)
FOR i = 1 TO CINT(LOF(1) / ((UBOUND(peli) * reclen% ^ 2))
   GET #1, i * reclen%, peli(i)
   IF INSTR(peli(i).p, pelaaja) > 0 Then
     UkkoX = VAL(RTRIM$(peli(i).x)))
     UkkoY = VAL(RTRIM$(peli(i).y)))
   End IF
NEXT i: CLOSE #1

-Nea-

PS. QB:n kanssa äheltämisestä on jo valovuosia joten en takaa toimivuutta...

Juhko [11.02.2009 18:31:19]

#

Grez kirjoitti:

että tyypissä ei (luullakseni) voi QB:ssä olla taulukoita.

Kyllä 7.1:ssä ainakin voi.

Metabolix [11.02.2009 18:49:30]

#

Juhko kirjoitti:

Grez kirjoitti:

että tyypissä ei (luullakseni) voi QB:ssä olla taulukoita.

Kyllä 7.1:ssä ainakin voi.

Kyse oli ehkä siitä, miten data säilytetään muistissa. Grezin väittämän voi testata yksinkertaisesti tarkistamalla tyypin koon.

TYPE t
	t(100) AS INTEGER
END TYPE

PRINT LEN(t)
' Eipä ole satoja tavuja ainakaan FreeBASICin QB-tilassa.

Nähtävästi tallennus kuitenkin FreeBASICin QB-tilassa mystisesti toimii odotetusti. Jos tämä on oikea QB:n ominaisuus, täytyy sanoa, että helpoksipa on tehty.

Grez [11.02.2009 19:02:45]

#

Juhko kirjoitti:

Kyllä 7.1:ssä ainakin voi.

Joo, tarkoitin sitä viimeistä ihan Quickbasic versiota (4.5), tuo 7.1:hän oli joku Microsoft Basic Professional Development System, mutta kai sitäkin sitten kutsutaan qb:ksi

Juhko [11.02.2009 19:12:11]

#

Metabolix kirjoitti:

(paljon tekstiä)

Vilkaiskaapa vielä tämä ohjelma:

DIM t(100) AS INTEGER

CLS
PRINT "Taulukko:"; VARSEG(t); VARPTR(t)
PRINT "Solut:"
FOR i% = 0 TO 100
  PRINT VARSEG(t(i%)); ":"; VARPTR(t(i%)),
NEXT i%

Taulukko on siis osoitin riippumatta siitä, onko se tyypissä vai ei.

Jos kiinnostaa, niin käytin itse tyyppeihin laitettuja taulukkoja tehdessäni graafista käyttöliittymää 7.1:llä, kansioiden käsittelyyn: folder(kansioindeksi).allFiles­(tiedostonNumeroKansiossa).name viittasi yhdessä avoinna olevassa kansiossa olevan yhden tiedoston nimeen.

Metabolix [11.02.2009 19:18:52]

#

Aivan, mutta mitä QB tekee, kun tallennat taulukon tiedostoon yhdellä PUT-komennolla tai luet yhdellä GET-komennolla?

Grez [11.02.2009 19:29:18]

#

Ihan hyvä kysymys sinänsä, koska se tallentaa 4 tavua nollaa. Eli se ei ole taulukon ensimmäinen alkio, koska se olisi vain 2 tavua ja nollaa tulee vaikka taulukossa olisikin jotain ihan muuta. Eikä se ole osoitin, koska se olisi jotain muuta kuin pelkkää nollaa.

Juhko [11.02.2009 19:30:12]

#

Niin ei voi tehdä, sillä QB tallentaa silloin sen ihme muuttujan muistipaikasta löytyvän sisällön. Kokeile seuraavaa koodia:

DIM t(100) AS INTEGER
DEF SEG = VARSEG(t)
POKE VARPTR(t), 1

OPEN "seivi.txt" FOR OUTPUT AS #1: CLOSE #1

OPEN "seivi.txt" FOR BINARY AS #1
PUT #1, , t
CLOSE #1

Edit: Grez ehti ensin...

Edit2: Onhan tietysti mahdollista, ettei t -nimistä muuttujaa ole olemassakaan. Esimerkiksi määrittelemättömän muuttujan VARSEG- ja VARPTR- funktiot palauttavat jonkin arvon, sillä QB alustaa muuttujan (nollaksi), kun sitä yritetään käsitellä ensimmäisen kerran.

Jos olen väärässä, niin huomauttakaa ihmeessä. :)

Metabolix [11.02.2009 19:50:21]

#

FB ei suostu tuota edes kääntämään, QB:tä minulla ei ole (eikä tule).

Onko QB:llä lopputulos sama myös silloin, kun taulukko on tyypissä? FB:n QB-tilan toimintaa tämä jostain syystä muuttaa, kuten jo mainitsin. Esimerkiksi seuraava koodi tuottaa sillä tiedoston, jossa on kymmenen tavua eli viisi lukua, kuten taulukossa, ja luvut ovat aivan sijoituksen mukaiset.

TYPE t
        t(4) AS INTEGER
END TYPE

DIM p AS t
DIM i AS INTEGER

FOR i = 0 TO 4: p.t(i) = (i+1) * 257: NEXT

OPEN "seivi.txt" FOR OUTPUT AS #1: CLOSE #1
OPEN "seivi.txt" FOR BINARY AS #1
PUT #1, , p
CLOSE #1

Rehellisesti sanoen en käsitä, miksi kukaan enää haluaa välttämättä käyttää QB:tä, jos nyt ei aivan erityisesti nauti juuri DOS-ohjelmoinnista. FreeBASIC tarjoaa vastaavat grafiikkatoiminnot, on tehokkaampi ja 32-bittinen, toimii useassa käyttöjärjestelmässä ja tukee tarvittaessa myös kaikenlaisia ulkoisia kirjastoja. :)

Grez [11.02.2009 20:06:10]

#

Siis kuten jo mainitsin, niin QB:llä (4.5) ei voi laittaa taulukkoa tyyppiin.

Ja samaa täytyy sanoa itsekin tuosta QB:stä. Piti ihan polkasta virtuaalikone käyntiin että pääsi testaamaan, kun eihän tuollainen 16-bittinen antiikki enää toimi näissä 64-bittisissä...

Juhko kirjoitti:

Edit2: Onhan tietysti mahdollista, ettei t -nimistä muuttujaa ole olemassakaan.

Ja tosiaan olet ihan oikeassa. Eihän tuollaisia hirveyksiä tule edes ajatelleeksi, mutta t() ja t ovat tosiaan erilliset muuttujat ja QB:ssähän ei mitään Option Explicitiä edes tueta :(

Grey [11.02.2009 20:07:38]

#

Metabolix kirjoitti:

ja 32-bittinen

Phew, 32-bittisyys on vanhentunutta! Nykyään se 64-bittisyys ja moniprosessorituki ovat sitä modernia ohjelmointia ^^

-Grey-

Grez [11.02.2009 20:14:09]

#

Grey kirjoitti:

Phew, 32-bittisyys on vanhentunutta! Nykyään se 64-bittisyys ja moniprosessorituki ovat sitä modernia ohjelmointia ^^

Tosin ainakin Windows-ympäristöissä 64-bittisten ohjelmien saatavuus on melkoisen onnetonta, Firefoxinkin joutuisi itse kääntämään jos haluaisi sen 64-bittisenä.

Tosin samahan se taisi olla silloin kuin 386 tuli, aika pitkään vielä monet softat sai vain 16-bittisinä.

Juhko [11.02.2009 20:22:37]

#

Metabolix kirjoitti:

Rehellisesti sanoen en käsitä, miksi kukaan enää haluaa välttämättä käyttää QB:tä, jos nyt ei aivan erityisesti nauti juuri DOS-ohjelmoinnista. FreeBASIC tarjoaa vastaavat grafiikkatoiminnot, on tehokkaampi ja 32-bittinen, toimii useassa käyttöjärjestelmässä ja tukee tarvittaessa myös kaikenlaisia ulkoisia kirjastoja. :)

Osasyy saattaa olla se, ettei FreeBASIC:issa ole IDE:ä. :/ Kun itse tein Jeppe-tekoälyäni, koodasin sen 7.1:n IDE:ssä, mutta käänsin FB:llä.

TsaTsaTsaa [13.02.2009 17:33:42]

#

Juhko kirjoitti:

Osasyy saattaa olla se, ettei FreeBASIC:issa ole IDE:ä. :/ Kun itse tein Jeppe-tekoälyäni, koodasin sen 7.1:n IDE:ssä, mutta käänsin FB:llä.

Eiks esim. tää kelpaa: http://fbide.freebasic.net/

Itse en ole testannut.

Juhko [13.02.2009 18:20:11]

#

Ai, mä en ollut kuullutkaan tuosta. :) Enpä sitten keksi enää muita syitä käyttää QB:tä.

Ja jos cool-driver välttämättä haluaa yleispätevän tallennuskoodin, niin on mahdollista tallentaa koko QB:n käyttämä muistialue (binäärimuodossa tietenkin). Tämä on kuitenkin viimeinen vaihtoehto, mitä kannattaa käyttää ja sen lisäksi todella hidas. Jos välttämättä haluat tehdä näin, tutustu POKE-käskyyn ja PEEK()-funktioon.

Grez [13.02.2009 21:29:26]

#

Juhko kirjoitti:

QB:n käyttämä muistialue (binäärimuodossa tietenkin). Tämä on kuitenkin viimeinen vaihtoehto, mitä kannattaa käyttää ja sen lisäksi todella hidas.

Miten niin todella hidas, mielestäni bload ja bsave on ihan vikkeliä. Tosin huono puoli on, etteivät ne pysty käsittelemään kuin yhtä segmenttiä kerrallaan, eli max 64k pystyy laittamaan samaan tiedostoon.

Juhko [13.02.2009 21:44:03]

#

Mitäs mä nyt taas sekoon, mä unohdin kokonaan bsaven ja bloadin! xD


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta