TicTacToe-Klon

    • VB.NET

    Es gibt 12 Antworten in diesem Thema. Der letzte Beitrag () ist von VB_Gamer.

      TicTacToe-Klon

      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

      VB.NET-Quellcode

      1. Public Class TicTacToe
      2. 'Der 1.Zug des Computergegners einer Runde, Enumeration hat: Keiner = 0, Mitte = 11 und RechtsUnten = 22
      3. Dim Zug1 As ComputerZug 'Eine Enumeration weiter unten
      4. 'Gibt an, ob das O für den Zug schon gesetzt wurde
      5. Dim O_gesetzt As Boolean 'Damit es nicht mehrmals gesetzt wird, weiß nicht obs notwendig ist
      6. 'Der aktuelle Zug der Runde (maximal 9, da es dann unentschieden ist)
      7. Dim Zug As Byte = 1
      8. 'Das Spielfeld als 2D-Array von Buttons (Entspricht der Anordnung für die Namen der Buttons)
      9. Dim Felder(2, 2) As Button 'Ist einfach leichter zu handeln als alle Buttons einzeln anzusprechen
      10. Private Sub TicTacToe_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
      11. 'Weist den Buttons ihren Platz im Array zu und macht ein 1.Belegen des lblsDate
      12. lblsDate.Text = System.DateTime.Now.ToString
      13. For ze = 0 To 2 'stehen für Zeile und Spalte (von 0 bis 2), Anordnung siehe oben
      14. For sp = 0 To 2
      15. Felder(ze, sp) = Me.Controls("btnFeld" & ze & sp) 'Die Buttons heißen ja btnFeld00- btnFeld22, das merkt euch
      16. Me.Controls("btnFeld" & ze & sp).Text = " " 'Jedem Text wird " " zugewiesen, damit er auf jeden Fall leer ist
      17. Next
      18. Next
      19. End Sub
      20. 'Die Funktion, die untersucht, ob man das Spiel gewonnen hat
      21. 'Der Parameter ist der Spieler, für den die Prozedur aufgerufen wird (X, O), der für die Siegesnachricht und den Punktestand gebraucht wird.
      22. 'Das ze_sp untersucht zuerst jede waagrechte oder senkrechte Reihe in EINER for-Schleife, und prüft dann per If die Diagonalen extra ab.
      23. Private Function CheckWin(ByVal Pl As Char) As Boolean
      24. 'ze_sp wird als Zeile und Spalte gleichzeitig verwendet, deswegen ze_sp. Zuerst Zeile dann Spalte.
      25. For ze_sp = 0 To 2
      26. 'waagrechte und senkrechte Reihe prüfen
      27. 'Prüft auf eine waagrechte Reihe
      28. If Felder(ze_sp, 0).Text = Pl AndAlso Felder(ze_sp, 1).Text = Pl _
      29. AndAlso Felder(ze_sp, 2).Text = Pl _
      30. 'Prüft auf eine senkrechte Reihe
      31. OrElse Felder(0, ze_sp).Text = Pl AndAlso Felder(1, ze_sp).Text = Pl _
      32. AndAlso Felder(2, ze_sp).Text = Pl Then
      33. 'Gib True zurück, wenn jemand gewonnen hat
      34. Return True
      35. End If
      36. Next
      37. 'Prüft Diagonalen ab
      38. 'Links-Oben Nach Rechts-Unten-Diagonale
      39. If Felder(0, 0).Text = Pl AndAlso Felder(1, 1).Text = Pl AndAlso _
      40. Felder(2, 2).Text = Pl OrElse _
      41. _
      42. 'Rechts-Oben Nach Links-Unten Diagonale
      43. Felder(0, 2).Text = Pl AndAlso _
      44. Felder(1, 1).Text = Pl AndAlso Felder(2, 0).Text = Pl Then
      45. Return True
      46. End If
      47. 'Wenn niemand gewonnen hat, gebe False zurück
      48. Return False
      49. End Sub
      50. 'Wenn man das Spiel gewonnen hat, was durch die obere Funktion überprüft wird
      51. Sub Sieg(ByVal pl As Char)
      52. 'Alle Buttons deaktivieren, damit man nicht mehr darauf klicken kann
      53. enablebuttons()
      54. 'MessageBox anzeigen
      55. MessageBox.Show("Spieler " & pl & " hat gewonnen", "Gewonnen")
      56. 'Die Punkte im jeweiligen Label erhöhen
      57. Me.Controls("lblScore" & Pl).Text += 1 'Funktioniert, auch wenn es Strict On-mäßig besser wäre
      58. 'Den NächsteRunde-Button hervorbringen, für die Nächste Runde, der vorher unsichtbar war.
      59. btnReset.Visible = True
      60. End Sub
      61. 'Deaktiviert Buttons bei einem Sieg
      62. Private Sub enablebuttons()
      63. 'For Each Schleife: Wenn das Control ein Button ist und
      64. 'sein Name mit btnFeld beginnt und es noch aktiviert ist, deaktiviere es
      65. For Each btn As Control In Me.Controls
      66. If TypeOf btn Is Button AndAlso btn.Name.StartsWith("btnFeld") _
      67. AndAlso btn.Enabled = True Then btn.Enabled = False
      68. Next
      69. End Sub
      70. 'Enumeration, die die Variable Zug1 besser verständlich macht
      71. Enum Computerzug
      72. Mitte = 11
      73. RechtsUnten = 22
      74. Keiner = 0
      75. End Enum
      76. 'Der Computer, der das Zeichen O setzt, die KI ist natürlich, euren Vorstellungen entsprechend anpassbar
      77. Public Sub Computergegner()
      78. Dim ze_sp As Byte 'Fungiert als Zeile + Spalte
      79. O_gesetzt = False 'Am Anfang setze das womöglich schon =true O_gesetzt auf false
      80. 'O vollenden
      81. For ze_sp = 0 To 2
      82. If Not O_gesetzt Then
      83. 'ze_sp= Zeile
      84. ReiheVollenden("O", Felder(ze_sp, 0), _
      85. Felder(ze_sp, 1), Felder(ze_sp, 2))
      86. End If
      87. If Not O_gesetzt Then
      88. 'ze_sp = Spalte
      89. ReiheVollenden("O", Felder(0, ze_sp), _
      90. Felder(1, ze_sp), Felder(2, ze_sp))
      91. End If
      92. Next
      93. If Not O_gesetzt Then ReiheVollenden("O", Felder(0, 0), _
      94. Felder(1, 1), Felder(2, 2))
      95. If Not O_gesetzt Then ReiheVollenden("O", Felder(0, 2), Felder(1, 1), Felder(2, 0))
      96. 'X vereiteln (Das Ganze ist getrennt, weil es zuerst das O vollenden und erst dann das X vereiteln soll
      97. For ze_sp2 = 0 To 2
      98. If Not O_gesetzt Then
      99. ReiheVollenden("X", Felder(ze_sp2, 0), Felder(ze_sp2, 1), Felder(ze_sp2, 2))
      100. End If
      101. If Not O_gesetzt Then
      102. ReiheVollenden("X", Felder(0, ze_sp2), Felder(1, ze_sp2), Felder(2, ze_sp2))
      103. End If
      104. Next
      105. If Not O_gesetzt Then ReiheVollenden("X", Felder(0, 0), Felder(1, 1), Felder(2, 2))
      106. If Not O_gesetzt Then ReiheVollenden("X", Felder(0, 2), Felder(1, 1), Felder(2, 0))
      107. 'Die Os setzten, wenn nichts vereitelt oder vollendet werden muss
      108. 'Das erste O setzten
      109. If Zug = 2 Then
      110. 'Wenn es der 1.Zug für O ist
      111. If Felder(1, 1).Text <> "X" Then
      112. If Not O_gesetzt Then
      113. Belegen("O", Felder(1, 1))
      114. Zug1 = ComputerZug.Mitte
      115. 'Signalisieren, dass das O gesetzt wurde
      116. O_gesetzt = True
      117. End If
      118. Else
      119. If Not O_gesetzt Then
      120. Belegen("O", Felder(2, 2))
      121. Zug1 = ComputerZug.RechtsUnten
      122. O_gesetzt = True
      123. End If
      124. End If
      125. End If
      126. ' Das zweite O setzten
      127. If Zug = 4 Then
      128. 'Wenn es der 2.Zug von O ist
      129. If Not O_gesetzt Then
      130. If Zug1 = 11 Then
      131. 'Wenn das 1.O in der Mitte war, setzt es das O in die rechte untere Ecke
      132. If Felder(2, 2).Enabled = True Then
      133. Belegen("O", Felder(2, 2))
      134. O_gesetzt = True
      135. End If
      136. Else
      137. 'andernfalls in die linke untere Ecke
      138. If Felder(2, 0).Enabled = True Then
      139. Belegen("O", Felder(2, 0))
      140. O_gesetzt = True
      141. End If
      142. End If
      143. End If
      144. End If
      145. 'Wenn keine der oben stehenden Möglichkeiten erfolgt,
      146. 'setzt es das O auf ein beliebiges freies Feld
      147. Dim rmd As New Random
      148. 'Die zufälligen Indices des Feldes
      149. Dim r1, r2 As Byte
      150. 'steht für Random-Index 1 und 2
      151. 'Wenn es ein Zug von O ist
      152. If Zug Mod 2 = 0 Then
      153. 'Solange O nocht nicht gesetzt wurde
      154. Do While O_gesetzt = False
      155. 'Ein Zufallsfeld besetzten
      156. r1 = rmd.Next(0, 2)
      157. r2 = rmd.Next(0, 2)
      158. If Felder(r1, r2).Enabled = True Then
      159. Belegen("O", Felder(r1, r2))
      160. O_gesetzt = True
      161. End If
      162. Loop
      163. End If
      164. End Sub
      165. 'Eine ReiheVollenden-Prozedur, die drei Felder werden über 6 Indices übergeben
      166. Sub ReiheVollenden(ByVal Sy As Char, ByVal B1 As Button, ByVal B2 As Button, ByVal B3 As Button)
      167. Dim Segment(2) As Char 'Die zu überprüfende Zeile, Spalte oder Diagonale
      168. Dim z_, zSy As Byte 'Der Zähler der belegten und unbelegten Felder
      169. Dim selSeg As Byte ' Das (erste) leere Segmentelement
      170. 'Das Segment belegen
      171. Segment(0) = B1.Text
      172. Segment(1) = B2.Text
      173. Segment(2) = B3.Text
      174. 'Prüft, ob 2 Felder 1 enthalten und das dritte Feld leer ist
      175. For i = 0 To 2
      176. If Segment(i) = Sy Then zSy += 1
      177. If Segment(i) = " " Then
      178. z_ += 1
      179. selSeg = i
      180. End If
      181. Next
      182. 'Wenn zwei gleich belegte und ein leeres Feld vorhanden sind...
      183. If zSy = 2 And z_ = 1 Then
      184. Select Case selSeg
      185. '...wird das leere Feld belegt
      186. Case 0
      187. Belegen("O", Felder(I1, I2))
      188. O_gesetzt = True
      189. Case 1
      190. Belegen("O", Felder(I3, I4))
      191. O_gesetzt = True
      192. Case 2
      193. Belegen("O", Felder(I5, I6))
      194. O_gesetzt = True
      195. End Select
      196. End If
      197. End Sub
      198. 'Hinweis: Das Spielfeld ist Indexmäßig so aufgebaut
      199. '0/0, 0/1, 0/2
      200. '1/0, 1/1, 1/2
      201. '2/0. 2/1, 2/2
      202. ' Buttons des Spielfelds
      203. 'Erst Belegen, dann den Computergegner aufrufen, damit er sein O setzt
      204. Private Sub FeldButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
      205. Handles btnFeld00.Click, btnFeld01.Click, btnFeld02.Click, btnFeld10.Click, _
      206. btnFeld11.Click, btnFeld12.Click, btnFeld20.Click, btnFeld21.Click, btnFeld22.Click
      207. Belegen("X", CType(sender, Button))
      208. If CheckWin("X") Then
      209. Sieg("X")
      210. Exit Sub
      211. End If
      212. If Zug < 9 Then : Computergegner()
      213. Else : Unentschieden()
      214. End If
      215. End Sub
      216. 'Reset Button
      217. Private Sub btnNaechsteRunde_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNaechsteRunde.Click
      218. Reset()
      219. 'Reset-Knopf verbergenbtnReset.Visible = False
      220. 'Die Runde um 1 erhöhen
      221. lblsRunde.Text += 1
      222. End Sub
      223. 'Menü
      224. Private Sub tmrZeit_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tmrZeit.Tick
      225. lblsDate.Text = System.DateTime.Now
      226. End Sub
      227. Sub Reset()
      228. Dim ze, sp As Byte
      229. 'Runde und Zug
      230. lblsZugZahl.Text = "1"
      231. Zug = 1
      232. For ze = 0 To 2
      233. For sp = 0 To 2
      234. With Felder(ze, sp)
      235. .Text = " "
      236. .Enabled = True
      237. End With
      238. Next
      239. Next
      240. Zug1 = ComputerZug.Keiner
      241. End Sub
      242. 'Einen übergeben Button mit einem übergebenen Symbol belegen
      243. Sub Belegen(ByVal Sp As Char, ByRef Feld As Button)
      244. Feld.Text = Sp
      245. Feld.Enabled = False
      246. lblsZugZahl.Text += 1
      247. Zug += 1
      248. End Sub
      249. 'Wenn das Spiel Unentschieden Endet
      250. Sub Unentschieden()
      251. MessageBox.Show("Unentschieden", "Unentschieden")
      252. btnNaechsteRunde.Visible= True
      253. End Sub
      254. Private Sub btnNeuesSpiel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNeuesSpiel.Click
      255. Reset()
      256. lblsRunde.Text = 1
      257. End Sub
      258. Private Sub Hintergrund(ByVal sender As Object, ByVal e as EventArgs) Handles btnHintergrund.Click
      259. If FarbenColorDialog.ShowDialog = Windows.Forms.DialogResult.OK Then
      260. Me.BackColor = FarbenColorDialog.Color
      261. btnNaechsteRunde.BackColor = FarbenColorDialog.Color
      262. End If
      263. End Sub
      264. 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 :D

      Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „VB_Gamer“ ()

      @Pes1899.vb

      Weiß nicht, wieso es manchmal nicht reagiert. ?(

      Das man gegen es nicht gewinnen kann, ist falsch. Ich hab mal durch Zufall gegen es gewonnen. 2x. Wenn es das O zufällig setzt (siehe Code), hast du ne Chance.

      @alex2009

      Was meinst du mit Label-System? Was verstehst du nicht?
      Was meinst du mit Credits?

      powachill schrieb:

      Ich habe ständig das problem, dass ich nicht weiß welches Feld welches Feld ist usw.
      Sind die Namen nicht verständlich genug? Die Auflistung der Buttons ist wie folgt:

      (00) (01) (02)
      (10) (11) (12)
      (20) (21) (22)

      Mir ist natürlich sehr daran gelegen, dass alle, die das hier lesen, es auch kapieren. Sag mir aber genauer, was du meinst.

      EDIT: Code geändert: Button_Click-Events zu einem zusammengefasst, Combobox durch Button mit ColorDialog ersetzt. Kleinere Änderungen (Sub win() -> Function CheckWin(), Unentschieden-Abprüfung entfernt, ab jetzt ist dann unentschieden, wenn der Zug > 9 ist).

      Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „VB_Gamer“ ()