So. längere Zeit war mal wieder nichts zu hören, nun so ist das nunmal wenn erst einmal die Feiertage da liegen und dann auch noch der Beruf einem die Zeit wegfrisst.

Heute möchte ich einmal allgemein vorab auf die Berechnung des Gewinners eingehen, die nach jedem Spielzu erfolgen muss.

Aus meinem letzten Post über die Logik für den Einwurf eines Steines ging ja bereits der Einsprungpunkt für die Berechnung des Gewinners, bzw. der Funktionsname hervor. Hier noch einmal der Code Abschnitt:

Rem “*** Berechnung auf vorhandenem Gewinner ******************************************”
  1.     If BerechneGewinner() = False Then
  2.         sText = "Fehler bei der Berechnung des Gewinners!"
  3.         MsgBox sText, vbOKOnly, "Fehler"
  4.         bInitialized = False
  5.         Exit Function
  6.     End If

Für die Berechnung des Gewinners muss eine Iteration über das gesamte Spielfeld stattfinden, und von jedem Feld aus geprüft werden, ob der Spieler dessen Spielstein hier liegt auch in den folgenden 4 Richtungen des Spielfeldes mindestens 1mal eine 4er Reihe besitzt:

  • rechts
  • unten
  • diagonal rechts unten
  • diagonal links unten

rechenwegeDer Findige sagt zwar jetzt, dass man doch auch nach oben und links etc prüfen muss, diese Richtungen ergeben sich jedoch von selbst aus der Iteration über das Spielfelds. Die kleine Grafik soll das Muster der Prüfung ein wenig schemattisch veranschaulichen.

die gesamte Iteration lässt sich nun noch ein wenig vereinfachen:

  1. Die einzelnen Prüfungen müssen nur angestossen werden, wenn das aktuelle Feld belegt ist.
  2. Zwar ist es prinzipiell für den menschlichen Verstand einfacher von oben links durch das Spielfeld zu laufen, jedoch füllt sich das Spielfeld von unten und so ist es sinnvolssten auch hier anzufangen.
  3. Wenn man unten anfängt ist es nicht sinnvoll die Wege nach unten zu prüfen, sondern statt dessen nanch oben, oben links, oben rechts.

Auf diese Weise läuft die Berechnung des Siegers vom ersten Spielzug an schnell und wird nur durch die Menge der Spielsteine mit der Zeit langsamer. Es lässt sich dagegen noch eine weitere Optimierung einbauen: wenn beim Durchlauf einer Zeile (davon ausgehend das man nach dem Muster “über alle Zeilen – über alle Spalten” prüft eine komplette Zeile als nicht belegt erkannt wird, braucht man die darüber liegenden Zeilen gar nicht mehr zu prüfen. )

So, damit hätten wir alles nötige um die Implementierung im Prinzip abbilden zu können. Nachfolgend noch einmal der Ablauf in eienr Art Pseudocode, ohne zu viele Optimierungen

von unten lins aus

über alle Zeilen

über alle Spalten

Zelle belegt?

prüfe 3 nach rechts

prüfe 3 nach oben

prüfe 3 nach oben links

prüfe 3 nach oben rechts

Nachdem ich die letzten Tage eine Reihe von Hilfsfunktionen veröffentlicht habe, kommt heute die Funktion, mit diese alle verwendet werden um den Einwurf eines Steins durch den aktiven Spieler zu realisieren und somit den Spielablauf zu steuern.

Die Funktion selbst ist letztendlich im Kern nichts weiter als ein Aufruf der einzelnen Hilfsfunktionen in einer bestimmten Reihenfolge:

  1. Prüfungen
    1. auf Initialisierung
    2. auf gültigen Spaltenindex
  2. Ermittlung des aktiven Spielers
  3. Ermittlung dessen Spielsteins
  4. Setzen des Steins in die erste freie Zelle in der Spalte
  5. Aktualisierung des Spielfeldes
  6. Prüfung auf Gewinner
  7. Wechsel des Spielers
'—————————————————————————————
  1. ' Procedure : Einwurf
  2. ' Author    : mainuser
  3. ' Date      : 13.12.2008
  4. ' Purpose   : Einwurf eiens Steins in eine Spalte des Bretts.
  5. '             Ermittelt den aktiven Spieler und die erste freie Position in der Spalte
  6. '             von unten (bedingt performant aber einfach) und setzt den Zellwert im
  7. '             Spielfeld
  8. ' Parameter : (E) sSpalte Excel Spaltenindex der Einwurfspalte
  9. ' Rückgabe  : true/false
  10. '—————————————————————————————
  11. '
  12. Public Function Einwurf(sSpalte As String) As Boolean
  13.     On Error GoTo Einwurf_Error
  14.     Einwurf = False
  15.     Dim sText As String
  16.     Dim sSpieler As String
  17.     Dim sSpielstein As String
  18.     Dim iIndex As Integer
  19.     Dim X As Integer
  20.     Dim bFound As Boolean
  21.  
  22. Rem "*** Initialisierung **************************************************************"
  23.     bFound = False
  24.  
  25. Rem "*** Prevalidierung ***************************************************************"
  26.  
  27.     Rem "=== Spielfeld Initialisiert =================================================="
  28.     If bInitialized <> True Then
  29.         sText = "Bitte erst auf 'Start' klicken um das Spiel zu initialisieren"
  30.         MsgBox sText, vbOKOnly, "Fehler"
  31.         Exit Function
  32.     End If
  33.  
  34.     Rem "=== Spaltenwert = leer? ======================================================"
  35.     If sSpalte = "" Then
  36.         sText = "Ungültiger Spaltenindex!"
  37.         MsgBox sText, vbOKOnly, "Fehler"
  38.         Exit Function
  39.     End If
  40.  
  41.     Rem "=== Spaltenwert nicht im Spielfeld? =========================================="
  42.     If EinwurfSpaltenIndex(sSpalte, iIndex) = False Then
  43.         sText = "Ungültiger Spaltenindex: (" + sSpalte + ") !"
  44.         MsgBox sText, vbOKOnly, "Fehler"
  45.         Exit Function
  46.     End If
  47.  
  48. Rem "*** Ermittlung des aktiven Spielers **********************************************"
  49.     If AktiverSpieler(sSpieler) = False Then
  50.         sText = "Es konnte kein aktiver Spieler ermittelt werden"
  51.         MsgBox sText, vbOKOnly, "Fehler"
  52.         Exit Function
  53.     End If
  54.  
  55. Rem "*** Ermittlung des Spielsteins ***************************************************"
  56.     sSpielstein = SpielerStein(sSpieler)
  57.     If sSpielstein = "" Then
  58.         sText = "Es konnte kein Speilstein für den Spieler >" + sSpieler + "< ermittelt werden"
  59.         MsgBox sText, vbOKOnly, "Fehler"
  60.         Exit Function
  61.     End If
  62.  
  63. Rem "*** Ermitteln der ersten freien Zelle und setzen des Steins **********************"
  64.     X = 7
  65.     Do While X > 0
  66.         If Spielfeld(iIndex, X) = "" Then
  67.             bFound = True
  68.             Exit Do
  69.         End If
  70.         X = X – 1
  71.     Loop
  72.  
  73.     Rem "=== kein freier Platz vorhanden =============================================="
  74.     If bFound = False Then
  75.         sText = "Hier kann nicht mehr gesetzt werden!"
  76.         MsgBox sText, vbOKOnly, "Hinweis"
  77.         Exit Function
  78.     End If
  79.  
  80.     Rem "=== Setzen des Spielsteins im Spielfeld ======================================"
  81.     Spielfeld(iIndex, X) = sSpielstein
  82.  
  83. Rem "*** Aktualisieren des Spielfeldes in Excel ***************************************"
  84.     If AktualisiereSpielfeld() = False Then
  85.         sText = "Fehler bei der Spielfeld Aktualisierung!"
  86.         MsgBox sText, vbOKOnly, "Hinweis"
  87.         bInitialized = False
  88.         Exit Function
  89.     End If
  90.  
  91. Rem "*** Berechnung auf vorhandenem Gewinner ******************************************"
  92.     If BerechneGewinner() = False Then
  93.         sText = "Fehler bei der Berechnung des Gewinners!"
  94.         MsgBox sText, vbOKOnly, "Fehler"
  95.         bInitialized = False
  96.         Exit Function
  97.     End If
  98.  
  99. Rem "*** Wechsel des Spielers *********************************************************"
  100.     If SpielerWechsel() = False Then
  101.         sText = "Fehler beim Spielerwechsel!"
  102.         MsgBox sText, vbOKOnly, "Hinweis"
  103.         bInitialized = False
  104.         Exit Function
  105.     End If
  106.  
  107. Rem "*** Rücksprung *******************************************************************"
  108.     On Error GoTo 0
  109.     Einwurf = True
  110.     Exit Function
  111.  
  112. Einwurf_Error:
  113.     MsgBox "Error " & Err.Number & " (" & Err.Description & ") in procedure Einwurf of Modul ScriptPool_4Gewinnt"
  114. End Function

Die heutige Hilfsfunktion Aktualisiere Spielfeld, stellt die letzte der zentralen Funktionen dar, die für den Einwurf eines Spielsteins und die notwendigen daraus resultierenden Berechnungen (ausser der Gewinnerermittlung) notwendig sind.

Zweck dieser Funktion ist es die interne Abbildung des Spielfelsdes, im Code als 2dimensionales Array definiert, zu visualisieren.

'—————————————————————————————
  1. ' Procedure : AktualisiereSpielfeld
  2. ' Author    : mainuser
  3. ' Date      : 13.12.2008
  4. ' Purpose   :
  5. '—————————————————————————————
  6. '
  7. Private Function AktualisiereSpielfeld() As Boolean
  8.     On Error GoTo AktualisiereSpielfeld_Error
  9.     AktualisiereSpielfeld = False
  10.     Dim X As Integer
  11.     Dim Y As Integer
  12.     Dim Zelle As String
  13.  
  14. Rem "*** Lauf durch das Spielfeld *****************************************************"
  15.     For X = 1 To 7
  16.         For Y = 1 To 7
  17.             Rem "=== Excel Zelle zusammenstellen ======================================"
  18.             Zelle = Spalten(X) + Zeilen(Y)
  19.             Range(Zelle) = Spielfeld(X, Y)
  20.         Next
  21.     Next
  22.  
  23. Rem "*** Rücksprung *******************************************************************"
  24.     On Error GoTo 0
  25.     AktualisiereSpielfeld = True
  26.     Exit Function
  27.  
  28. AktualisiereSpielfeld_Error:
  29.     MsgBox "Error " & Err.Number & " (" & Err.Description & ") in procedure AktualisiereSpielfeld of Modul ScriptPool_4Gewinnt"
  30. End Function

Die Funktion selbst ist noch so trivial implementiert, dass eine feste Größe des Spielfeldes von jeweils 7 Feldern angenommen wird. De facto sollte man aber die Iteration in den beiden Schleufen dynamisch mittels UBound() und LBound() halten.

Die Funktion durchläuft nun jedes Feld des 2dimensionales Arrays Spielfeld und trägt deren Wert in das entsprechende Feld in der Excel Arbeitsmappe ein. Welches Feld das korrespondierende ist, wird über die beiden Arrays Zeilen() und Spalten() bestimmt, für die jeweils der Wert am Schleifenindex X bzw. Y bestimmt wird. Diese Werte werden verkoppelt und dienen dann als Zelldefinition.

Da ich die letzten Tage nichts gepostet hatte, gibts heute gleich noch einmal eine triviale Funktion hinterher.

Die Funkion AktiverSpieler() ermittet dient zur Rückgabe des aktuell eingetragenen aktiven Spielers. Da dieser durch die Funktion SpielerWechsel immer an einer Festen Position steht, liest diese Funktion den Feldwert schlicht aus der Zelle im Excel Sheet aus.

'—————————————————————————————
  1. ' Procedure : AktiverSpieler
  2. ' Author    : mainuser
  3. ' Date      : 13.12.2008
  4. ' Purpose   : Ermittelt den Namen des aktiven Spielers aus dem Spielfeld
  5. ' Parameter : (A) sSpieler  Name des aktiven Spielers
  6. ' Rückgabe  : true/false
  7. '—————————————————————————————
  8. '
  9. Private Function AktiverSpieler(sSpieler As String) As Boolean
  10.     On Error GoTo AktiverSpieler_Error
  11.     AktiverSpieler = False
  12.  
  13.     sSpieler = Range("I4").Value
  14.  
  15. Rem "*** Rücksprung *******************************************************************"
  16.     On Error GoTo 0
  17.     If sSpieler <> "" Then AktiverSpieler = True
  18.     Exit Function
  19.  
  20. AktiverSpieler_Error:
  21.     MsgBox "Error " & Err.Number & " (" & Err.Description & ") in procedure AktiverSpieler of Modul ScriptPool_4Gewinnt"

Der Vorteil dieser Funktionskapselung besteht daran, das man einfach in jeder anderen Funktion mittes des Aufrufs AktiverSpieler direkt den Namen parat hat, ohne jedesmal auf die Zelle gehen zu müssen. Dies bietet besonders dann einenVorteil, wenn man das Spielfeld oder auch nur die Ausgabeposition des Spielernamens in der Excel Tabelle verändert, denn dann muss man nur eine Zeile im Programmcode an einer Stelle anpassen und nicht alle möglichen Vorkommen suchen.

Die heutige Funktion dient dem Zweck, zu einem übergebenen Spaltenwert, analog einer Excel Spaltennummer, den korrespondierenden Wert aus dem Spaltenarray für das Spielfeld zu ermitteln.

Hintergrund dieser Funktion war der Gedanke die Programmierung so weit abstrakt und dynamisch zu halten, damit das Spielfeld sich in Excel an jeder Position befinden kann.

'—————————————————————————————
  1. ' Procedure : EinwurfSpaltenIndex
  2. ' Author    : mainuser
  3. ' Date      : 13.12.2008
  4. ' Purpose   : Liefert zu einem übergebenen Spaltenwert die korespondiernde
  5. '             Spaltennummer im SpielfeldArray
  6. ' Parameter : (E) sSpalte Buchstabe der Spalte aus Excel
  7. '             (A) iIndex  Ermittelter Spielfeld Index
  8. ' Rückgabe  : true/false
  9. '—————————————————————————————
  10. '
  11. Private Function EinwurfSpaltenIndex(sSpalte As String, iIndex As Integer) As Boolean
  12.     On Error GoTo EinwurfSpaltenIndex_Error
  13.     EinwurfSpaltenIndex = False
  14.     Dim X As Integer
  15.  
  16. Rem "*** Prevalidierung ***************************************************************"
  17.     If sSpalte = "" Then Exit Function
  18.  
  19. Rem "*** Ermittlung des Indexwerts zum SpaltenIndex ***********************************"
  20.     For X = LBound(Spalten) To UBound(Spalten)
  21.         If Spalten(X) = sSpalte Then
  22.             iIndex = X
  23.             EinwurfSpaltenIndex = True
  24.             Exit Function
  25.         End If
  26.     Next
  27.  
  28. Rem "*** nichts gefunden **************************************************************"
  29.     iIndex = 0
  30.  
  31. Rem "*** Rücksprung *******************************************************************"
  32.     On Error GoTo 0
  33.     EinwurfSpaltenIndex = True
  34.     Exit Function
  35.  
  36. EinwurfSpaltenIndex_Error:
  37.     MsgBox "Error " & Err.Number & " (" & Err.Description & ") in procedure EinwurfSpaltenIndex of Modul ScriptPool_4Gewinnt"
  38. End Function

Der Abnlauf der Funktion ist dafür denkbar einfach:

Es wird das Array Spalten() durchaufen und jeder Wert mit dem übergebenen Spaltenbuchstaben verglichen. Sobald eine Übereinstimmung vorliegt, wird die Schleife und die Funktion verlassen. Der ermittelte index liegt dann über die Variable iIndex der rufenden Funktion vor.

Anmerkung:

Im Gegensatz zu den letzten Hilfsfunktionen hat diese den “nach meiner Ansicht” korrekten Standardaufbau einer Scriptfunktion:

  • boolscher Rückgabewert zur Kennzeichnung des korrekten oder fehlerhaften Ablaufs
  • Wertübergabe aus der Funktion rein über Call by Reference Variablen

Die heutige Hilfsfunktion Spielerstein() ist ebenfalls eine triviale Funktion, die ich direkt im Ganzen postet.

Zweck der Funktion ist es, zu einem übergebenen Spielernamen den entsprechenden Spielerstein zu ermitteln.

'—————————————————————————————
  1. ' Procedure : SpielerStein
  2. ' Author    : mainuser
  3. ' Date      : 13.12.2008
  4. ' Purpose   : Ermittelt zu einem Spielernamen den Spielstein
  5. ' Parameter : (E) sSpieler  Name des Spielers
  6. ' Rückgabe  : Spielstein Kennung des Spielers
  7. '—————————————————————————————
  8. '
  9. Private Function SpielerStein(sSpieler As String) As String
  10.     On Error GoTo SpielerStein_Error
  11.     SpielerStein = ""
  12.  
  13.     Dim X As Integer
  14.  
  15. Rem "*** Ermittlung der Position ******************************************************"
  16.     For X = LBound(Spieler) To UBound(Spieler)
  17.         If Spieler(X, 0) = sSpieler Then
  18.             SpielerStein = Spieler(X, 1)
  19.             Exit Function
  20.         End If
  21.     Next
  22.  
  23. Rem "*** nichts gefunden **************************************************************"
  24.     SpielerStein = ""
  25.  
  26. Rem "*** Rücksprung *******************************************************************"
  27.    On Error GoTo 0
  28.    Exit Function
  29.  
  30. SpielerStein_Error:
  31.     MsgBox "Error " & Err.Number & " (" & Err.Description & ") in procedure SpielerStein of Modul ScriptPool_4Gewinnt"
  32. End Function

Name und Stein des Spielers sind wie gewohnt im 2dimensianalen Spielerarray enthalten. somit wird in einer einzelnen Schleife über die erste Dimension des Arrays iteriert und der übergebene Name mit dem im Array verglichen.

Sobald ein Treffer vorliegt, wird die Schleife verlassen und der Stein als Ergebnis zurückgeliefert. Wurde bis zum Ende der Iteration nichts gefunden, do wird als Funktionswert ein leerer String zurückgegeben.

Die heutige Hilfsfunktion ist wieder eine sehr triviale Funktion, die ich gleich im Ganzen angebe. Sinn und Zweck der Funktion ist es, zu einem übergebene Spielernamen aus dem Spielerarray den Indexwert zu ermitteln:

'—————————————————————————————
  1. ' Procedure : SpielerIndex
  2. ' Author    : mainuser
  3. ' Date      : 13.12.2008
  4. ' Purpose   : Ermittelt zu einem Spielernamen den Index im SpielerArray
  5. ' Parameter : (E) sSpieler Name des Spielers
  6. ' Rückgabe  : Index des Namen
  7. '—————————————————————————————
  8. '
  9. Private Function SpielerIndex(sSpieler As String) As Integer
  10.     On Error GoTo SpielerIndex_Error
  11.     SpielerIndex = 0
  12.  
  13.     Dim X As Integer
  14.  
  15. Rem "*** Ermittlung der Position ******************************************************"
  16.     For X = LBound(Spieler) To UBound(Spieler)
  17.         If Spieler(X, 0) = sSpieler Then
  18.             SpielerIndex = X
  19.             Exit Function
  20.         End If
  21.     Next
  22.  
  23. Rem "*** nichts gefunden **************************************************************"
  24.     SpielerIndex = 0
  25.  
  26. Rem "*** Rücksprung *******************************************************************"
  27.    On Error GoTo 0
  28.    Exit Function
  29.  
  30. SpielerIndex_Error:
  31.  
  32.     MsgBox "Error " & Err.Number & " (" & Err.Description & ") in procedure SpielerIndex of Modul ScriptPool_4Gewinnt"
  33. End Function

Dazu durchläuf die Funktion das Spielerarray in einer Zählschleife von der Untergrenze (LBound() ) bis zur Obergrenze (UBound()) und prüft für jeden Index, on der übergebene Name mit dem Namen an der aktuellen Stelle übereinstimmt.

Sobald ein Treffer vorliegt, wird der Index als Funktionswert belegt und die Schleife beendet. Wird nichts gefunden, so erreicht die Funktion das Ende der Schleife und als Standardwert wird 0 zurückgegeben. Dies ist natürlich nur bedingt sinnvoll, wenn das Array bei 0 beginnt. Es sollte als bedacht werden, welche Wert letztendlich als Fehlercode verwendet wird (für ein SpielerArray von 1-n ist 0 durchaus gültig).

Bevor ich mit der Erläuterung der Funktion zur Umsetzung des Einwurfs eines Steins in einer Spalte des Spielfeldes beginne, möchte ich zunächst einmal eine Reihe von Hilfsfunktionen, die hierbei verwendet werden erläutern.

Einige davon sind speziell nur für den “Einwurf” gedacht, andere wiederum haben einen eher generellen Charakter und sind auch für die Verwendung in weiteren Bereichen der Answendung gedacht.

Auf die erste Funktion, BerechneStartSpieler(), bin ich ja bereits im vorherigen Post eingegangen. Kommen wir heute zur Funktion SpielerWechsel()

Sinn dieser Funktion ist es, vom aktuellen Spieler ausgehend den anderen Spieler zu ermitteln.

'—————————————————————————————
  1. ' Procedure : SpielerWechsel
  2. ' Author    : mainuser
  3. ' Date      : 13.12.2008
  4. ' Purpose   : Wechsel des aktiven Spielers in der Anzeige auf dem Spielbrett
  5. ' Parameter : keine
  6. ' Rückgabe  : true/false
  7. '—————————————————————————————
  8. '
  9. Private Function SpielerWechsel() As Boolean
  10.     On Error GoTo SpielerWechsel_Error
  11.     SpielerWechsel = False
  12.  
  13.     Dim AktiverSpieler As String
  14.  
  15. Rem "*** Initialisierung **************************************************************"
  16.     AktiverSpieler = Range("I4").Value
  17.  
  18. Rem "*** Ermittlung des aktiven Spielers **********************************************"
  19.     If Spieler(0, 0) = AktiverSpieler Then
  20.         AktiverSpieler = Spieler(1, 0)
  21.     ElseIf Spieler(1, 0) = AktiverSpieler Then
  22.         AktiverSpieler = Spieler(0, 0)
  23.     End If
  24.  
  25. Rem "*** Setzen des aktiven Spielers **************************************************"
  26.     Range("I4").Value = AktiverSpieler
  27.  
  28. Rem "*** Rücksprung *******************************************************************"
  29.    On Error GoTo 0
  30.    SpielerWechsel = True
  31.    Exit Function
  32.  
  33. SpielerWechsel_Error:
  34.     MsgBox "Error " & Err.Number & " (" & Err.Description & ") in procedure SpielerWechsel of Modul ScriptPool_4Gewinnt"
  35. End Function

Die Funktion arbeitet nach dem folgenden einfachen Muster:

  1. Auslesen des Feldwerts für den aktiven Spieler
  2. Ermittlung des 2. Spielerwertes aus dem Spielerarray (dessen Name abweicht)
  3. Eintragung des Namens in das Feld für den aktiven Spieler

Da die Funktion recht trivial in ihrem Inhalt ist, denke ich mal nicht dass eine tiefere Beschreibung notwendig ist.

Heute folgt die Erläuterung der Hilfsfunktion BerechneStartSpieler(), die in der Initialisierung verwendet wird.

Die Funktion ist an sich äußerst trivial, und wird daher hier einmal komplett aufgelistet. Damit zeige ich auch gleich den generellen Aufbau der Funktionen in VBA für diese Anwendung mitsamt Kommentarkopf unf Fehlerbehandlung.

'—————————————————————————————
  1. ' Procedure : BerechneStartSpieler
  2. ' Author    : mainuser
  3. ' Date      : 13.12.2008
  4. ' Purpose   : Berechnet eine Zufallszahl zwischen 0 und 1
  5. '             0 = Spieler A
  6. '             1 = Spieler B
  7. ' Parameter:  (A) iResult  Ergebnis der Berechnung
  8. ' Rückgabe:   true/false
  9. '—————————————————————————————
  10. '
  11. Private Function BerechneStartSpieler(iResult As Integer) As Boolean
  12.     On Error GoTo BerechneStartSpieler_Error
  13.     BerechneStartSpieler = False
  14.  
  15.     Dim Obergrenze  As Integer
  16.     Dim Untergrenze As Integer
  17.  
  18. Rem "*** Initialisierung **************************************************************"
  19.     Obergrenze = 1
  20.     Untergrenze = 0
  21.     Call Math.Randomize
  22.  
  23. Rem "*** Berechnung der Zufallszahl ***************************************************"
  24.     iResult = Int((Obergrenze – Untergrenze + 1) * Rnd + Untergrenze)
  25.  
  26. Rem "*** Rücksprung *******************************************************************"
  27.     On Error GoTo 0
  28.     BerechneStartSpieler = True
  29.     Exit Function
  30.  
  31. BerechneStartSpieler_Error:
  32.     MsgBox "Error " & Err.Number & " (" & Err.Description & ") in procedure BerechneStartSpieler of Modul ScriptPool_4Gewinnt"
  33. End Function

Die gesamte Logik steckt eigentlich in nur 2 Zeilen. Zum einen wird zuerst mittels Math.Randomize der Zufallszahlengenerator initialisiert. Danach erfolgt die Berechnung der Zufallszahl in den vorgegebenen Grenzen gem., der aus der VBA Hilfe für Rnd übernommenen Struktur.

Der Aufbau der Funktion ist hier auch gleich mal Beispiel für die von mir verwendete Programmierkonvention. Die Funktionen selber haben als Rückgabewert einen Boolean Typ mit dem der rufenden Funktion eine korrekte oder fehlerhafte Verarbeitung signalisiert wird.

Der Datentransfer zur rufenden Funktion erfolgt rein über die Parameter (hier iResult als Ausgabeparameter), die generell als “call by reference” übergeben werden. Die eintige Ausnahmevon dieser Notation bilden “Trivialfunktionen” die i.d.R einen String zurückgebenund im Fehlerfall einfach einen Standardwert oder “”als Funktionswert haben. zu diesenHilfsunktionen komme ich im Zuge der Erläuterung der Funktion für den Einwurf eines Spielsteins in eienr Spalte des Spielfeldes.

Bevor man eigentlich mit dem Spiel loslegen kann, muss das Spielfeld erst einmal initialisiert werden. Bei einem ersten Start mag das vielleicht noch nicht ganz so wichtig erscheinen, doch spätestens wenn man eine 2. Spielrunde starten will, muss man ja erst einmal das Spielfeld löschen.

Schritt 1: Variablen

Der erste Schritt der Funktion, die ich StartSpiel() genannt habe führt die Initialisierung des Spalten und Zeilenarrays aus:

Rem “*** Initialisierung **************************************************************”
  1. Spalten(1) = "F"
  2. Spalten(2) = "G"
  3. Spalten(3) = "H"
  4. Spalten(4) = "I"
  5. Spalten(5) = "J"
  6. Spalten(6) = "K"
  7. Spalten(7) = "L"
  8. Zeilen(1) = "7"
  9. Zeilen(2) = "8"
  10. Zeilen(3) = "9"
  11. Zeilen(4) = "10"
  12. Zeilen(5) = "11"
  13. Zeilen(6) = "12"
  14. Zeilen(7) = "13"

Die beiden Arrays dienen im weiteren Programmablauf dazu, die einzelnen Excel Zellen des Spielfeldes einzugrenzen. Jede Kombination der beiden Arrays bestimmen als X/Y Wert eine Zelle des Spielfeldes auf der “Excelmaske”.

Schritt 2: Spielerdaten

Schritt 2 befasst sich mit dem Auslesen und Validieren der Spielerdaten.

Spieler() ist hierbei wiederum ein 2 dimensionales Array, bei dem der 1. Index den Spielernamen, der 2 Index den “Spielstein” aufnimmt.

Rem “*** Auslesen der Spielerdaten ****************************************************”
  1.     Spieler(0, 0) = Range("C4").Value
  2.     Spieler(0, 1) = Range("D4").Value
  3.     Spieler(1, 0) = Range("C5").Value
  4.     Spieler(1, 1) = Range("D5").Value
  5.  
  6.     Rem "=== Prüfung auf Namen ========================================================"
  7.     sText = ""
  8.     If Spieler(0, 0) = "" Then
  9.         sText = sText + "- Spieler A wurde nicht angegeben" + Chr(10)
  10.     End If
  11.  
  12.     If Spieler(1, 0) = "" Then
  13.         sText = sText + "- Spieler B wurde nicht angegeben" + Chr(10)
  14.     End If
  15.  
  16.     Rem "=== fehlt mindesten ein Spieler = Fehlermeldung und Abbruch =================="
  17.     If sText <> "" Then
  18.         sText = "Es wurden folgende Fehler festgestellt: " + Chr(10) + sText
  19.         MsgBox sText, vbOKOnly, "Fehler"
  20.         Exit Function
  21.     End If

Nur wenn beide Spielernamen angegeben sind, wird die Verarbeitung der Funktion weiter ausgeführt. Andernfalls erfolgt eine Meldung über das Fehlen mindestens eines Spielernamens oder auch Beider und ein gezielter Abbruch der Funktion.

 Schritt 3: Spielfeld löschen

Als nächstes wird in einem kleinen Schleifendurchlauf das Spielfeld, dass als globales 2 dimensionales Array deklariert wurde gelöscht/initialisiert:

Rem “*** Spielfeld löschen ************************************************************”
  1.     For X = 1 To 7
  2.         For Y = 1 To 7
  3.             Spielfeld(X, Y) = ""
  4.             Range(Spalten(X) + Zeilen(Y)).Value = ""
  5.         Next
  6.     Next

Schritt 4: ersten Spieler ermitteln

Damit nicht immer mit dem gleichen Spieler begonnen wird, habe ich eine kleine Hilfsfunktion implementiert, die mittes Zufallszahlen einen Spieler als startenden Spieler ermittelt.

Rem “*** Berechnung des beginnenden Spielers ==========================================”
  1.     If BerechneStartSpieler(iReturn) = False Then
  2.         sText = "Fehler bei Berechnung des beginnenden Spielers"
  3.         MsgBox sText, vbOKOnly, "Fehler"
  4.         Exit Function
  5.     End If
  6.  
  7.     Rem "=== Spieler eintragen ========================================================"
  8.     Range("I4").Value = Spieler(iReturn, 0)

Das Ergebnis der Funktion wird dann als Wert im Spielfeld eingetragen. Im Laufe des Spiels wird diese Zelle “I4″ immer mit dem Spieler angedruckt, der seienn Zug machen soll. Die ausprogrammierte Logik der BerechneStartSpieler() wird in einem späteren Post erläutert werden.

Schritt 5: Abschlußmeldung:

Wie sich das für jede Initialisierungsfunktion gehört, wird zum Abschluß, wenn die Verarbeitung erfolgreich war, eine Meldung ausgegeben, die dem Spieler signalisieren soll, dass er loslegen darf.

Rem “*** Abschlussmeldung *************************************************************”
  1.     sText = "Initialisierung abgeschlossen " + Chr(10)
  2.     sText = sText + "Viel Spaß"
  3.     MsgBox sText, vbOKOnly, "Info"
Gelistet im Blog Verzeichnis
Köln Fans Die Seite für Kölner
Blog Verzeichnis