Übersicht
DirectQB Tutorial
Teil 5 Keyboard
3D-Grunglagen
in QBasic
ASM Tutorial Teil
2 Interrupts
ASM Tutorial Teil
3 Der Stack
Turbo
Pascal Tutorial 1 Grundaufbau
Turbo
Pascal Tutorial 2 Ein- und Ausgabe von Text
Turbo
Pascal Tutorial 3 Auswahlstrukturen
Anfängerkurs
2
Bonus
|
Hallo QBasic-Times-Leser.
Auch in dieser Ausgaber der QBasic Times
gibt es wieder viel zu entdecken.
Neben einem DirectQB Tutorial geht es
diesmal um Assembler und Turbo-Pascal.
Wer sich für 3D interessiert sollte
sich das 3D Grundlagen Tutorial nicht entgehen lassen.
Im Anfänger Tutorial geht es diesmal
um Rekursion.
Und wer immer noch nicht genug hat, kann
sich den Bonus ansehen, in dem es ums Keyboard geht.
Also viel Spaß beim stöbern.
DirectQB Tutorial Teil 5 Keyboard
Habt ihr euch nicht auch manchmal eine
richtig gute Inkeyroutine gewünscht. Ich meine, Inkey$ ist zwar zum
eingeben einzelner Buchstaben nicht schlecht aber für ein Spiel, bei
welchem man die Cusortasten benötigt, ist es der absolute Schwachsinn.
Man kann immer nur eine Taste drücken, es kommt immer zu einer Verzögerung
und wenn man zu lange drückt, schreit der Computer herum, dass man
doch gefälligst die Tasten los lassen soll (das BEEP).
Wie wäre es den mit einer Routine,
bei der man immer genau weiß, welche Taste gerade gedrückt wird
und welche gerade nicht gedrückt wird?
Nun, DirectQB bietet diese Routine. Leider
hat diese einige Nachteile aber dazu komme ich später.
Das wichtigste ist der Befehl
DQBinstallKeyboard
Dabei wird die Routine in den Speicher
geladen und ist gleich aktiv.
Mit der Funktion
DQBkey(X)
Kann man dann in Erfahrung bringen, welche
Taste gerade gedrückt wird.
Das X ist die Zahl der Taste, der Status
man ermitteln möchte.
Es ist zum Beispiel die 1 für ESC.
DQBkey liefert dann einen Wert ungleich
Null zurück wenn die Taste gedrückt wird. Wenn die taste nicht
gedrückt wird, wird der Wert gleich Null zurück geliefert.
Um die Keyboardroutine wieder zu deaktivieren
muß man einfach nur
DQBremoveKeyboard
Ausführen.
Das wars eigentlich schon. Aber kommen
wir nun zu den Problemen.
So lange die Routine aktiv ist, das heißt,
nachdem DQBinstallKeyboard ausgeführt wurde, kann QBasic keine Tasten
basierenden Funktionen mehr starten. Es funktioniert weder INKEY$
noch SLEEP 0 oder Input.
Das QBasic-Program kann auch nicht
mehr durch STRG + Pause beendet werden.
Man hat dann auch keine Kontrolle mehr
über QBasic selbst.
Es ist dann so, als ob das Keyboard nicht
mehr angeschlossen ist.
Es ist also unbedingt zu beachten, dass
immer DQBremoveKeyboard vor dem Beenden des Programms ausgeführt wird.
Wenn man dieses vergißt, kann man den PC nur noch neu starten.
Hier jetzt die List für die Tasten
1 = ESC
2 = 1
3 = 2
4 = 3
5 = 4
6 = 5
7 = 6
8 = 7
9 = 9
10 = 0
11 = - oder _
12 = = oder +
13 = Backspace
14 = Tab
15 = Q
17 = W
18 = E
19 = R
20 = T
21 = Y
22 = U
23 = I
24 = O
25 = P
26 = [ oder {
27 = ] oder }
28 = Enter
29 = Control
30 = A
31 = S
32 = D
33 = F
34 = G
35 = H
36 = J
37 = K
38 = L
39 = ; oder :
40 = ' oder "
41 = \ oder ~
42 = linkes Shift
44 = Z
45 = X
46 = C
47 = V
48 = B
49 = N
50 = M
51 = , oder <
52 = . oder >
53 = / oder ?
54 = rechtes Shift
55 = * oder Druck
56 = ALT
57 = Leer
58 = Caps Lock
59 = F1
60 = F2
61 = F3
62 = F4
63 = F5
64 = F6
65 = F7
66 = F8
67 = F9
68 = F10
69 = Num lock
70 = Rollen
71 = 7 oder Home
72 = 8 oder Hoch
73 = 9 oder Page up
74 = -
75 = 4 oder Links
76 = 5
77 = 6 oder Rechts
78 = +
79 = 1 oder END
80 = 2 oder Runter
81 = 3 oder Seite runter
82 = 0 oder Einfg
83 = . oder Entf
87 = F11
88 = F12
Diese List ist für ein Amerikanisches
Keyboard.
Hier noch ein Beispiel:
' All Integer für
die Geschwindigkeit
DEFINT A-Z
'$INCLUDE:'DIRECTQB.BI'
' Es wird DQB ohne
Extras geladen
IF DQBinit(0, 0,
0) THEN DQBclose: PRINT DQBerror$: END
' Keyboardroutine
wird installiert
DQBinstallKeyboard
CLS
PRINT "Keyboard
DEMO drücke eine Taste für seinen Scanncode. Es sind auch mehrere
Tasten gleichzeitig erlaubt ; Drücke ESC zum Beenden."
DO
LOCATE 3, 1
' Suche nach allen Tasten
FOR i = 0 TO 127
' Wenn eine Taste gedrückt wird dann zeige sie an
IF DQBkey(i) THEN PRINT "[" + LTRIM$(STR$(i)) + "] ";
NEXT i
' Löscht ein
Stück das Bildschirms
PRINT SPACE$(40)
' Schleife verlasen
wenn ESC gedrückt wird
LOOP UNTIL DQBkey(KEYESC)
' Beende KeyboardRoutine
DQBremoveKeyboard
' Beende Programm
DQBclose
Ich denke, dass das das Wichtigste war.
Das wichtigste was man zur 3D Programmierung
wissen muß, ist die Tatsache, dass man auf dem Bildschirm keine dreidimensionalen
Objekte darstellen kann. Der Bildschirm ist dafür ein bißchen
zu flach.
Aber man kann einen Trick ausnutzen. Nämlich
je weiter Etwas vom Beobachter entfernt steht, um so kleiner ist es.
So kann man sich den 3D Raum vorstellen.
Y ist die horizontale Achse
Z ist die vertikale Achse
X ist die Achse die aus dem Bildschirm
kommt
a ist der XY Ebene
b ist der Winkel der Z-Achse
Also wie erzeuge ich den Effekt der Tiefe?
Wir haben von dem Objekt die X, Y und Z Koordinaten. Diese müssen in X und Y Koordinaten des Bildschirms um gewandelt werden. Das geht mit folgenden Formeln:
x2D = 256 * (x3D
/ (z3D + zCenter)) + xCenter
y2D = 256 * (y3D
/ (z3D + zCenter)) + yCenter
x2D und y2D sind die Koordinaten des Punktes
der auf dem Bildschirm dargestellt wird.
x3D , y3D und z3D sind die Koordinaten
des Objekts im dreidimensionalen Raum
xCenter , yCenter und zCenter sind Zentumwerte
des Objekts.
Nun soll sich das Objekt aber auch bewegen
und vielleicht sogar drehen.
Wie geht das?
Als erstes brauchen wir zwei Winkel a und b und diese Formeln:
xR = -xO * SIN(a)
+ yO * COS(a)
yR = -xO * COS(a)
* SIN(b) - yO * SIN(a) * SIN(b) - zO * COS(b)
zR = -xO * COS(a)
* COS(b) - yO * SIN(a) * COS(b) + zO * SIN(b)
xO , yO , und zO stehen für die Originalkoordinaten
des Punktes im Raum
xR , yR , und zR stehen für den gedrehten
Punkt.
a und b sind die Winkel der horizontalen
und vertikalen Rotation
Kompliziert?
Vielleicht wird es mit diesem Beispiel
verständlicher.
*************************
3D Beispiel von
Soeren Dressler
e-mail: soeren01@t-online.de
url: fly.to/qmystic
*************************
DIM S!(359)
DIM C!(359)
DIM x3d(100, 1)
DIM y3d(100, 1)
DIM z3d(100, 1)
DIM x2d(100, 1)
DIM y2d(100, 1)
DIM ox3d(100, 1)
DIM oy3d(100, 1)
DIM oz3d(100, 1)
DIM olx2d(100, 1)
DIM oly2d(100, 1)
DIM olz2d(100, 1)
CONST PI = 3.141592
FOR i = 0 TO 359
S!(i)
= SIN(i * (PI / 180))
C!(i)
= COS(i * (PI / 180))
NEXT
SCREEN 13
zCenter = 100
xCenter = 150
yCenter = 100
FOR n% = 1 TO 20
FOR nn% = 0 TO 1
READ ox3d(n%, nn%),
oy3d(n%, nn%), oz3d(n%, nn%)
NEXT nn%
NEXT n%
u = 0 ' erster
Winkel
i = 0 ' zweiter
Winkel
a = 1 ' Rotation
fuer u
b = 1 ' Rotation
fuer i
DO
LOCATE 1, 1: PRINT
"Taste druecken zum beenden"
q = q + 1
IF q = 1 THEN
u = u + a
i = i + b
q = 0
IF u >= 360 THEN
u = u - 360
IF u < 0 THEN
u = u + 360
IF i >= 360 THEN
i = i - 360
IF i < 0 THEN
i = i + 360
END IF
FOR n% = 1 TO 20
olx2d(n%, 0) = x2d(n%,
0)
oly2d(n%, 0) = y2d(n%,
0)
olx2d(n%, 1) = x2d(n%,
1)
oly2d(n%, 1) = y2d(n%,
1)
'Rotation
x3d(n%, 0) = -ox3d(n%, 0) * S!(u) + oy3d(n%, 0) * C!(u) + l
y3d(n%, 0) = -ox3d(n%, 0) * C!(u) * S!(i) - oy3d(n%, 0) * S!(u) * S!(i)
- oz3d(n%, 0) * C!(i)
z3d(n%, 0) = -ox3d(n%, 0) * C!(u) * C!(i) - oy3d(n%, 0) * S!(u) * C!(i)
+ oz3d(n%, 0) * S!(i)
x3d(n%, 1) = -ox3d(n%, 1) * S!(u) + oy3d(n%, 1) * C!(u) + l
y3d(n%, 1) = -ox3d(n%, 1) * C!(u) * S!(i) - oy3d(n%, 1) * S!(u) * S!(i)
- oz3d(n%, 1) * C!(i)
z3d(n%, 1) = -ox3d(n%, 1) * C!(u) * C!(i) - oy3d(n%, 1) * S!(u) * C!(i)
+ oz3d(n%, 1) * S!(i)
' Umwandeln von 3D
in 2D
x2d(n%, 0) = 256
* (x3d(n%, 0) / (z3d(n%, 0) + zCenter)) + xCenter
y2d(n%, 0) = 256
* (y3d(n%, 0) / (z3d(n%, 0) + zCenter)) + yCenter
x2d(n%, 1) = 256
* (x3d(n%, 1) / (z3d(n%, 1) + zCenter)) + xCenter
y2d(n%, 1) = 256
* (y3d(n%, 1) / (z3d(n%, 1) + zCenter)) + yCenter
'Alte Linien loeschen
IF olx2d(n%, 0)
> -100 AND olx2d(n%, 0) < 420 AND olx2d(n%, 1) > -100 AND olx2d(n%,
1) < 320 THEN
LINE (olx2d(n%,
0), oly2d(n%, 0))-(olx2d(n%, 1), oly2d(n%, 1)), 0
END IF
'Neue Linien zeichnen
IF x2d(n%, 0) >
-100 AND x2d(n%, 0) < 420 AND x2d(n%, 1) > -100 AND x2d(n%, 1) <
320 THEN
LINE (x2d(n%, 0),
y2d(n%, 0))-(x2d(n%, 1), y2d(n%, 1)), 15
END IF
NEXT n%
LOOP UNTIL INKEY$
<> ""
DATA -20, -20, -20
DATA 20, -20, -20
DATA 20, -20, -20
DATA 20, 20, -20
DATA 20, 20, -20
DATA -20, 20, -20
DATA -20, 20, -20
DATA -20, -20, -20
DATA -20, -20, 20
DATA 20, -20, 20
DATA 20,-20, 20
DATA 20, 20, 20
DATA 20, 20, 20
DATA -20, 20, 20
DATA -20, 20, 20
DATA -20,-20,20
DATA -30, -30, 30
DATA 30, -30, 0
DATA 30, -30, 0
DATA 30, 30, -30
DATA 30,30,-30
DATA -30,30,0
DATA -30,30,0
DATA -30,-30,30
DATA 30,30,30
DATA 30,-30,0
DATA 30,30,30
DATA 30,30,-30
DATA 30,30,30
DATA -30,30,0
DATA 30,30,30
DATA -30,-30,30
DATA -30,-30,-30
DATA 30,-30,0
DATA -30,-30,-30
DATA 30,30,-30
DATA -30,-30,-30
DATA -30,30,0
DATA -30,-30,-30
DATA -30,-30,30
ASM Tutorial Teil 2 Interrupts
Es ist natürlich war, das man mit den Grundlagen, die ich im ersten ASM Tutorial beschrieben habe, noch nicht besonders viel anfangen kann.
Wie funktioniert das nun, mit der Mouse?
Für solche Dinge gibt es so genannte
Interrupts. Die Interrupts sind DOS Funktionen.
Es gibt insgesamt 256 davon und sie werden
mit
INT (Interrupnummer)
aufgerufen.
INT 33h ist zum Beispiel der Mouseinterrupt.
Gesteuert werden die Interrupts meistens
mit dem Register AX.
Bei Interrupt 33h bedeutet 1h in AX, dass
die Mouse aktiviert wird und 2h, dass die Mouse deaktiviert wird.
Ein Beispiel:
MOV AX, 1h
INT 33h
AX wurde gleich 1h gesetzt und dann Interrupt
33h aufgerufen.
Die Folge ist, das Sichtbar werden der
Mouse.
Das wars schon zum Interrupt
Eine sehr wichtige Bedeutung in der Assembler
Programmierung, hat der Stack.
Wie schon erwähnt, kann man in Assembler
nur 4 Variablen verwenden. Wenn man nun aber mehr Variablen benötigt
und den Inhalt der Register für später noch bracht, kann man
diese in den Stack zwischen speichern.
QBasic kann den Stack auch verwenden.
Zum Beispiel bei der Rekursion.
Der Stack ist eine Art Kellerspeicher
oder Stapelspeicher.
Man kann eine Variable nach der anderen
in ihm abspeichern. Man kann es sich wie einen Stapel vorstellen.
Die Werte werden übereinander gestapelt.
Beim herauslesen wiederum, wird immer der oberste Wert gelesen.
Wenn man zum Beispiel erst eine
1, dann eine 2 und danach eine 3 abspeichert, dann erhält man beim
aus lesen erst die 3, dann die 2 du zum Schluß die 1.
Also wie macht man das nun.
Um den Inhalt eines Registers in de Stack
zu kopieren, verwendet man
PUSH
Hinter PUSH steht das Register. z.B:
PUSH AX
Um den obersten Wert im Stack in ein Register
zu schieben, gibt es:
POP
Hinter POP steht das REGISTER in welches
der Wert abgelegt werden soll. Z.B:
POP AX
Hier mal ein kleines Programmbeispiel:
MOV AX, 1h
MOV BX, Fh
PUSH BX
PUSH AX
POP BX
POP AX
Wen ich mich nicht irre, ist nun in AX
das Fh und in BX die 1h .
Die Werte wurden ohne eine dritte Variable
vertauscht.
Es gibt natürlich noch mehr, was man
mit dem Stack machen kann.
Man kann gezieht einen tieferen Wert aus
dem Stack lesen.
Zum Beispiel
MOV AX, [BP + 2]
Was ist den nun BP und was bedeuten die
eckigen Klammern?
Nun die Eckigen Klammern sagen, dass ein
Speicherbereich an gewählt wird.
BP ist ein Base Pointer.
Das ist ja ganz schön und gut, hat
nur zwei Hacken.
1. Muß BP erst mal wissen, wo der
Stack eigentlich ist.
2. Darf man BP gar nicht benutzten da
es vom Computer schon benutzt wird.
Aber dafür gibt es wie immer eine
Lösung.
Es gibt noch einen weiteren Pointer, der
immer genau weiß, wo der Stack gerade ist.
Es ist SP Stack Pointer.
Der Inhalt von SP muß also nur in
BP kopiert werden.
MOV BP, SP
SP selbst darf unter keinen Umständen
verändert werden, weil sonst der Computer stehen bleibt.
Das zweite Problem war BP selbst.
Es ist so, dass der Assembler sich die
Variablen nur ausleiht und sie dann wieder unverändert zurückgeben
muß.
Also wie speichert man eine Variable
ab wenn man den Inhalt noch für später bracht.
Genau!
Mit PUSH und POP.
Das heißt, am Anfang sollte zuerst
BP abgespeichert werden
PUSH BP
Dann wird die Stackposition ermittelt.
MOV BP, SP
Zum ende muß dann nur noch PB zurückgegeben
werden
POP BP
Der Computer hat nun sein BP zurück ohne das er etwas gemerkt hat.
Wichtig ist vielleicht noch, dass sich
die Position des Stacks bei jeden PUSH um 2 verschiebet.
Das heißt , dass nach PUSH das BP
aktualisiert werden sollte.
Das wars zum Stack
Turbo Pascal Tutorial 1 Grundaufbau
Für die meisten Qbasicprogrammierer ist Turbo Pascal ein Buch mit sieben Siegeln. Das liegt wo hauptsächlich an dem anderen Syntax und dem Programmaufbau.
Einer der Hauptunterschiede zwischen TP
und QB ist das Ende jeder Zeile.
QBasic erkennt selbst wann eine
Zeile zu ende ist.
TP kann das nicht. Jede Zeile muß
mit einem ; beendet werden.
Ein weiterer Unterschied ist die Struckturierung
des Programms.
Der Grundaufbau sieht so aus:
PROGRAM ProgrammName;
USES crt, dos;
VAR
BEGIN
.
.
.
END.
Die erste Zeile ist immer
PROGRAM.
Daran weiß TP, dass es sich bei
der Software ein normales Programm handelt.
Das ist wichtig, denn es gibt auch noch
andere Struckturen.
Hinter PROGRAM
kommt der Name der Software.
Als nächstes kommt
USES
Hier werden alle benötigten Uses
aufgerufen. Bei QBasic sind das Libraries.
Welche Uses benötigt werden kann
man aus der Hilfe zu den einzelnen Befehlen erfahren.
Die am häufigsten vorkommenden sind
CRT
und DOS. Es gibt zwar noch viel mehr, aber
dazu später.
Nun kommt der Befehl
VAR
Hier müssen alle Globalen Variablen,
die man in seinem Programm verwenden will, aufgelistet sein.
Das sieht dann wie folgt aus
Variablenname : Variablentyp;
Der Variablentyp ist teilweise schon aus
QBasic bekannt.
Da gibt es zum Beispiel: STRING,
INTEGER, LONGINT, uvm.
Aus der Hilfe von TP kann man auch erfahren,
welche Variblentypen es noch gibt.
Dr Bereich zwischen
BEGIN
und
END.
Ist das Hauptprogramm. Hier können
nun alle Befehle stehen.
Alles klar?
Turbo Pascal Tutorial 2 Ein- und Ausgabe von Text
Wie in QBasic, gibt es auch in Turbo-Pascal,
Befehle wie PRINT und INPUT.
Der Printbefehl ist in Turbo-Pascal
Write(text);
und
Writeln(text);
Write schreibt den Text ganz normal. Dabei
bleibt der Cursor hinter dem Text stehen.
Bei Writeln hingegen springt der Cursor
in die nächste Zeile.
Ein Text muß immer in den Hochkommas
stehen. Wenn eine Variable auf den Bildschirm gebracht werden soll, dürfen
keine Hochkommas benutzt werden.
Der Inputbefehl in TP ist
Read(variable);
und
Readln(variable);
Read wartet auf die Eingabe und speichert sie in der Variable ab. Bei Readln sprint der Cursor wieder in die nächste Zeile.
Um den Bildschirm zu löschen benutzt
man
CLRSCR;
Um den Cursor an eine bestimmte Stelle
zu bringen kann man
GOTOXY(spalte, zeile);
Verwenden.
Die letzen beiden Befehle benötigen
die Uses CRT
Wichtig: {Kommentare können bei TP in geschweifte Klammern gestellt werden.}
Hier nun ein kleinen Beispiel:
PROGRAM eingabe;
USES
crt;
VAR
textvar : STRING;
BEGIN
clrscr;
writeln('Bitte geben Sie etwas ein und druecken ENTER');
readln(textvar);
gotoxy(10,10);
write('Sie haben ',textvar,' eingegen');
readln;
END.
Das sollte es zur Ein und Ausgabe von Text fürs erste gewesen sein.
Turbo Pascal Tutorial 3 Auswahlstrukturen
Auswahlstrukturen sollten eigentlich schon aus QBasic bekannt sein. Es sind zum Beispiel IF THEN oder SELECT CASE.
In Turbo-Pascal ist es etwa genauso einfach.
IF (Bedingung) THEN
BEGIN
.
.
END;
Die Bedingung ist genauso wie bei QBasic.
Es können auch mehrere Bedingungen eingebaut werden.
Die müssen jeweils durch eine Klammer
begrenzt werde und durch AND oder OR verbunden werden.
Alle Anweisungen die ausgeführt werden
sollen, wenn die Bedingung war ist müssen BEGIN und END; eingeklammert
sein.
Beispiel:
PROGRAM Auwahl1;
USES
crt;
VAR
Zahl : Longint;
BEGIN
Clrscr;
Write(Bitte Zahl
eingeben:);
Readln(zahl);
IF (Zahl = 0) THEN Write(Es wurde Null eingeben.);
IF (Zahl < 0)
THEN
BEGIN
Writeln(Es wurde eine Zahl eingegeben die kleiner ist als Null);
END;
IF (Zahl > 0) AND
(Zahl <> 10) THEN
BEGIN
Writeln(Es wurde eine Zahl eingegeben die großer ist als Null);
Writeln(Die Zahl ist aber auch nicht 10 );
END;
Readln;
END;
Eine CASE Auswahlstruktur gibt es in Turbo-Pascal auch.
Die erste Zeile ist
CASE Ausdruck OF
Ausdruck ist eine Variable.
Dann kommt die Liste mit en Konstanten,
die jeweils in Hochkommas stehen.
Konstante :
BEGIN
.
.
.
END;
Hinter dem Doppelpunkt kommen dann die
Befehle die bei der Auswahl ausgeführt werden.
Sind es mehr als eine Anweisung, müssen
sie wieder von BEGIN und END;
eingeklammert werden.
Zum Schluss kommt nur noch das END;
womit die CASE Auswahl zu ende ist.
Beispiel:
PROGRAM XCASE;
USES crt;
VAR zahl: word;
BEGIN
{Bildschirm loeschen}
clrscr;
{Text ausgabe}
write('Geben Sie
bitte eine Zahl von 1 bis 10 ein:');
{Eingabe}
readln(zahl);
{Fallauswahl}
case zahl of
1:
begin
Write('Sie haben die Eins gedrueckt.')
end;
2:
begin
write('Sie haben die Zwei gedrueckt.');
end;
3..5:
begin
writeln('Sie haben eine Zahl');
writeln('zwischen 3 und 5 gedrueckt');
end;
6..9:
begin
writeln('Die Zahl ist groá');
end;
10:
begin
writeln('Die 10');
end;
else
begin
Writeln('Keine ', zahl, ' sollte gedrueckt werden');
end;
end;
{Ausgabe}
writeln('Enter Druecken');
{Warte auf ENTER}
readln;
END.
So schwer ist es eigetlich nicht.
Thema: Rekursion
Den meisten dürfte Rekursion nicht
bekannt sein. Vielleicht aber doch. Es gibt in der Mathematik etwas ähnliches.
Es sind die rekursiven Zahlenfolgen Bei diesen Zahlenfolgen kann
man ein Glied nur ermitteln wen man dessen Vorgänger kennt.
Und genauso ist es bei der Rekursiven
Programmierung.
Das Problem wird solange auf sich
selbst zurückgeführt , bis sich das Problem von selbst löst.
Wenn man das so hört, kann man sich
nicht vorstellen, was damit gemeint ist. Es ist aber sehr einfach.
Die Funktion ruft sich einfach immer wieder
selbst auf, bis die Abbruchbedingung erfüllt ist.
Dabei legt es alle Werte im Stack ab und
holt sie wieder heraus wenn Abbruchbedingung erfolgt ist.
Ein einfaches Beispiel.
Ich möchte die Xte Zahl ermitteln,
die doppelt so groß ist wie ihr Vorgänger.
Anders gesagt, die Zahl 2 hoch X mal.
DECLARE FUNCTION fkt! (Nr%)
CLS
INPUT "Welche Zahl";
n%
PRINT fkt(n%)
FUNCTION fkt (Nr%)
IF Nr% > 0 THEN
fkt = fkt(Nr% -
1) * 2
ELSE
fkt = 1
END IF
END FUNCTION
Wie man sehen kann ruft sich die Funktion
immer wieder selbst auf, bis die Abbruchbedingung nämlich
Nr% = 0 erfüllt ist.
In diesem Fall erhält die Fkt ihren
Startwert 1 und fällt dann wieder rückwerts aus dem Stack heraus.
Das Problem bei dieser Technik ist, dass
es viel Stackspace benötigt wird und es relativ langsam ist.
Dafür kann ein Problem sehr leicht
erklärt werden, dass heißt der Quellcode ist nicht sehr kompliziert.
Hier ist ein Beispiel das die Tasten des
Keyboards in Echtzeit lesen kann.
Es weiß immer genau, welche Taste
gerade gedrückt wird. Selbst wenn mehrere Tasten gleichzeitig gedrück
werden. Das besondere ist, dass es ohne Assembler arbeitet.
Es ist aber wichtig, das NumLock ausgeschaltet
ist, da es sonst zu Fehlern kommt.
Viel Spaß!
'#################################################################
'
' xKey
'
' Dieses Programm
demonstriert die Tastatur-Direkt-Eingabe.
' Es erkennt
in Echtzeit, ob eine Bestimmte Taste gedrueckt wird
' oder nicht.
' Und es arbeitet
ganz ohne Assembler
'
' Wichtig!!!!
[NumLock] muss AUS sein, da es sonst zu Problemen mit den
' Cursortasten
kommt.
'
' Autor :
Soeren Dressler
' eMail :
soeren01@t-online.de
' WWW
: http://qmystic.xxn.de
'
'
'#################################################################
DIM SHARED xkey%(128)
DIM SHARED tasten AS STRING * 300
CLS
DO
' Rountine zum ermiteln der Tasten
ii% = i%
i% = INP(&H60)
IF ii% <> i% AND i% < 128 THEN xkey%(i%) = -1
IF ii% <> i% AND i% >= 128 THEN xkey%(i% - 128) = 0
' Das war's schon
' Ausgabe der Tasten
tasten$ = ""
FOR n% = 1 TO 128
IF xkey%(n%) = -1 THEN MID$(tasten$, n% * 3, 3) = STR$(n%)
NEXT
LOCATE 1, 1
PRINT tasten$
' Verlasse Schleife
wenn ESC gedrckt wird.
LOOP UNTIL INKEY$
= CHR$(27)
Bis zum nächsten Mal!