Funktionen Verwendung für Anfänger

Übersicht BlitzBasic FAQ und Tutorials

Neue Antwort erstellen

Midimaster

Betreff: Funktionen Verwendung für Anfänger

BeitragMi, Dez 23, 2009 16:19
Antworten mit Zitat
Benutzer-Profile anzeigen
Dies ist ein Tutorial für blutige Anfänger. Es erklärt was Funktionen sind und wo und wie man sie in eigenen Programmen verwenden könnte.

(Ich bitte alle, sich mit eigenen Einträgen rauszuhalten und dafür lieber den Thread "Kritik an Midimaster-Tutorials" zu nutzen. Dieses Tutorial soll den Anfänger möglichst durch keine Diskussionen irritieren.) Kritik hier hin: Kritik-Thread

Allen Anfängern lege ich wärmstens ans Herz dieses Tutorial durchzuarbeiten. Es spart euch viele Fehler in späteren Programmen. Fragen von Hilfesuchenden bitte ins BB-Beginners-Corner (https://www.blitzforum.de/forum/viewforum.php?f=18), aber auf keinen Fall hier hin posten!

Das Tutorial ist didaktisch konzipiert aufgebaut. Die Lektionen bauen aufeinander auf. Die Befehle werden nie vollständig erklärt, sondern immer nur soweit man es für diese Lektion unbedingt braucht.


Lektion I: Funktionen sparen Code-Zeilen Arrow zur Lektion I

Lektion II: Variablen übergeben Arrow zur Lektion II

Lektion III: Sind Funktionen wie neue Blitz-Befehle? Arrow zur Lektion III

Lektion IV: Funktionen liefern Rückwerte Arrow zur Lektion IV
  • Zuletzt bearbeitet von Midimaster am Do, Jan 07, 2010 10:56, insgesamt 10-mal bearbeitet

Midimaster

Betreff: Lektion 1: Funktionen sparen Code-Zeilen

BeitragMi, Dez 23, 2009 16:48
Antworten mit Zitat
Benutzer-Profile anzeigen
Lektion 1: Funktionen sparen Code-Zeilen

Die meisten Anfänger benutzen keine Funktionen, weil sie glauben, dies wäre irgendwie schwierig. Aber genau das Gegenteil ist der Fall: Funktionen sind supereinfach zu verstehen und machen das Programmieren leichter. Viele Abläufe, die in Spaghetti-Code Kopfzerbrechen verursachen, werden durch Funktionen zu harmlosen "Kurzprogrammen". Also los....

Zunächst ein erklärendes Beispiel, das leider nicht den Code verkürzt, aber die Funktionsweise deutlich macht

Vorher:
BlitzBasic: [AUSKLAPPEN]
Graphics 800,600
Print "Zeile 1"
Print "Zeile 2"
Print "Zeile 3"
End

Nachher:
BlitzBasic: [AUSKLAPPEN]
Graphics 800,600
Print "Zeile 1"
SpringDahin()
Print "Zeile 3"
End

Function SpringDahin()
Print "Zeile 2"
End Function


Das war es schon! Mit Funktionen schneidest Du Codezeilen aus und fügst Sie unten an den Code an. Der Computer springt an der Stelle SpringDahin in die Funktion, arbeitet sie ab, und kehrt dann zum Absprungstelle zurück.

Jetzt aber etwas nützliches:

Wer ein Quizspiel macht hat mit vielen Fragen zu arbeiten, die aber immer wieder auf die gleiche Weise angezeigt, beantwortet und ausgewertet werden müssen:

Vorsicht SpaghettiCode! Nicht nachmachen!
BlitzBasic: [AUSKLAPPEN]
Graphics 800,600
;
Cls
Color 255,255,0
Text 100,100,"Wer ist Tarzan?"
Color 0,0,255
Text 100,140,"<1>........" + "ich"
Text 100,160,"<2>........" + "mein Held"
Text 100,180,"<3>........" + "der Freund von Jane"
Flip
Versuch$=Input$(" Wie lautet deine Antwort ? ")
If Versuch$="3" Then
Color 0,255,0
Text 100,220, "Sehr gut"
Else
Color 255,0,0
Text 100,220, "Leider falsch"
EndIf
Flip
WaitKey()
;
;
Cls
Color 255,255,0
Text 100,100,"Wer ist Jane?"
Color 0,0,255
Text 100,140,"<1>........" + "Jane?"
Text 100,160,"<2>........" + "mein Hund"
Text 100,180,"<3>........" + "was soll die blöde Fragerei"
Flip
Versuch$=Input$(" Wie lautet deine Antwort ? ")
If Versuch$="2" Then
Color 0,255,0
Text 100,220, "Sehr gut"
Else
Color 255,0,0
Text 100,220, "Leider falsch"
EndIf
Flip
WaitKey()
;
;
Cls
Color 255,255,0
Text 100,100,"blablabla?"
Color 0,0,255
Text 100,140,"<1>........" + "bla"
Text 100,160,"<2>........" + "blabla"
Text 100,180,"<3>........" + "blablabla"
Flip
Versuch$=Input$(" Wie lautet deine Antwort ? ")
If Versuch$="1" Then
Color 0,255,0
Text 100,220, "Sehr gut"
Else
Color 255,0,0
Text 100,220, "Leider falsch"
EndIf
Flip
WaitKey()
;
End


Das Ganze funktioniert schon so einigermaßen, aber bei 100 Fragen wird das Programm ziemlich lang. Man könnte nun Teile des Programms in eine Funktion ausgliedern:
BlitzBasic: [AUSKLAPPEN]
Graphics 800,600
Global Frage$, Antwort1$, Antwort2$, Antwort3$, Versuch$, Richtig$
;
Frage="Wer ist Tarzan?"
Antwort1="ich"
Antwort2="mein Held"
Antwort3=" der Freund von Jane"
Richtig="3"
FrageAnzeigenUndAuswerten()
;
;
Frage="Wer ist Jane?"
Antwort1= "Jane?"
Antwort2="mein Hund"
Antwort3= "was soll die blöde Fragerei"
Richtig="2"
FrageAnzeigenUndAuswerten()
;
;
Frage="blablabla?"
Antwort1="blablabla?"
Antwort2="blablabla?"
Antwort3="blablabla?"
Richtig="1"
FrageAnzeigenUndAuswerten()
;
End
BlitzBasic: [AUSKLAPPEN]
Function FrageAnzeigenUndAuswerten()
Cls
Color 255,255,0
Text 100,100,Frage
Color 0,0,255
Text 100,140,"<1>........" + Anwort1
Text 100,160,"<2>........" + Anwort2
Text 100,180,"<3>........" + Anwort3
Flip
Versuch=Input$(" Wie lautet deine Antwort ? ")
If Versuch=Richtig Then
Color 0,255,0
Text 100,220, "Sehr gut"
Else
Color 255,0,0
Text 100,220, "Leider falsch"
EndIf
Flip
WaitKey()
End Function


Während in dem ersten Beispiel pro Frage noch 18 Zeilen nötig waren, sind es im zweiten Beispiel nur noch 6 Zeilen.

Wie wurde das erreicht?

Die Frage und die Antworten wurden in String-Variable eingetragen:

Code: [AUSKLAPPEN]
Frage="Wer ist Tarzan?"


Und in der Textanzeige wird dann diese Variable verwendet:

Code: [AUSKLAPPEN]
Text 100,100,Frage


Dies führt dazu, dass jetzt große Teile des Programms gleiche Codezeilen enthalten würden. Diese Code-Zeilen werden aus dem Hauptprogramm entfernt und als Funktion ausgelagert.

Was bringt mir das?

Zunächst wird der Code kürzer...Aber wirklich toll ist die Tatsache, dass ich nun in der Funktion an z.B. der Optik der Fragen herumbasteln kann, z.B. andere Farben oder anderer Bildaufbau. Und das Ergebnis ändert sich bei allen 100 Fragen.
  • Zuletzt bearbeitet von Midimaster am Mi, Dez 30, 2009 1:41, insgesamt 6-mal bearbeitet

Midimaster

Betreff: Lektion 2:Variablen übergeben

BeitragMi, Dez 23, 2009 18:08
Antworten mit Zitat
Benutzer-Profile anzeigen
Lektion 2: Variablen übergeben

Eine sehr bequeme Möglichkeit Daten in die Funktion durchzureichen ist das Übergeben in der Headerzeile der Funktion, das spart wieder Codezeilen und macht unsere Funktion irgendwann universell nutzbar. Das heißt jeder kann die Funktion in seinem Programm nutzen, ohne Probleme mit seinem eigenen Code zu bekommen.

Warum gibt es bei Funktionen überhaupt Probleme?

Wenn wir uns die Funktion aus dem letzten Beispiel noch einmal ansehen, bemerken wir, dass innerhalb der Funktion feste Variablennamen (z.B. FRAGE$) des Hauptprogramms vorkommen.
BlitzBasic: [AUSKLAPPEN]
Function FrageAnzeigenUndAuswerten()
Cls
Color 255,255,0
Text 100,100,Frage
...

Ein Dritter der diese Funktion nutzen wollte, müsste für seine Quizfrage auch genau die Variable FRAGE$ benutzen. Würde er die Variable QUIZ$ benutzen, bliebe die Funktion wirkungslos.

Noch schlimmer: Würde er den Namen FRAGE schon für eine Variable "Nummer der aktuellen Frage" benutzen...
Code: [AUSKLAPPEN]
Frage%=21

...dann gäbe es richtig Ärger, den sein Hauptprogramm erwartet für FRAGE eine INTEGER-Zahl, deine Funktion für Frage aber einen STRING-Zeichenkette.

Es wäre also toll, wenn Namen innerhalb einer Funktion nicht mit Namen außerhalb einer Funktion in Konflikt geraten würden. Das ist Grunde ganze leicht, weil es extra dafür einen Befehl LOCAL gibt. Dieser Befehl definiert eine Variable als lokal gültig, das heißt sie gilt nur innerhalb der Funktion:

BlitzBasic: [AUSKLAPPEN]
Function FrageAnzeigenUndAuswerten()
Local Frage$
Cls
Color 255,255,0
Text 100,100,Frage
...

Jetzt allerdings ist FRAGE total lokal und kennt natürlich den Inhalt der Variable FRAGE aus dem Hauptprogramm nicht mehr.

Übergabe von Werten als Parameter
Wir suchen also eine Möglichkeit den Satz "Wer war Tarzan?" an die Funktion FrageAnzeigenUndAuswerten() durchzureichen.

Zunächst die Theorie:

BlitzBasic: [AUSKLAPPEN]
Print "Zeile 1"
SpringDahin "Zeile 2"
Print "Zeile 3"
End

Function SpringDahin(DiesDrucken$)
Print DiesDrucken
End Function

In diesem Beispiel wird beim Aufruf der Funktion SpringDahin der Parameter "Zeile 2" übergeben. Die Funktion nimmt ihn in der LOKALEN Variablen DiesDrucken$ auf und nun lässt er sich innerhalb der Funktion bearbeiten. Eine Variable gleichen Namens im Hauptprogramm bliebe unberührt, da "Variablen zur Parameterübergabe" automatisch LOKAL sind.

Es können auch mehrere Parameter gleichzeitig übergeben werden, wobei darauf zu achten ist, dass die Reihenfolge und der Typ der Parameter beim Aufruf und in der Funktions-Headerzeile gleich sind:

BlitzBasic: [AUSKLAPPEN]
Print "Zeile 1"
SpringDahin "Zeile 2", 3
Print "Zeile 3"
End

Function SpringDahin(DiesDrucken$, WieOft%)
Local i%
For i=1 To WieOft
Print DiesDrucken
Next
End Function


Nun sehen wir uns an, wie sich dies auf unser Quiz-Spiel auswirkt:

BlitzBasic: [AUSKLAPPEN]
Graphics 800,600
Global Frage$, Antwort1$, Antwort2$, Antwort3$, Versuch$, Richtig$
;
Frage="Wer ist Tarzan?"
Antwort1="ich"
Antwort2="mein Held"
Antwort3=" der Freund von Jane"
FrageAnzeigenUndAuswerten Frage, Antwort1, Antwort2, Antwort3, "3"
;
;
Frage="Wer ist Jane?"
Antwort1= "Jane?"
Antwort2="mein Hund"
Antwort3= "was soll die blöde Fragerei"
FrageAnzeigenUndAuswerten Frage, Antwort1, Antwort2, Antwort3, "2"
;
;
Frage="blablabla?"
Antwort1="blablabla?"
Antwort2="blablabla?"
Antwort3="blablabla?"
FrageAnzeigenUndAuswerten Frage, Antwort1, Antwort2, Antwort3, "1"
;
End
BlitzBasic: [AUSKLAPPEN]
Function FrageAnzeigenUndAuswerten(Quiz$, LoesungA$, LoesungB$, LoesungC$, Richtig$)
Cls
Color 255,255,0
Text 100,100,Quiz
Color 0,0,255
Text 100,140,"<1>........" + LoesungA
Text 100,160,"<2>........" + LoesungB
Text 100,180,"<3>........" + LoesungC
Flip
Versuch=Input$(" Wie lautet deine Antwort ? ")
If Versuch=Richtig Then
Color 0,255,0
Text 100,220, "Sehr gut"
Else
Color 255,0,0
Text 100,220, "Leider falsch"
EndIf
Flip
WaitKey()
End Function

Ich habe absichtlich die Variablen-Namen in der Funktion geändert. Aus Name$ wurde Quiz$, damit klar wird, dass dies jetzt wirklich möglich ist. Der Inhalt von Frage$ wandert in Quiz$.
Wir verkürzten den Code dabei nur um eine Code-Zeile pro Frage, es bleiben 5 Zeilen pro Frage. Aber geht es noch kürzer?

Der Aufruf der Funktion lässt sich auch so gestalten:
Zitat:
FrageAnzeigenUndAuswerten "Wer ist Tarzan?", "ich", "mein Held", " der Freund von Jane", "3"
;
FrageAnzeigenUndAuswerten "Wer ist Jane?", "Jane?","mein Hund", "was soll...", "2"
;
FrageAnzeigenUndAuswerten "blabla?", "bla", "bla", "bla", "3"

Nur noch eine Zeile pro Frage!!! der Wahnsinn!!!
  • Zuletzt bearbeitet von Midimaster am Mi, Dez 30, 2009 1:46, insgesamt 3-mal bearbeitet

Midimaster

Betreff: Sind Funktionen wie neue Blitz-Befehle?

BeitragDo, Dez 24, 2009 13:35
Antworten mit Zitat
Benutzer-Profile anzeigen
Sind Funktionen wie neue Blitz-Befehle?

Ja, eindeutig ja! Was du als BlitzBasic-Befehl wahrnimmst, ist nichts anderes als die eben gelernten Funktionen mit Übergabe von Parametern. Dazu ein Beispiel:
BlitzBasic: [AUSKLAPPEN]
Graphics 800,600
Rect 100,100,200,300,0
Flip
WaitKey()
End
zeichnet ein ungefülltes Rechteck auf den Bildschirm. Das ist ein BB-Befehl. Aber kennst Du das?

Code: [AUSKLAPPEN]
Triangle 100,100,100,300,200,100

Dies zeichnet ein ungefülltes Dreieck auf den Bildschirm. Wie? Du erfindest eine Funktion dazu:
BlitzBasic: [AUSKLAPPEN]
Graphics 800,600
Triangle 100,100,100,300,200,100
Flip
WaitKey()
End
Function Triangle( X1%,Y1%, X2%,Y2%, X3%,Y3% )
Line X1,Y1, X2,y2
Line X1,Y1, X3,Y3
Line X2,Y2, X3,Y3
End Function


Eigene Spezialfarben schnell verfügbar haben:
BlitzBasic: [AUSKLAPPEN]
Graphics 800,600
SetMyColor "Orange"
Rect 100,100,100,100
SetMyColor "Azurblau"
Rect 150,150,100,100
Flip
WaitKey()
BlitzBasic: [AUSKLAPPEN]
Function SetMyColor( FarbName$ )
If FarbName="Orange" Then
Color 255,128,64
ElseIf FarbName="Azurblau" Then
Color 64,255,255
EndIf
End Function
End

Oder wie wäre es mit dieser Funktion:
Code: [AUSKLAPPEN]
RectTrans 100,100,200,300,0.5
Sie zeichnet ein halbtransparentes Rechteck in Dein Spiel. Geht nicht? Geht doch...

Funktionen können Funktionen aufrufen

Es muss nicht bei einem Aufruf einer Funktion aus dem Hauptprogramm bleiben. Funktionen können auch wieder Funktionen aufrufen. Dazu zunächst ein nutzloses Beispiel:
BlitzBasic: [AUSKLAPPEN]
Graphics 800,600
Global SpielerName$
SpielerName="Tarzan"

MaleHauptScreen SpielerName
Flip
WaitKey()
End
BlitzBasic: [AUSKLAPPEN]
Function MaleHauptScreen(Wer$)
Cls
SetMyColor "Orange"
Rect 100,100,300,200
SetMyColor "AzurBlau"
Text 200,200,Wer
End Function
BlitzBasic: [AUSKLAPPEN]
Function SetMyColor( FarbName$ )
If FarbName="Orange" Then
Color 255,128,64
ElseIf FarbName="Azurblau" Then
Color 64,255,255
EndIf
End Function

Die Funktion MaleHauptScreen nutzt die Möglichkeiten der Funktion SetMyColor. Je genialer Deine Funktion ist, desto mehr kannst Du sie in anderen Funktionen einsetzen. Deshalb jetzt einmal zurück zu unserem Beispiel der Transparenz in BlitzBasic:

Bilder halbtransparent in BlitzBasic zu machen scheint nicht möglich zu sein. Wir probieren lieber ein einzelnen Pixel mit PlotTrans() halbtransparent zu machen. Gelingt uns dies, können wir uns an eine Funktion wagen die ganze Linien halbtransparent macht LineTrans(). Diese Funktion ruft einfach immer wieder PlotTrans() auf, bis die Linie gezeichnet ist. Dann wird auch RectTrans() möglich und bald DrawImageTrans()

BlitzBasic: [AUSKLAPPEN]
Function PlotTrans(X%,Y%,Alpha#)
Local cRed%,cGreen%,cBlue%
Local pRed%,pGreen%,pBlue%
Local origRed%,origGreen%,origBlue%
origRed=ColorRed()
origGreen=ColorGreen()
origBlue=ColorBlue()

cRed=ColorRed()*Alpha
cGreen=ColorGreen()*Alpha
cBlue=ColorBlue()*Alpha

GetColor X,Y
pRed=ColorRed() * (0.99-Alpha)
pGreen=ColorGreen() * (0.99-Alpha)
pBlue=ColorBlue() * (0.99-Alpha)

pRed= cRed+pRed
pGreen= cGreen+pGreen
pBlue= cBlue+pBlue

Color pRed,pGreen,pBlue
Plot X,Y
Color origRed,origGreen,origBlue

End Function

Die Funktion besteht aus fünf Teilen:
Im ersten Teil wird die aktuell gültige COLOR in die Variablen origRED origGREEN und origBLUE gerettet. Im Hauptprogramm wurde sie wahrscheinlich mit Color x,y,z kurz vor Aufruf der Funktion festgelegt. Vor Beendigung der Funktion wollen wir wieder auf diese Farbe zurückstellen.

Wir gehen davon aus, dass die aktuell eingestellte Farbe die "gewünschte" Malfarbe ist. Durch die Multiplikation mit dem Transparentwert ALPHA# (liegt zwischen 0 und 1) erreichen wir, dass sie etwas "unwichtiger" wird . Diese Ergebnisse speichern wir in cRed, cGreen, cBlue.

Im dritten Teil wird die Farbe des Pixel am Bildschirms untersucht, das genau auf der Stelle liegt, wo wir gleich malen wollen. Wir nennen sie mal "vorhandene" Farbe. Durch die Multiplikation mit dem Transparentwert 0.99-ALPHA# erreichen wir, dass sie ebenfalls "unwichtiger" wird . War Alpha z.B. 0.7, dann wird die vorhandene Farbe nun mit dem Faktor 0.3 verringert.

Dann wird für alle drei Farbtöne aus gewünschter und vorhandener Farbe der Mittelwert gebildet. Die gewünschte Farbe auf Wichtigkeit 70% reduziert, die vorhandene Farbe auf 30%. Zusammengezählt ergibt sich genau wieder 100%. Es entsteht eine Mischung aus 30% vorhandener Farbe + 70 % gewünschter Farbe.

Im letzten Teil setzen wir diese neu gewonnenen Werte als COLOR und malen das Pixel. Zu guter letzt stellen wir das System wieder auf die Originalfarbe.


Die Funktion ist alles andere als perfekt und sie ist nicht gerade schnell. Aber sie funktioniert. Hast Du später einmal Verbesserungsvorschläge und weißt, wie Du sie schneller machen kannst, dann brauchst Du nur die Zeilen in dieser Funktion zu ändern. Sofort werden alle Deine Programme, in denen diese Funktion und LineTrans(), RectTrans() und DrawImageTrans() vorkommen, schneller.
  • Zuletzt bearbeitet von Midimaster am Mi, Okt 12, 2011 17:32, insgesamt 2-mal bearbeitet

Midimaster

Betreff: Lektion IV Funktionen liefern Rückwerte

BeitragMo, Dez 28, 2009 16:02
Antworten mit Zitat
Benutzer-Profile anzeigen
Funktionen liefern Rückwerte

Du kannst nicht nur Werte in Funktionen hinein übergeben, Du kannst auch Ergebnisse an das Hauptprogramm zurückfunken.

BlitzBasic: [AUSKLAPPEN]
Global a#, b#
a=12
b=Quadrat(a)
Print b
Function Quadrat#(Wert#)
Local Ergebnis#
Ergebnis=Wert*Wert
Return Ergebnis
End Function

Zugegeben ein nicht sehr geistreiches Bespiel. Aber es zeigt wie du mit dem Befehl RETURN das Ergebnis in das Hauptprogramm zurücksendest, wo es in B aufgenommen wird.

Beachte, dass die Funktion selbst einem VariablenTyp FLOAT zugeordnet wurde. Schließlich könnte jemand die Funktion mit Kommawerten benötigen:
Function Quadrat#()

Hier noch ein zweites Beispiel hierzu: "Der Pythagoras". Sinnigerweise nutz er gleich Deine Function Quadrat():

BlitzBasic: [AUSKLAPPEN]
Print Pythagoras(3.6 , 4)

Funktion Pythagoras#(A#,B#)
Local Ergebnis#
Ergebnis = Quadrat(a)+Quadrat(b)
Ergebnis = Sqr(Ergebnis)
Return Ergebnis
End Function


Die Funktion SQR() ist eine BlitzBasic-Funktion. Aber dahinter steht ebenso nur Code wie in unserer Quadrat() oder Pythagoras(). Es ist im Grunde das gleiche.

Natürlich kannst Du auch Strings zurückgeben lassen

BlitzBasic: [AUSKLAPPEN]
Sieger$=Bester()

Function Bester$()
Local I%, Max%, Wer%
For i=1 To LastSpieler
If Max < SpielerPunkte(i) Then
Max=SpielerPunkte(i)
Wer=i
EndIf
Next
Return SpielerName(i)
End Function


Leider bist Du in BB nicht in der Lage, mehr als 1 Wert zurückgeben zu lassen. Man könnte das Ganze höchstens über GLOBALE tempVariable lösen:

BlitzBasic: [AUSKLAPPEN]
Global Verlierer$, Sieger$, Temp1$, Temp2$

If SucheMinUndMax()=True Then
Sieger=Temp1
Verlierer=Temp2
EndIf
BlitzBasic: [AUSKLAPPEN]
Function SucheMinUndMax()
Local I%, Max%, Min%, WerGut%, WerSchlecht%
Min=999999
For i=1 To LastSpieler
If Max < SpielerPunkte(i) Then
Max=SpielerPunkte(i)
WerGut=i
EndIf

If Min > SpielerPunkte(i) Then
Min = SpielerPunkte(i)
WerSchlecht=i
EndIf
Next

If Min=999999 Then
; kein Verlierer
Return False
EndIf

If Max=0 Then
; kein Sieger
Return False
EndIf

If Min=Max Then
; unentschieden
Return False
EndIf
Temp1=SpielerName(Max)
Temp2=SpielerName(Min)
Return True
End Function


Interessant ist, dass Du in der Funktion mehrmals RETURN verwenden kannst. Da die Funktion bei RETURN sofort abbricht, werden alle nachstehenden Zeilen nicht mehr abgearbeitet. Die Funktion SucheMinUndMax() nutzt das, um mitzuteilen, wenn es keinen Sieger gab. Nur wenn sie soweit kam und die Variablen TEMP1 und TEMP2 mit Inhalt versorgen konnte, meldet sie TRUE zurück.

Neue Antwort erstellen


Übersicht BlitzBasic FAQ und Tutorials

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group