Most folytatjuk a Basic nyelv megismerését. Ami az előző részben volt:
1. A print parancs
2. A változók használata, na meg minden ronda művelet velük
3. Elágazások (döntések)
4. Számlálós ciklusok
5. Végtelen ciklusok
Ami most jön:
6. A GOTO parancs
A Basic (meg akármilyen más programnyelv) parancsértelmezője egymás utáni veszi a programsorokat. Ezt azonban különböző vezérlési szerkezetekkel tudjuk befolyásolni. Ami gyakran előfordul. Az elágazásokkal és a ciklusokkal már megismerkedtünk. Vannak még az ugrások és az alprogramok. Először a feltétel nélküli ugrásról beszélünk. Ő a GOTO parancs. Önmagában azonban semmire se jó, mert meg kell határozni, hova ugorjon a parancsértelmező. Ezt a régi basicekben (pl. C64 Basic - a Qbasicben is lehet, de nem kötelező) a programsorok számozásával adtuk meg. A DarkBasicben (meg minden többi basicben) címkéket helyezhetünk el a programban. A címke egy kis karaktersorozat, nem lehet benne ékezet, nem egyezhet meg egy utasítás nevével, és ami legfontosabb: a végén kettőspontnak kell lennie. Nem írhatunk utána más parancsot: egyedül kell állnia a sor elején. És hogy miért kell össze-vissza ugrálni a programban ok nélkül? Mindjárt kiderül.
Hozzunk össze egy programot, amivel másodfokú egyenletet lehet számolgatni!
`Az egyenlethez szükségünk van az a,b,c értékekre:
eleje:
input "Az A értéke:",a
input "A B értéke:",b
input "A C értéke:",c
`És átírjuk a megoldóképletet a basic nyelvére.
`Legelőször vizsgáljuk meg, hogy van-e valós gyök.
if ((b^2)-(4*a*c))<0 then print "Nincs valós gyök!" : goto vege
`Számolás! A két gyököt külön-külön kiszámítjuk.
x1=((0-b)+sqrt((b^2)-(4*a*c)))/(2*a)
x2=((0-b)-sqrt((b^2)-(4*a*c)))/(2*a)
`Majd kiírjuk.
print "X1= ";x1
print "X2= ";x2
vege:
print "Új számoláshoz nyomj egy billentyűt! ESC-kel kiléphetsz."
`Egy billentyű lenyomásáig felfüggesztjük a program futását.
`Esc amúgy is kilépés, nem kell vizsgálnunk.
suspend for key
cls
goto eleje
A goto-val ciklust is lehet csinálni, de a DO-LOOP szerkezet átláthatóbb. Példa erre egy ősrégi közismert C64 (QB) program:
10 PRINT "SZIA"
20 GOTO 10
Dark Basicben ez így néz ki: (Sajnos a DB nem scrollozza printnél a képernyőt. Csak a DBPro az 1.05-ös verziótól kezdődően. De az se olyan szép, mint a DOS képernyő-scrollja :-)
start:
PRINT "SZIA"
goto start
Ennek a programnak nem volt sok értelme, de jólesett bepötyögni :-)
7. A GOSUB alprogram
Sokszor előfordul az, hogy egy programrészt (nevezzük alprogramnak) sokszor szeretnénk felhasználni, több helyen egy programban. Ezt GOTO-val nem tehetjük meg; egy olyan vezérlési szerkezet kell, ami az alprogram lefutása után a parancssor-értelmezőt visszaállítja az alprogram meghívása utáni sorba. Ez a Gosub-Return szerkezet. A Gosub olyan mint egy Goto, a program a Gosub utáni cimkére ugrik. Fut tovább addig, amíg returnhoz nem ér. Ekkor visszaugrik a meghívás helyére. A DB-nek nem ért, ha gosub nélkül összetalálkozik egy returnnal, a többi Basic azonban harap erre. Íme egy példa a használatára.
a=8 : b=6
gosub szamol
a=10 : b=20
gosub szamol
a=4 : b=24
gosub szamol
end
szamol:
print "A érték:";a;" B érték:";b
print "Összeg:";a+b
print "Különbség:";a-b
print "Szorzat:";a*b
print "Hányados:";a/b
return
8. A Function alprogramok
Ezek a felhasználó által készített függvények. Hogy mi köze van a függvényeknek az alprogramokhoz?
A QBasicben az alprogramok lehettek Subok vagy Functionok. A DB összemosta a két tipus között a határt.
A programozásban a függvény egy olyan utasítás, aminek visszatérési értrke van. A functionnak LEHET visszatérési értéke. De nem KÖTELEZŐ, hogy legyen. Ugyanígy lehet paramétere (bemenő értéke) is. Sokkal önállóbb, mint a gosub.
Előnyei:
-Akár külön fájlban tárolható
-DBpro-ban "összecsukható"
-Úgy lehet használni, mint egy parancsot
-Nem kell címkékkel szenvedni
Hátrányai:
-Át kell adni neki a változókat
Ajánlom ennek a szerkezetnek a használatát, a gosubhoz csak végveszélyban nyúljunk, ha túl sok bemenő változót használnánk. A hátránya (át kell adni neki a változókat) előnnyé válhat, mert lokális változókat használ. A lokális változó azt jelenti, hogy csak a functionban létezik, a program többi részén nem. Tehát a főprogramban is lehet ugyanolyan nevű változó, nem fog megegyezni az értékük.
Most már nézzük meg, miről van szó! Az alprogram maga:
Function Funcnév
(parancsok)
....
...
....
...
endfunction
Úgy hívjuk meg, hogy a parancsok közé egyszeren beírjuk az alprogram nevét.A DBpro kötelezővé teszi, hogy a funkciónév után legyen két zárójel: () . Nem tudom ez miért kell, a sima DB megvan nélküle. Nézzünk egy egyszerű példát.
randomize timer()
do
veletlenszoveg
loop
function veletlenszoveg
`Szín meghatározása
ink rgb(rnd(255),rnd(255),rnd(255)),0
`Hely meghatározása
set cursor rnd(640),rnd(480)
print "Ez a véletlen!"
endfunction
A program egy szöveget ír ki a képernyőre véletlen színnel a véletlenszerűen megadott koordinátákra. Ami új, az a véletlenszám számítása.
Véletlen számot az RND() függvény ad, a szám 0 és a zárójelek között megadott maximális érték között lesz. A probléma az, hogy minden futáskor ugyanazokat a "véletlen" számokat számolja ki a DB. Ezért a véletlenszám-generátor kezdőértékét kell változtatni. Ezt a Randomize paranccsal tehetjük meg. Utána írjuk kezdőértéknek a Timer() függvényt, ami az időt adja vissza ezredmásodpercekben. Így már tényleg véletlen számokat kapunk. A set cursor-ral a kiírás helyét állítjuk be, képpontokban.
A másik újdonság a function. Láthatjuk, az alprogram nevét úgy használjuk, mintha egy DB-s parancs lenne. De ha változót is kell használni?
x=100 : y=100
kiir
suspend for key
end
function kiir
set cursor x,y
print x;";";y
endfunction
Ha futtatjuk a programot, azt írja ki, hogy 0;0. Az x és y változót át kell adni az alprogramnak. Mert most az történik, hogy:
1, Az x és y felveszi a 100 értéket.
2, A kiir alprogram nem törődik a főprogram változóival. Ő is létrehoz egy x és egy y változót 0 értékkel. A főprogram változóinak értéke ettől 0 marad!
3, Ezek után az alprogram kiírja a változóit. Nem a főprograméit.
A megoldás: át kell adni az alprogramnak az x és y változót: (az alprogramban megváltoztattam a változóneveket az áttekinthetőség kedvéért)
x=100 : y=100
kiir(x,y)
suspend for key
end
function kiir(xhely,yhely)
set cursor xhely,yhely
print xhely;";";yhely
endfunction
Az alprogram meghívásánál (2.sor) átadjuk a két változó értékét az alprogramnak. Hogy ezek az értékek milyen néven kerülnek be az alprogramba, azt a funkció-deklaráció (function kiir(xhely,yhely) sor) után adjuk meg.
És ha az a szerencsétlen alprogram függvény szeretne lenni, mit kell csinálni?
egyik=10
masik=30
print kulonbseg(egyik,masik)
end
function kulonbseg(a,b)
c=a-b
endfunction c
Ehhez nem kell sok komment. A visszaadandó változót az endfunction után írjuk, és alprogramunkat függvénynek nevezhetjük.
A functionokat - mint már írtam - ki lehet exportálni külön dba-kba. Meghívásukhoz az #include parancs kell.
Használata: #include "fájlnév" Ezután használhatjuk a megadott fájlban lévő functionokat. A DBpro támogatja a több fájlra bontott forráskódot, ott nem kell "includeolni" azokat a fájlokat, amik a project managerben a "files" pontnál megjelennek (azaz már benne vannak a projectben).
Az end nem véletlenül van benne a programban. Ha a program meghívás nélkül szembetalálkozik egy functionnal, runtime error-t (futásközbeni hibát) kapunk.
Apropó, hibák. Hibákból 3 fajta van:
1, elírási hibák, hiányzó ciklusvégek vagy paraméterek, stb.: Ezeket a DB futtatás előtt kiszűri, amikor leellenőrzi a kódot
2, futásközbeni hibák: Ők futás közben jönnek elő, amikor egy parancsnak rossz értékeket adtunk, vagy mondjuk egy fájl nem létezik. Legalább a DB szól, hogy léteznek.
3, bugok: Ez az ősmagyar szó az olyan hibát jelöli, amit a DB nem vesz hibának, csak mi. Nem azt kapjuk, amit várunk. Ők a legalattomosabbak. Jó esetben hamar kiderül, mi okozza őket.
A hibajavítás külön művészet. A programozás leghálátlanabb feladata: nem veszi senki észre, ha kijavítjuk a programhibákat, de az mindenkinek feltűnik, hogyha benne marad a programban.
Vége ennek a kis kitérőnek, nézzünk valami mást:
9. Összetett változók: a tömbök
Gyakran elő fog fordulni, hogy programunknak sok adattal kell dolgoznia. Ezt a sok adatot tárolni kell valahol. Mindhez külön változónév kellene, és szerintem senki se kezdene 1000 változó értékét pl. egyenként megnövelni. Sok adat együttes kezelésére találták ki a tömböket. Míg az egyszerű változókat nem kell deklarálni (megadni a típusukat a parancsértelmezőnek a program elején), addig a tömböket kell. Ezt a DIM paranccsal végezhetjük el.
dim szamok(10)
vagy
dim tortek#(10)
vagy
dim szovegek$(10)
Többdimenziós is lehet egy tömb:
kétdimenziós:
dim szamok(10,10)
háromdimenziós:
dim szamok(10,10,10)
négydimenziós:
dim szamok(10,10,10,10)
ötdimenziós:
dim szamok(10,10,10,10,10)
(Ez a maximum - a dimenziót persze nem fizikailag/matematikailag kell értelmezni)
A típus-előjelekről (#,$) itt se kell megfeledkeznünk. A fent leírt parancsok egy 11 elemű tömböt készítettek. (Tipp: Érdemes a tömb 0. elemét szabadon hagyni, és ideinformációkat írogatni magáról a tömbről - pl. azt, hogy hány elemben van adat) Adat kiolvasása: változó=szamok(5) Ez a sor a számok tömb 5-ös elemének az értékét teszi változóba. Egy tömb kiválasztott elemével mindent meg lehet csinálni, amit egy egyszerű változóval. Adatok beleírása is egyszerű: szamok(5)=34534. El lehet játszadozni az egymásba pakolgatásukkal, pl. szamok(maximum(x,1),10)=minimum(0,x) Így is lehet értéket adni...
Nézzünk egy példaprogramot:
randomize timer()
dim adatok(10,10)
`feltöltés adatokkal
for i=1 to 10
for j=1 to 10
adatok(j,i)=rnd(9)
next j
next i
`Kiolvasás
for i=1 to 10
`A számokat egy stringgé alakítjuk, amit az a$ változó tárol.
for j=1 to 10
a$=a$+str$(adatok(j,i))
`Két szám közé + jel, az utolsó után =
if j<10 then a$=a$+" + " else a$=a$+" = "
`Nem csak stringként fűzzük egybe a számokat, össze is adjuk őket
a=a+adatok(j,i)
next j
`Az összeadás eredményét az a$ változó végére írjuk
a$=a$+str$(a)
`Kiírjuk
print a$
`Az összeget eltároljuk a dimben
adatok(0,i)=a
`Lenullázzuk a két változó értékét
a$="" : a=0
next i
`üres sor
print " "
`Most az előbb letárolt ösdszegeket adjuk össze
for i=1 to 10
`a$-be mennek a szöveggé alakított számok...
a$=a$+str$(adatok(0,i))
`...a-ba az összeg
a=a+adatok(0,i)
if i<10 then a$=a$+" + " else a$=a$+" = "
next i
`kiírjuk
a$=a$+str$(a)
print a$
Amint láthatjuk, a tömbök igen alkalmasak műveletek végzésére. És mivel ez egy játékírásra kifejlesztett basic, sok helyen fogjuk őket használni, pl. mátrix magasságának tárolása, ellenségek életerejének tárolása, stb...
Ezzel véget is ért a Basic-okítás, Úgy gondolom, ez az előző résszel együtt elég erős alapot ad arra, hogy belkezdj te is egy saját játék írásába. Azaz - előtte olvasd el a Dark Basic "Dark" részével (most csak a basicet tárgyaltuk) foglalkozó írást. De ez nem azt jelenti, hogy evvel vége a BASIC nyelv ismertetésének - sok minden maradt! Szóval következő hónapban még mélyebbre ássuk magunkat a Basic rejtelmeiben!