Tic Tac Toe - mein allererstes Vb.Net Programm

    • Release
    • Open Source

    Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von DerSmurf.

      Tic Tac Toe - mein allererstes Vb.Net Programm

      Hallo Leute
      Nach einiger Zeit VBA Excel Programmierung, habe ich nun mein allererstes Vb.Net Programm erstellt.
      Ein einfaches Tic Tac Toe Spiel. Ich habe versucht (unnötige) Basics mit einfließen zu lassen, wie z.B. das Laden einer zweiten Form, mehrere Timer, um dies einfach mal gemacht zu haben.
      Ich würde mich über eine Bewertung des Codes sehr freuen.
      Da ich vorhabe mein VBA Programm mit mehreren 10.000 Zeilen Code in Vb.Net umzusetzen, ist mir auch ein sauberer Programmierstil sehr wichtig, hier freue ich mich natürlich auch über eure Kritik.
      Aber bitte denkt dran - meine VBA Kentnisse sind gut, meine Vb.Net Kentnisse, sowie das Programmieren mit einer grafischen Oberfläche, sind gleich null.
      Natürlich gibt es auch ein paar Fragen, welche sich mir nicht durch google beantworten ließen, aber schaut erstmal.

      Name:
      Tic Tac Toe (Net Framework 4.6.1)

      Beschreibung:
      einfaches Tic Tac Toe Spiel, mit ein paar unnötigen Funktionen, wie z.B. autmoatischem Neustart des Spiels nach Ende und Anzeigen des Gewinners in einer zweiten Form.
      Das ganze ohne KI

      Verwendete Programmiersprache(n) und IDE(s):
      Visual Basic.Net / Visual Studio Community 2017
      Dateien
      • Tic Tac Toe.zip

        (633,11 kB, 25 mal heruntergeladen, zuletzt: )
      Hier mal ein paar Sachen die mir aufgefallen sind:
      1. Vor hochladen ins Forum, bitte auf Debug und Release mal "Bereiningen". Dadurch sollten sämtliche ausführbaren Dateien verschwinden.
      2. ClickOnce? Wofür? Sofern du das nicht in einem Netzwerk oder tatsächlich per FTP verteilen möchtest, ist das ziemlich unnötig.(Auf was für einem Surface arbeitest du denn? ;) )
      3. Anstatt CStr() kannst du bei absolut allen Objekten in .NET .ToString aufrufen.
      4. Anstatt CInt benutzt du Integer.Parse() oder, falls du nicht sichergehen kannst, dass sich nur zahlen in einem String befinden, benutzt du Integer.TryParse(). Gilt für alle Zahlentypen in .NET
      5. Anstatt CChar kannst du Chars auch so schreiben: "X"c
      6. Trennung von Daten und GUI. Anstatt die Labels als "Datenfeld" zu benutzen, überlegst du dir, wie du das Spielfeld in einer Klasse abbilden kannst. Beim Start eines neuen Spiels initialisierst du dann eine neues Objekt der Klasse, und lässt deine Buttons dieses Objekt manipulieren, und dann das Ergebnis anzeigen. Für die Statistik ganz ähnlich. Das mag zwar Overkill für dieses Projekt sein, doch gerade weil es so einfach ist, lässt sich das hier ganz gut lernen denke ich.
      7. Option Strict On in den Einstellungen vorgefunden :thumbup: . Lass dich niemals dazu überreden es anders zu machen. Option Strict On ist absolut unverzichtbar für die korrekte Entwicklung mit VB.NET
      Post-AGB:
      §1 Mit dem Lesen dieses Posts stimmst du den AGB unverzüglich zu
      §2 Ein Widerruf muss innerhalb von 3 Sekunden nach Lesen des Hauptbestandteil des ersten jemals gelesenen Posts erfolgen
      Abs.1 Die Signatur zählt nicht zum Hauptbestandteil des Posts
      §3 Ein erfolgreicher Widerruf zwingt zu einem Besuch bei einem Hypnotiseur oder Neurochirurg, sodass der gelesene Text aus den Erinnerungen entfernt werden kann
      Abs.1 Die Kosten und Risiken sind jeweils selbst zu tragen

      VB.NET-Quellcode

      1. With Form2
      2. '...
      3. Form2.Show()
      -> Dialoge richtig instanziieren
      • Du arbeitest ohne Verwendung des VB6-Namespaces. Gut! Für zukünftige Programme am besten auch die Verweise und importierte Namespaces bereinigen: Projekteigenschaften -> Verweise
      • My.Settings.Save() im FormClosing-EventHandler brauchst Du nicht, da bei Projekteigenschaften -> Anwendung bereits ein Haken bei "My.Settings beim Herunterfahren speichern" steht
      • schau auch mal hier rein: Der Unterschied zwischen And und AndAlso/Or und OrElse
      • intZugzaehler - Hungarian notation ist obsolet, aber Deine Entscheidung

      VB.NET-Quellcode

      1. Dim Button As Button
      2. For Each Button In Me.PnlSpielfeld.Controls.OfType(Of Button)

      Die 1. Zeile kann weg, VS deklariert Button selber in der For-Each-Schleife.
      Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

      Häufig von mir verwendete Abkürzungen: CEs = control elements (Labels, Buttons, DGVs, ...) und tDS (typisiertes DataSet)
      Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht in den Spekulatiusmodus gehen.
      Hallo Earan, Hallo VaporiZed, erstmal vielen Dank fürs angucken :o)
      Ich gehe mal systematisch durch, denn was euch auffällt, kann ich größtenteils nur mit Gegenfragen beantworten.

      Zu 1. und 2.

      EaranMaleasi schrieb:

      2.ClickOnce? Wofür? Sofern du das nicht in einem Netzwerk oder tatsächlich
      per FTP verteilen möchtest, ist das ziemlich unnötig.(Auf was für einem
      Surface arbeitest du denn? )

      Also was click Once ist, habe ich mir ergooglet. ABer ich kann mich nicht erinnern soetwas (absichtlich) integriert zu haben.
      Allerdings verstehe ich das ganze bereitstellen eh noch nicht so 100%ig (aber ich weiß jetzt hochladen ins Forum ohne Exe)
      Ich nutze ein Surface Pro 4

      Zu 3. / 4./ 5.
      CStr - .Tostring / CInt - .Integer(TryParse)

      CChar - "X"c
      Wenn ich dich jetzt richtig verstanden habe ist "X"c und CChar("x") das gleiche, nur in einer anderen Schreibweise.
      Es ist also wurscht welche ich nehme (in Zukunft dann aber natürlich die Kürzere).
      Aber warum das überhaupt? Char ist doch ein String aus einem Zeichen, warum kann ich dies nicht mit einem String befüllen? (also nur Cchar="x")
      Cstr - .ToString und Cint .-(Try)Parse
      Hierbei handelt es sich um zwei verschiedene Funktionen? ich nutze Cstr wegen meiner VBA Kentnisse, aber in allen VB.Net Tutorials sehe ich .tostring. Gibt es hier Vor- /Nachteile, oder eine Konvention, was benutzt werden sollte?

      6. uff / aber eigentlich hast du recht. Von Anfang an sauber programmieren... ich mach mich mal ran, wenn sonst soweit alles geklärt ist

      7. ist gemerkt (meckert echt oft und zwingt mich zum googlen - also nebenbei auch noch perfekt zum lernen)

      @Vaporized: erstmal danke für die Links :o)
      1. Namespaces: kein VB6 Namespace ist zufall (hab nix umgestellt)An Verweise habe ich mich noch nicht rangetraut, weil ich keinen Plan habe was ich brauche und was nicht. Aber prinzipiell gilt wohl, alle was nicht benötigt wird, muss weg?

      2. My.Settings.Save OK, welche Methode ist denn sauberer? Speichern über die GUI, oder über den Code?

      3. Hungarian Notation: In VBA fand ich es sehr angenehm, zu wissen, bzw. direkt zu sehen, welcher Datentyp dahinter steckt.
      Ist dies in VB.Net nicht üblich?

      DerSmurf schrieb:

      Wenn ich dich jetzt richtig verstanden habe ist "X"c und CChar("x") das gleiche, nur in einer anderen Schreibweise.
      Hab gerade noch mal nachgesehen, CChar und ""c machen hinterher keinen Unterschied. Ich hatte da die Befürchtung, dass CChar tatsächlich zu einem Funktionsaufruf führen würde.

      DerSmurf schrieb:

      ich nutze Cstr wegen meiner VBA Kentnisse
      Und genau dafür ist es auch da, um Leuten aus VB6, VBA usw. den Umstieg zu erleichtern. Doch CStr, CInt usw. machen eben was sie für richtrig halten, hier ein Konkretes Beispiel:

      VB.NET-Quellcode

      1. System.Diagnostics.Debug.WriteLine(CInt("123.1567"))
      2. System.Diagnostics.Debug.WriteLine(Integer.Parse("123.1567"))

      Rate was nacher in der Ausgabe steht, und schau dir dann die Lösung an:
      Spoiler anzeigen

      Bei CInt wird einfach das Dezimaltrennzeichen entfernt. Es steht 1231567 in der Ausgabe
      Integer.Parse wirft eine FormatException. Es hat erkannt, dass es sich um einen double handelt und weißt den Programmierer auf diesen Fehler hin


      DerSmurf schrieb:

      Char ist doch ein String aus einem Zeichen, warum kann ich dies nicht mit einem String befüllen?
      Falsch, in der .NET Welt ist ein String kein "einfacher" Datentyp wie Integer oder Boolean. Dahinter versteckt sich tatsächlich ein Array aus Chars. Viel Interessanter ist aber vielleicht auch, das Char an und für sich eigentlich sogar ein Zahlentyp ist, der lediglich die Darstellung der Zahl als Unicode-Buchstabe(UTF16) erlaubt.

      DerSmurf schrieb:

      3. Hungarian Notation: In VBA fand ich es sehr angenehm, zu wissen, bzw. direkt zu sehen, welcher Datentyp dahinter steckt.
      Ist dies in VB.Net nicht üblich?
      Dank der Einführung einer Supermächtigen IDE wie VisualStudio und Intellisense, kannst du über jede Variable mit der Maus hovern (egal wo sie auftaucht) und bekommst jederzeit angezeigt, von welchem Typ sie ist, und welchen Zugriffsmodifizierer (Private, Shared, etc.) sie hat. Bei Konstanten siehst du sogar den zugewiesenen Wert. Dasselbe gilt für den fall in dem du einfach lostippst. VS zeigt dir dann Vorschläge, und wird dir bei deinen Variablen ebenfalls den Typ mitanzeigen. Auch XML Kommentare (Drei Hochkommas :''') werden dir dann von IntelliSense angezeigt.

      Es gibt aber auch Fälle in denen die Notation noch sinnvoll ist. Benennung von Controls.
      Beispiel:
      btnAnlage, txtAnlage und lbAnlage, erlauben es dir 3 Controls um dasselbe "Objekt" herum zu bauen, in diesem Fall die Anlage, ohne dass man mit den Namen Kreativ werden muss. Man weiß wo sie hingehören, man weis welches Control dahinter ist, und findet so auch beim drauflostippen schnell das richtige Control.
      Post-AGB:
      §1 Mit dem Lesen dieses Posts stimmst du den AGB unverzüglich zu
      §2 Ein Widerruf muss innerhalb von 3 Sekunden nach Lesen des Hauptbestandteil des ersten jemals gelesenen Posts erfolgen
      Abs.1 Die Signatur zählt nicht zum Hauptbestandteil des Posts
      §3 Ein erfolgreicher Widerruf zwingt zu einem Besuch bei einem Hypnotiseur oder Neurochirurg, sodass der gelesene Text aus den Erinnerungen entfernt werden kann
      Abs.1 Die Kosten und Risiken sind jeweils selbst zu tragen

      DerSmurf schrieb:

      Namespaces: kein VB6 Namespace ist zufall (hab nix umgestellt)An Verweise habe ich mich noch nicht rangetraut, weil ich keinen Plan habe was ich brauche und was nicht. Aber prinzipiell gilt wohl, alle was nicht benötigt wird, muss weg?
      Achtung! Der Unterschied zwischen Verweisen und importierte Namespaces: Importierte Namespaces machen das Schreiben kürzer. Wenn Du den System.Threading-Namespace importierst, also einbindest, musst Du nicht mehr vollqualifiziert schreiben System.Threading.Thread.Sleep(1000), sondern kannst kürzen auf Thread.Sleep(1000). Ein Verweis bindet eine andere Datei in Dein Projekt ein und erweitert die Funktionalität. So kannst Du auf Excel zugreifen, indem Du die passende DLL einbindest. Ohne diesen DLL-Verweis kann Dein Programm nix mit Excel anfangen.
      Aber wichtig für den Anfang: bei den Importierten Namespaces den Microsoft.VisualBasic-Namespace rausnehmen, also Haken wegmachen.

      DerSmurf schrieb:

      My.Settings.Save OK, welche Methode ist denn sauberer? Speichern über die GUI, oder über den Code?
      Sauberer ist schwierig zu sagen. Wenn Du weißt, dass es passiert, dann ist die in-den-Projekteigenschaften-Häkchen-setzen-Methode besser, da weniger Code in Deinem eigentlichen Programm auftaucht. Wenn Dir das aber suspekt ist oder Du gezielte Kontrolle darüber haben willst, nimm die Codevariante.
      Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

      Häufig von mir verwendete Abkürzungen: CEs = control elements (Labels, Buttons, DGVs, ...) und tDS (typisiertes DataSet)
      Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht in den Spekulatiusmodus gehen.
      Guten Morgen ihr beiden
      Gestern Abend habe ich mir die Links zu Gemüte geführt und eure Tipps soweit umgesetzt.
      • CChar ("x") heißt jetzt "x"c
      • Cint und Cstr, wurden durch Integer.Parse und .ToString ersetzt
      • alle And Verknüpfungen wurden durch AndAlso ersetzt
      • speichern von My.Settins aus dem Code entfernt
      Hier nun meine Fragen:
      1. Code zum anzeigen der zweiten Form
      Spoiler anzeigen
      Den Code zum Anzeigen der zweiten Form würde ich wie folgt ändern (da bin ich mir aber nicht sicher, ob das so korrekt / gut ist)

      Quellcode

      1. 'alt
      2. 'With Form2
      3. '.LblGewinner1.Text = "O"
      4. '.LblGewinner1.ForeColor = Color.DarkGreen
      5. '.LblGewinner2.Text = "gewinnt"
      6. 'End With
      7. 'neu
      8. Dim frm as New Form2
      9. With frm
      10. '.LblGewinner1.Text = "O"
      11. '.LblGewinner1.ForeColor = Color.DarkGreen
      12. '.LblGewinner2.Text = "gewinnt"
      13. .Show(Me)
      14. End with
      15. [/spoiler][spoiler]

      So ist das dann sauberer, weil ich nicht auf die Form selber zugreife, sondern vorher eine neue Klasse davon instanziere? (stimmt das so? - ich hab den Sinn dahinternoch nicht ganz verstanden)
      Wie verhält es sich denn, wenn ich in der Form nichts ändere, sondern diese nur anzeige?
      Empfiehlt es sich dann auch

      Quellcode

      1. Form2. show

      durch

      Quellcode

      1. Dim frm as New Form2
      2. frm.Show(me)

      zu ersetzen?


      2. Der Microsoft.VisualBasic-Namespace
      Spoiler anzeigen
      Wofü ist dieser Namespace gut und warum empfiehlt es sich, diesen zu entfernen? Ich konnte leider nichts finden, dass mit weiterhilft.


      3. Die Dateien in der Projektmappe
      Spoiler anzeigen
      Wenn ich mir meine Projektmappe anschaue, finde ich folgende Ordnerstruktur:
      /bin/Debug <-- hier finde ich eine lauffähige Exe meines Programmes
      /bin/Release
      /MyProject
      /obj/Debug/ <-- hier finde ich auch eine lauffähige Exe meines Programmes, aber mit sehr viel mehr Dateien drumherum
      Wenn mein Projekt nun fertig ist (und ich keinen installer brauche / möchte), welchen Ordner nehme ich dann?
      Oder empfiehlt es sich immer einen Installer zu erstellen?
      Also wie ist das allgemeine vorgehen, wenn mein Code fertig ist?


      4. For Schleife und Variablendeklaration
      Spoiler anzeigen
      Nachdem Vaporized geschrieben hat, dass Visual Studio die Variable einer For Schleife automatisch deklariert, habe ich ausprobiert, dass auch

      Quellcode

      1. Sub Test()
      2. For i = 1 to 2
      3. msgbox (i).tostring
      4. Next
      5. End Sub

      Funktioniert auch, ist aber wahrscheinlich ja nicht so sinnvoll.
      Gibt es hier einen Tipp, wann ich deklariere und wann nicht?


      Edit1: bisschen grammatik
      Edit2: Frage4 hinzugefügt

      Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „DerSmurf“ ()

      Zu 1.: Ja, absolut. Der Punkt ist, dass Form2.Show eigentlich überhaupt keinen Sinn ergibt, da Form2 eine Klasse ist, also ein Bauplan. Und z.B. in einen Autobauplan kann man schlecht einsteigen und damit irgendwo hinfahren. Etwas detaillierter gehe ich in einem eigenen Thread darauf ein: Warum »Form1.Show« und Co. einem irgendwann ins Bein schießen
      Zu 2.: Er ermöglicht Abwärtskompatibilität zu alten Programmen, die man noch in VB6 geschrieben hat. Es sind also Altfunktionen enthalten, die man aber heutzutage durch .Net-Varianten ersetzt: Böses aus VB6 und ihre .Net-Alternativen
      Zu 3.: Du nimmst normalerweise am Ende nur die EXE-, ggf. die DLL- und ggf. von Deinem Programm zusätzlich benötige Dateien* aus dem BIN/DEBUG-Ordner. * Benötigte Dateien sind solche, die Du ganz bewusst erstellst oder in Deinem Projekt einbindest: Bilder, Datenbankdateien, tDS-XML-Dateien (fortgeschrittenes Thema) usw.
      Zu 4.: Warum solltest Du bei einer For-Schleife eine Variable vorausdeklarieren, wenn sie eh nur innerhalb der Schleife verwendet wird. Wenn Du sie aber außerhalb der Schleife noch brauchst, dann deklarier sie vorher. Aber meistens (nicht immer!) ist da ein Anfänger-Designfehler versteckt und man kann das Problem auch ohne Vorabdeklaration lösen. Fazit: Erstmal ohne Vorabdeklaration. Erst wenn die Variable auch außerhalb der Schleife (weiter)verwendet wird, dann Vorabdeklaration.
      Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

      Häufig von mir verwendete Abkürzungen: CEs = control elements (Labels, Buttons, DGVs, ...) und tDS (typisiertes DataSet)
      Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht in den Spekulatiusmodus gehen.