Hallo, ich habe in meiner Freizeit mal ein TicTacToe programmiert und wollte das jetzt hier veröffentlichen, weil ich Expertenmeinugen dazu hören wollte. Außerdem soll dies allen helfen, die Probleme haben, ein TicTacToe zu programmieren.
Sollte eigentlich bei allen funktionieren.
Die Steuerelemente sind:
Form: Form namens TicTacToe (Spielfeld)
11 Buttons:
9 für das Spielfeld : btnFeld00 - btnFeld22
Anordnung ist so aufgebaut ([X/X] ist ein Button):
[0/0] [0/1] [0/2]
[1/0] [1/1] [1/2]
[2/0] [2/1] [2/2]
2 für Neues Spiel und Nächste Runde
Labels (Statusbar-Labels beginnen mit lbls statt mit lbl):
für Punktestand von X und O (lblScoreX & lblScoreO),
für Datum und Zeit (optional),
Für Runde und Zug der jeweiligen Runde (Statuslabels),
Timer fürs Datum (optional)
ColorDialog zur Auswahl der Hintergrundfarbe
eventuell: Statusleiste, ToolStrip
Hier der Code für das Game:
Spoiler anzeigen
Verbesserungs- und/oder Verkürzungs-vorschläge sind erwünscht, aber wenn möglich, bitte mit Erklärungen und/oder Beispielen.
Danke im Voraus
Sollte eigentlich bei allen funktionieren.
Die Steuerelemente sind:
Form: Form namens TicTacToe (Spielfeld)
11 Buttons:
9 für das Spielfeld : btnFeld00 - btnFeld22
Anordnung ist so aufgebaut ([X/X] ist ein Button):
[0/0] [0/1] [0/2]
[1/0] [1/1] [1/2]
[2/0] [2/1] [2/2]
2 für Neues Spiel und Nächste Runde
Labels (Statusbar-Labels beginnen mit lbls statt mit lbl):
für Punktestand von X und O (lblScoreX & lblScoreO),
für Datum und Zeit (optional),
Für Runde und Zug der jeweiligen Runde (Statuslabels),
Timer fürs Datum (optional)
ColorDialog zur Auswahl der Hintergrundfarbe
eventuell: Statusleiste, ToolStrip
Hier der Code für das Game:
VB.NET-Quellcode
- Public Class TicTacToe
- 'Der 1.Zug des Computergegners einer Runde, Enumeration hat: Keiner = 0, Mitte = 11 und RechtsUnten = 22
- Dim Zug1 As ComputerZug 'Eine Enumeration weiter unten
- 'Gibt an, ob das O für den Zug schon gesetzt wurde
- Dim O_gesetzt As Boolean 'Damit es nicht mehrmals gesetzt wird, weiß nicht obs notwendig ist
- 'Der aktuelle Zug der Runde (maximal 9, da es dann unentschieden ist)
- Dim Zug As Byte = 1
- 'Das Spielfeld als 2D-Array von Buttons (Entspricht der Anordnung für die Namen der Buttons)
- Dim Felder(2, 2) As Button 'Ist einfach leichter zu handeln als alle Buttons einzeln anzusprechen
- Private Sub TicTacToe_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
- 'Weist den Buttons ihren Platz im Array zu und macht ein 1.Belegen des lblsDate
- lblsDate.Text = System.DateTime.Now.ToString
- For ze = 0 To 2 'stehen für Zeile und Spalte (von 0 bis 2), Anordnung siehe oben
- For sp = 0 To 2
- Felder(ze, sp) = Me.Controls("btnFeld" & ze & sp) 'Die Buttons heißen ja btnFeld00- btnFeld22, das merkt euch
- Me.Controls("btnFeld" & ze & sp).Text = " " 'Jedem Text wird " " zugewiesen, damit er auf jeden Fall leer ist
- Next
- Next
- End Sub
- 'Die Funktion, die untersucht, ob man das Spiel gewonnen hat
- 'Der Parameter ist der Spieler, für den die Prozedur aufgerufen wird (X, O), der für die Siegesnachricht und den Punktestand gebraucht wird.
- 'Das ze_sp untersucht zuerst jede waagrechte oder senkrechte Reihe in EINER for-Schleife, und prüft dann per If die Diagonalen extra ab.
- Private Function CheckWin(ByVal Pl As Char) As Boolean
- 'ze_sp wird als Zeile und Spalte gleichzeitig verwendet, deswegen ze_sp. Zuerst Zeile dann Spalte.
- For ze_sp = 0 To 2
- 'waagrechte und senkrechte Reihe prüfen
- 'Prüft auf eine waagrechte Reihe
- If Felder(ze_sp, 0).Text = Pl AndAlso Felder(ze_sp, 1).Text = Pl _
- AndAlso Felder(ze_sp, 2).Text = Pl _
- 'Prüft auf eine senkrechte Reihe
- OrElse Felder(0, ze_sp).Text = Pl AndAlso Felder(1, ze_sp).Text = Pl _
- AndAlso Felder(2, ze_sp).Text = Pl Then
- 'Gib True zurück, wenn jemand gewonnen hat
- Return True
- End If
- Next
- 'Prüft Diagonalen ab
- 'Links-Oben Nach Rechts-Unten-Diagonale
- If Felder(0, 0).Text = Pl AndAlso Felder(1, 1).Text = Pl AndAlso _
- Felder(2, 2).Text = Pl OrElse _
- _
- 'Rechts-Oben Nach Links-Unten Diagonale
- Felder(0, 2).Text = Pl AndAlso _
- Felder(1, 1).Text = Pl AndAlso Felder(2, 0).Text = Pl Then
- Return True
- End If
- 'Wenn niemand gewonnen hat, gebe False zurück
- Return False
- End Sub
- 'Wenn man das Spiel gewonnen hat, was durch die obere Funktion überprüft wird
- Sub Sieg(ByVal pl As Char)
- 'Alle Buttons deaktivieren, damit man nicht mehr darauf klicken kann
- enablebuttons()
- 'MessageBox anzeigen
- MessageBox.Show("Spieler " & pl & " hat gewonnen", "Gewonnen")
- 'Die Punkte im jeweiligen Label erhöhen
- Me.Controls("lblScore" & Pl).Text += 1 'Funktioniert, auch wenn es Strict On-mäßig besser wäre
- 'Den NächsteRunde-Button hervorbringen, für die Nächste Runde, der vorher unsichtbar war.
- btnReset.Visible = True
- End Sub
- 'Deaktiviert Buttons bei einem Sieg
- Private Sub enablebuttons()
- 'For Each Schleife: Wenn das Control ein Button ist und
- 'sein Name mit btnFeld beginnt und es noch aktiviert ist, deaktiviere es
- For Each btn As Control In Me.Controls
- If TypeOf btn Is Button AndAlso btn.Name.StartsWith("btnFeld") _
- AndAlso btn.Enabled = True Then btn.Enabled = False
- Next
- End Sub
- 'Enumeration, die die Variable Zug1 besser verständlich macht
- Enum Computerzug
- Mitte = 11
- RechtsUnten = 22
- Keiner = 0
- End Enum
- 'Der Computer, der das Zeichen O setzt, die KI ist natürlich, euren Vorstellungen entsprechend anpassbar
- Public Sub Computergegner()
- Dim ze_sp As Byte 'Fungiert als Zeile + Spalte
- O_gesetzt = False 'Am Anfang setze das womöglich schon =true O_gesetzt auf false
- 'O vollenden
- For ze_sp = 0 To 2
- If Not O_gesetzt Then
- 'ze_sp= Zeile
- ReiheVollenden("O", Felder(ze_sp, 0), _
- Felder(ze_sp, 1), Felder(ze_sp, 2))
- End If
- If Not O_gesetzt Then
- 'ze_sp = Spalte
- ReiheVollenden("O", Felder(0, ze_sp), _
- Felder(1, ze_sp), Felder(2, ze_sp))
- End If
- Next
- If Not O_gesetzt Then ReiheVollenden("O", Felder(0, 0), _
- Felder(1, 1), Felder(2, 2))
- If Not O_gesetzt Then ReiheVollenden("O", Felder(0, 2), Felder(1, 1), Felder(2, 0))
- 'X vereiteln (Das Ganze ist getrennt, weil es zuerst das O vollenden und erst dann das X vereiteln soll
- For ze_sp2 = 0 To 2
- If Not O_gesetzt Then
- ReiheVollenden("X", Felder(ze_sp2, 0), Felder(ze_sp2, 1), Felder(ze_sp2, 2))
- End If
- If Not O_gesetzt Then
- ReiheVollenden("X", Felder(0, ze_sp2), Felder(1, ze_sp2), Felder(2, ze_sp2))
- End If
- Next
- If Not O_gesetzt Then ReiheVollenden("X", Felder(0, 0), Felder(1, 1), Felder(2, 2))
- If Not O_gesetzt Then ReiheVollenden("X", Felder(0, 2), Felder(1, 1), Felder(2, 0))
- 'Die Os setzten, wenn nichts vereitelt oder vollendet werden muss
- 'Das erste O setzten
- If Zug = 2 Then
- 'Wenn es der 1.Zug für O ist
- If Felder(1, 1).Text <> "X" Then
- If Not O_gesetzt Then
- Belegen("O", Felder(1, 1))
- Zug1 = ComputerZug.Mitte
- 'Signalisieren, dass das O gesetzt wurde
- O_gesetzt = True
- End If
- Else
- If Not O_gesetzt Then
- Belegen("O", Felder(2, 2))
- Zug1 = ComputerZug.RechtsUnten
- O_gesetzt = True
- End If
- End If
- End If
- ' Das zweite O setzten
- If Zug = 4 Then
- 'Wenn es der 2.Zug von O ist
- If Not O_gesetzt Then
- If Zug1 = 11 Then
- 'Wenn das 1.O in der Mitte war, setzt es das O in die rechte untere Ecke
- If Felder(2, 2).Enabled = True Then
- Belegen("O", Felder(2, 2))
- O_gesetzt = True
- End If
- Else
- 'andernfalls in die linke untere Ecke
- If Felder(2, 0).Enabled = True Then
- Belegen("O", Felder(2, 0))
- O_gesetzt = True
- End If
- End If
- End If
- End If
- 'Wenn keine der oben stehenden Möglichkeiten erfolgt,
- 'setzt es das O auf ein beliebiges freies Feld
- Dim rmd As New Random
- 'Die zufälligen Indices des Feldes
- Dim r1, r2 As Byte
- 'steht für Random-Index 1 und 2
- 'Wenn es ein Zug von O ist
- If Zug Mod 2 = 0 Then
- 'Solange O nocht nicht gesetzt wurde
- Do While O_gesetzt = False
- 'Ein Zufallsfeld besetzten
- r1 = rmd.Next(0, 2)
- r2 = rmd.Next(0, 2)
- If Felder(r1, r2).Enabled = True Then
- Belegen("O", Felder(r1, r2))
- O_gesetzt = True
- End If
- Loop
- End If
- End Sub
- 'Eine ReiheVollenden-Prozedur, die drei Felder werden über 6 Indices übergeben
- Sub ReiheVollenden(ByVal Sy As Char, ByVal B1 As Button, ByVal B2 As Button, ByVal B3 As Button)
- Dim Segment(2) As Char 'Die zu überprüfende Zeile, Spalte oder Diagonale
- Dim z_, zSy As Byte 'Der Zähler der belegten und unbelegten Felder
- Dim selSeg As Byte ' Das (erste) leere Segmentelement
- 'Das Segment belegen
- Segment(0) = B1.Text
- Segment(1) = B2.Text
- Segment(2) = B3.Text
- 'Prüft, ob 2 Felder 1 enthalten und das dritte Feld leer ist
- For i = 0 To 2
- If Segment(i) = Sy Then zSy += 1
- If Segment(i) = " " Then
- z_ += 1
- selSeg = i
- End If
- Next
- 'Wenn zwei gleich belegte und ein leeres Feld vorhanden sind...
- If zSy = 2 And z_ = 1 Then
- Select Case selSeg
- '...wird das leere Feld belegt
- Case 0
- Belegen("O", Felder(I1, I2))
- O_gesetzt = True
- Case 1
- Belegen("O", Felder(I3, I4))
- O_gesetzt = True
- Case 2
- Belegen("O", Felder(I5, I6))
- O_gesetzt = True
- End Select
- End If
- End Sub
- 'Hinweis: Das Spielfeld ist Indexmäßig so aufgebaut
- '0/0, 0/1, 0/2
- '1/0, 1/1, 1/2
- '2/0. 2/1, 2/2
- ' Buttons des Spielfelds
- 'Erst Belegen, dann den Computergegner aufrufen, damit er sein O setzt
- Private Sub FeldButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
- Handles btnFeld00.Click, btnFeld01.Click, btnFeld02.Click, btnFeld10.Click, _
- btnFeld11.Click, btnFeld12.Click, btnFeld20.Click, btnFeld21.Click, btnFeld22.Click
- Belegen("X", CType(sender, Button))
- If CheckWin("X") Then
- Sieg("X")
- Exit Sub
- End If
- If Zug < 9 Then : Computergegner()
- Else : Unentschieden()
- End If
- End Sub
- 'Reset Button
- Private Sub btnNaechsteRunde_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNaechsteRunde.Click
- Reset()
- 'Reset-Knopf verbergenbtnReset.Visible = False
- 'Die Runde um 1 erhöhen
- lblsRunde.Text += 1
- End Sub
- 'Menü
- Private Sub tmrZeit_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tmrZeit.Tick
- lblsDate.Text = System.DateTime.Now
- End Sub
- Sub Reset()
- Dim ze, sp As Byte
- 'Runde und Zug
- lblsZugZahl.Text = "1"
- Zug = 1
- For ze = 0 To 2
- For sp = 0 To 2
- With Felder(ze, sp)
- .Text = " "
- .Enabled = True
- End With
- Next
- Next
- Zug1 = ComputerZug.Keiner
- End Sub
- 'Einen übergeben Button mit einem übergebenen Symbol belegen
- Sub Belegen(ByVal Sp As Char, ByRef Feld As Button)
- Feld.Text = Sp
- Feld.Enabled = False
- lblsZugZahl.Text += 1
- Zug += 1
- End Sub
- 'Wenn das Spiel Unentschieden Endet
- Sub Unentschieden()
- MessageBox.Show("Unentschieden", "Unentschieden")
- btnNaechsteRunde.Visible= True
- End Sub
- Private Sub btnNeuesSpiel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNeuesSpiel.Click
- Reset()
- lblsRunde.Text = 1
- End Sub
- Private Sub Hintergrund(ByVal sender As Object, ByVal e as EventArgs) Handles btnHintergrund.Click
- If FarbenColorDialog.ShowDialog = Windows.Forms.DialogResult.OK Then
- Me.BackColor = FarbenColorDialog.Color
- btnNaechsteRunde.BackColor = FarbenColorDialog.Color
- End If
- End Sub
- End Class
Verbesserungs- und/oder Verkürzungs-vorschläge sind erwünscht, aber wenn möglich, bitte mit Erklärungen und/oder Beispielen.
Danke im Voraus
Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „VB_Gamer“ ()