Moin Leute,
auf Anregung aus einem anderen Thread hier meine Umsetzung eines TicTacToe Spiels. Der Code ist lauffähig (mit Option Strict on). Im Anhang noch eine Compilierte .exe, um besser zu sehen was passiert.
Habe ich grobe Design Fehler im Aufbau des Codes gemacht oder sonstige Entscheidungen getroffen die ich mir nicht aneignen sollte für spätere Projekte. Geht es anders viel besser.
Ganz klar wird das mit JA zu beantworten sein. Falls möglich dann noch kurz sagen, wie wichtig es wäre das zu ändern (Einschätzung der Dringlichkeit/Wichtigkeit) oder ist es eher eine Geschmackssache.
(den Thread [Sammelthread] Code-Korrektur hab ich wahrgenommen. Denke mein Bsp. ist zu groß dafür. Falls nicht gerne dorthin verschieben).
Erklärung was das Programm macht:
Es soll ein TicTacToe Clone sein 3 gleiche Symbole in Reihe, Spalte oder Diagonale gewinnt. Es wird abwechselt gezogen. Feld ist 3x3 groß.
Struktur:
Form1 -> im Grunde keine Logik Entscheidungen oder Variablen, es werden nur die nötigen Subs und Funktionen in Modul2 in der richtigen Reihenfolge aufgerufen sobald der User ein Feld angeklickt hat.
wichtige Methoden des Moduls
ResetGame ()-> setzt alle Felder und Checkboxen etc. wieder auf Anfang. Belegt das Spielfeld mit String " " das symbolisiert, dass das Feld frei ist und noch nicht gespielt wurde
UserMove () -> Speichert ins SpielstandArray "0" (Spielstein des Users) beim Index der der Nummer der angeklickten Box entspricht.
Spielfeld ist so im Array angelegt
0 1 2
3 4 5
6 7 8
Falls der User Textbox 1 anklickt wird an Arraystelle 1 eine "0" gespeichert und im Feld angezeigt
DidIWin ()-> schaut nach ob im SpielstandArray drei gleiche Symbole vorliegen.
4 mal 2 For next Schleifen
Alle Zeilen werden durchgesehen
(0 1 2) (3 4 5 ) (6 7 8)
Alle Spalten
(0 3 6) (1 4 7) (2 5 8)
& beide Diagonalen
(0 4 8) und (2 4 6)
BotLvl0 () -> bei Level 0 wählt die CPU einfach ein Zufälliges freies Feld aus
Erst wird geschaut wie viele Freiespielfelder noch existieren (ist abhängig wie viele Züge schon gespielt wurden). Dann wird eine Zufallszahl generiert aus der Menge 1 bis Anzahl freie Felder.
Bsp:
0 X 0
0 - X
- - -
Anzahl freie Felder 4 -> Zufallszahl von 1-4 = 2 -> das zweite Freifeld wird als gewählt angezeigt
0 X 0
0 - X
X - -
BotLvl1()-> ruft Bestmove() ->
Es wird wie bei 3 Gleiche in Reihe gesucht nach 2 in "Reihe/Spalte/Diag." und falls es dazu noch ein freies Feld in dieser "Reihe/Spalte/Diag." gibt ist das beste Feld.
Falls da nichts gefunden wird wird Level0 aufgerufen und ein Zufallsfeld genommen.
BotLvl2() -> hab ich nicht fertig und daher auf nicht sichtbar gestellt
Spoiler anzeigen
Ich freue mich auf Anregungen und bitte daran zu denken das ich noch ziemlich am Anfang stehe. Es sollte möglichst nicht zu abstrakt werden damit ich es noch verstehe. Am besten konkret mit Code. Danke und viel Spass...
*Beitrag verschoben, langen Codeteil gespoilert und EXE aus Sicherheitsgründen entfernt (bitte Projektdateien hochladen)* ~NoFear23m
auf Anregung aus einem anderen Thread hier meine Umsetzung eines TicTacToe Spiels. Der Code ist lauffähig (mit Option Strict on). Im Anhang noch eine Compilierte .exe, um besser zu sehen was passiert.
Habe ich grobe Design Fehler im Aufbau des Codes gemacht oder sonstige Entscheidungen getroffen die ich mir nicht aneignen sollte für spätere Projekte. Geht es anders viel besser.
Ganz klar wird das mit JA zu beantworten sein. Falls möglich dann noch kurz sagen, wie wichtig es wäre das zu ändern (Einschätzung der Dringlichkeit/Wichtigkeit) oder ist es eher eine Geschmackssache.
(den Thread [Sammelthread] Code-Korrektur hab ich wahrgenommen. Denke mein Bsp. ist zu groß dafür. Falls nicht gerne dorthin verschieben).
Erklärung was das Programm macht:
Es soll ein TicTacToe Clone sein 3 gleiche Symbole in Reihe, Spalte oder Diagonale gewinnt. Es wird abwechselt gezogen. Feld ist 3x3 groß.
Struktur:
Form1 -> im Grunde keine Logik Entscheidungen oder Variablen, es werden nur die nötigen Subs und Funktionen in Modul2 in der richtigen Reihenfolge aufgerufen sobald der User ein Feld angeklickt hat.
wichtige Methoden des Moduls
ResetGame ()-> setzt alle Felder und Checkboxen etc. wieder auf Anfang. Belegt das Spielfeld mit String " " das symbolisiert, dass das Feld frei ist und noch nicht gespielt wurde
UserMove () -> Speichert ins SpielstandArray "0" (Spielstein des Users) beim Index der der Nummer der angeklickten Box entspricht.
Spielfeld ist so im Array angelegt
0 1 2
3 4 5
6 7 8
Falls der User Textbox 1 anklickt wird an Arraystelle 1 eine "0" gespeichert und im Feld angezeigt
DidIWin ()-> schaut nach ob im SpielstandArray drei gleiche Symbole vorliegen.
4 mal 2 For next Schleifen
Alle Zeilen werden durchgesehen
(0 1 2) (3 4 5 ) (6 7 8)
Alle Spalten
(0 3 6) (1 4 7) (2 5 8)
& beide Diagonalen
(0 4 8) und (2 4 6)
BotLvl0 () -> bei Level 0 wählt die CPU einfach ein Zufälliges freies Feld aus
Erst wird geschaut wie viele Freiespielfelder noch existieren (ist abhängig wie viele Züge schon gespielt wurden). Dann wird eine Zufallszahl generiert aus der Menge 1 bis Anzahl freie Felder.
Bsp:
0 X 0
0 - X
- - -
Anzahl freie Felder 4 -> Zufallszahl von 1-4 = 2 -> das zweite Freifeld wird als gewählt angezeigt
0 X 0
0 - X
X - -
BotLvl1()-> ruft Bestmove() ->
Es wird wie bei 3 Gleiche in Reihe gesucht nach 2 in "Reihe/Spalte/Diag." und falls es dazu noch ein freies Feld in dieser "Reihe/Spalte/Diag." gibt ist das beste Feld.
Falls da nichts gefunden wird wird Level0 aufgerufen und ein Zufallsfeld genommen.
BotLvl2() -> hab ich nicht fertig und daher auf nicht sichtbar gestellt
FORM1
Modul
VB.NET-Quellcode
- Option Strict On
- Public Class Form1
- Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
- Randomize()
- ResetGame()
- End Sub
- Private Sub CheckBoxBot_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBoxBot.CheckedChanged
- If CheckBoxBot.Checked = True Then
- CheckBoxBot.Enabled = False
- LblTop.Focus()
- BotMove()
- End If
- End Sub
- Private Sub Txboxes_clicked(sender As Object, e As EventArgs) Handles Txb0.Click, Txb1.Click, Txb2.Click, Txb3.Click,
- Txb4.Click, Txb5.Click, Txb6.Click, Txb7.Click, Txb8.Click
- 'Late Binding ist nicht erlaubt daher mit direct cast
- Dim ClickedBox As String
- ClickedBox = DirectCast(sender, TextBox).Name
- UserMove(ClickedBox) 'Starte Sub mit "Welche Textbox hat der User angeclicked"
- DidIWin()
- If Ende = False Then
- BotMove()
- DidIWin()
- End If
- If Ende Then
- Ergebnise()
- Exit Sub
- End If
- End Sub
- Private Sub BtnReset_Click(sender As Object, e As EventArgs) Handles BtnReset.Click
- ResetGame()
- End Sub
- End Class
Modul
VB.NET-Quellcode
- Option Strict On
- Module Module2
- Dim FreiesFeldZeichen As String = " "
- Dim HumanPlays0 As String = "0"
- Dim BotplaysX As String = "X"
- Dim SpielStandArray(8) As String
- Dim WinFieldHuman As Integer = -1
- Dim WinfieldBot As Integer = -1
- Dim HWins As Integer = 0
- Dim BWins As Integer = 0
- Dim Draw As Integer = 0
- Dim SpielfeldBoxen As TextBox() = {Form1.Txb0, Form1.Txb1, Form1.Txb2, Form1.Txb3, Form1.Txb4, Form1.Txb5, Form1.Txb6, Form1.Txb7, Form1.Txb8}
- Dim UserMoveArray(5) As Integer 'Array index des User Moves für Botlevl 2
- Dim UsermoveCounter As Integer = 0
- Dim BotMoveArray(5) As Integer 'Array index des Bots Moves für Botlevl 2
- Dim BotMoveCounter As Integer = 0
- Dim Count0 As Integer 'Human
- Dim CountX As Integer 'CPU
- Dim FreiesFeldIn3erReihe As Integer = -1 'falls es so was wie X -- X gibt wird der Index des FreienFeldes hier gespeichert
- Public SpielTiefe As Integer = 1
- Public Ende As Boolean = False
- Sub ResetGame()
- For i = 0 To 8
- SpielfeldBoxen(i).Text = FreiesFeldZeichen 'wird mit z.B. String " " vorbelegt
- SpielfeldBoxen(i).Enabled = True
- SpielStandArray(i) = FreiesFeldZeichen
- Next
- SpielTiefe = 1
- WinFieldHuman = -1
- WinfieldBot = -1
- Form1.CheckBoxBot.Enabled = True
- Form1.CheckBoxBot.Checked = False
- Ende = False
- For i = 0 To 4
- BotMoveArray(i) = -1
- UserMoveArray(i) = -1
- Next
- BotMoveCounter = 0
- UsermoveCounter = 0
- End Sub
- Sub UserMove(ByVal ClickedBoxName As String)
- For i = 0 To 8
- If SpielfeldBoxen(i).name = ClickedBoxName Then
- SpielStandArray(i) = HumanPlays0
- SpielfeldBoxen(i).Text = HumanPlays0
- SpielfeldBoxen(i).Enabled = False
- UserMoveArray(UsermoveCounter) = i
- Form1.LblTop.Focus()
- Exit For
- End If
- Next
- Form1.CheckBoxBot.Enabled = False 'User hat angefangen also kann Bot nicht mehr anfangen
- UsermoveCounter += 1
- SpielTiefe += 1
- End Sub
- Sub Count3Win()
- If Count0 = 3 Or CountX = 3 Then
- If Count0 = 3 Then
- MsgBox("Humans win!")
- Ende = True
- HWins += 1
- Exit Sub
- End If
- If CountX = 3 Then
- MsgBox("Oh my God Bot wins!")
- Ende = True
- BWins += 1
- Exit Sub
- End If
- End If
- End Sub
- Sub DidIWin()
- 'Zeilen nach 3 Gleichen in Reihe duchsuchen
- '0 1 2
- '3 4 5 wird zu (0 1 2) (3 4 5) (6 7 8)
- '6 7 8
- For i = 0 To 2
- Count0 = 0
- CountX = 0
- For j = 0 To 2
- If SpielStandArray(i * 3 + j) = HumanPlays0 Then Count0 += 1
- If SpielStandArray(i * 3 + j) = BotplaysX Then CountX += 1
- Next
- Count3Win()
- If Ende = True Then Exit Sub
- Next
- 'Spalten nach 3 Gleichen durchsuchen
- '0 1 2
- '3 4 5 wird zu (0 3 6) (1 4 7) (2 5 8)
- '6 7 8
- For k = 0 To 2
- Count0 = 0
- CountX = 0
- For l = 0 To 6 Step 3
- If SpielStandArray(k + l) = HumanPlays0 Then Count0 += 1
- If SpielStandArray(k + l) = BotplaysX Then CountX += 1
- Next
- Count3Win()
- If Ende = True Then Exit Sub
- Next
- 'Diagonalen nach 3 Gleichen durchsuchen
- '0 1 2
- '3 4 5 wird zu (0 4 8) (2 4 6)
- '6 7 8
- '
- 'Erste Diagonale (0 4 8)
- Count0 = 0
- CountX = 0
- For m = 0 To 8 Step 4
- If SpielStandArray(m) = HumanPlays0 Then Count0 += 1
- If SpielStandArray(m) = BotplaysX Then CountX += 1
- Next
- Count3Win()
- If Ende = True Then Exit Sub
- 'Zweiter Diagonale (2 4 6)
- Count0 = 0
- CountX = 0
- For n = 2 To 6 Step 2
- If SpielStandArray(n) = HumanPlays0 Then Count0 += 1
- If SpielStandArray(n) = BotplaysX Then CountX += 1
- Next
- Count3Win()
- If Ende = True Then Exit Sub
- 'Falls keine 3 in Reihe gefunden wurden und der letzte Zug 10 war ist es ein Draw
- If SpielTiefe = 10 Then
- MsgBox("We will see us again Human!")
- Ende = True
- Draw += 1
- End If
- End Sub
- Sub BotMove()
- If Form1.OptLvl0.Checked Then BotMoveLvl0()
- If Form1.OptLvl1.Checked Then BotMoveLvl1()
- If Form1.OptLvl2.Checked Then BotMoveLvl2()
- End Sub
- Sub BotMoveLvl0() 'Bot selects random FreeField
- Dim AnzahlFreierFelder As Integer = 10
- Dim ZufallsFeldZahl As Integer
- Dim count As Integer = 0
- AnzahlFreierFelder -= SpielTiefe
- ZufallsFeldZahl = Convert.ToInt32(Math.Floor(Rnd() * AnzahlFreierFelder)) + 1
- For i = 0 To 8
- If SpielStandArray(i) = FreiesFeldZeichen Then count += 1
- If count = ZufallsFeldZahl Then
- SpielStandArray(i) = BotplaysX
- SpielfeldBoxen(i).text = BotplaysX
- SpielfeldBoxen(i).Enabled = False
- Form1.LblTop.Focus()
- Exit For
- End If
- Next
- SpielTiefe += 1
- End Sub
- Sub BotMoveLvl1()
- BestMoves() 'looks for 2 in a Row for Human0 and for BotX
- 'and stores a possible freefield index Array Nr. in WinfieldHuamn and WinfieldBot
- If WinfieldBot <> -1 Then
- SpielStandArray(WinfieldBot) = BotplaysX
- SpielfeldBoxen(WinfieldBot).text = BotplaysX
- SpielfeldBoxen(WinfieldBot).Enabled = False
- Form1.LblTop.Focus()
- SpielTiefe += 1
- ElseIf WinFieldHuman <> -1 Then
- SpielStandArray(WinFieldHuman) = BotplaysX
- SpielfeldBoxen(WinFieldHuman).text = BotplaysX
- SpielfeldBoxen(WinFieldHuman).Enabled = False
- Form1.LblTop.Focus()
- SpielTiefe += 1
- Else
- BotMoveLvl0()
- End If
- End Sub
- Sub BotMoveLvl2()
- 'kommt noch
- End Sub
- Sub BestMoves() 'looks for 2 in a Row 0 or X and saves the index of a possible freefield
- FreiesFeldIn3erReihe = -1 'equals kein freies Feld
- WinfieldBot = -1
- WinFieldHuman = -1
- 'Zeilen nach 2 Gleichen in Reihe duchsuchen
- '0 1 2
- '3 4 5 wird zu (0 1 2) (3 4 5) (6 7 8)
- '6 7 8
- For i = 0 To 2
- Count0 = 0
- CountX = 0
- FreiesFeldIn3erReihe = -1
- For j = 0 To 2
- If SpielStandArray(i * 3 + j) = FreiesFeldZeichen Then FreiesFeldIn3erReihe = (i * 3 + j)
- If SpielStandArray(i * 3 + j) = HumanPlays0 Then Count0 += 1
- If SpielStandArray(i * 3 + j) = BotplaysX Then CountX += 1
- Next
- If Count0 = 2 And FreiesFeldIn3erReihe <> -1 Then WinFieldHuman = FreiesFeldIn3erReihe
- If CountX = 2 And FreiesFeldIn3erReihe <> -1 Then WinfieldBot = FreiesFeldIn3erReihe
- Next
- 'Spalten nach 2 Gleichen durchsuchen
- '0 1 2
- '3 4 5 wird zu (0 3 6) (1 4 7) (2 5 8)
- '6 7 8
- For k = 0 To 2
- Count0 = 0
- CountX = 0
- FreiesFeldIn3erReihe = -1
- For l = 0 To 6 Step 3
- If SpielStandArray(k + l) = FreiesFeldZeichen Then FreiesFeldIn3erReihe = (k + l)
- If SpielStandArray(k + l) = HumanPlays0 Then Count0 += 1
- If SpielStandArray(k + l) = BotplaysX Then CountX += 1
- Next
- If Count0 = 2 And FreiesFeldIn3erReihe <> -1 Then WinFieldHuman = FreiesFeldIn3erReihe
- If CountX = 2 And FreiesFeldIn3erReihe <> -1 Then WinfieldBot = FreiesFeldIn3erReihe
- Next
- 'Diagonalen nach 2 Gleichen durchsuchen
- '0 1 2
- '3 4 5 wird zu (0 4 8) (2 4 6)
- '6 7 8
- '
- 'Erste Diagonale (0 4 8)
- Count0 = 0
- CountX = 0
- FreiesFeldIn3erReihe = -1
- For m = 0 To 8 Step 4
- If SpielStandArray(m) = FreiesFeldZeichen Then FreiesFeldIn3erReihe = (m)
- If SpielStandArray(m) = HumanPlays0 Then Count0 += 1
- If SpielStandArray(m) = BotplaysX Then CountX += 1
- Next
- If Count0 = 2 And FreiesFeldIn3erReihe <> -1 Then WinFieldHuman = FreiesFeldIn3erReihe
- If CountX = 2 And FreiesFeldIn3erReihe <> -1 Then WinfieldBot = FreiesFeldIn3erReihe
- 'Zweiter Diagonale (2 4 6)
- Count0 = 0
- CountX = 0
- FreiesFeldIn3erReihe = -1
- For n = 2 To 6 Step 2
- If SpielStandArray(n) = FreiesFeldZeichen Then FreiesFeldIn3erReihe = (n)
- If SpielStandArray(n) = HumanPlays0 Then Count0 += 1
- If SpielStandArray(n) = BotplaysX Then CountX += 1
- Next
- If Count0 = 2 And FreiesFeldIn3erReihe <> -1 Then WinFieldHuman = FreiesFeldIn3erReihe
- If CountX = 2 And FreiesFeldIn3erReihe <> -1 Then WinfieldBot = FreiesFeldIn3erReihe
- End Sub
- Sub Ergebnise()
- Form1.LblScore.Text = "H:" & HWins & " D:" & Draw & " Bot:" & BWins
- For i = 0 To 8
- SpielfeldBoxen(i).Enabled = False
- Next
- Form1.BtnReset.Focus()
- End Sub
- End Module
Ich freue mich auf Anregungen und bitte daran zu denken das ich noch ziemlich am Anfang stehe. Es sollte möglichst nicht zu abstrakt werden damit ich es noch verstehe. Am besten konkret mit Code. Danke und viel Spass...
*Beitrag verschoben, langen Codeteil gespoilert und EXE aus Sicherheitsgründen entfernt (bitte Projektdateien hochladen)* ~NoFear23m
codewars.com Rank: 4 kyu
Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Nofear23m“ ()