Spieler mit verschiedenen Eigenschaften

  • VB.NET

Es gibt 18 Antworten in diesem Thema. Der letzte Beitrag () ist von Mangafreak1995.

    Spieler mit verschiedenen Eigenschaften

    Hallo,

    habe folgendes Problem:

    Für ein Managerspiel benötige ich eine Spielerdatenbank, in denen Namen, Vereinszugehörigkeit, Stärke, Alter ... festgehalten sind. Während des Spiels muss die Möglichkeit bestehen, neue Spieler dort hinzuzufügen. Wenn ich die OOP korrekt verstanden habe (was mir leider schwer fällt, vielleicht habt Ihr nen guten Literaturtip als Einstieg?), kann ich dies am besten über Klassen erreichen. Seht Ihr das auch so oder gibt es da eine elegantere Möglichkeit?

    Ich habe also über Neues Element hinzufügen eine neue Klasse erstellt. Da ich ja eine ganze Reihe an Spielern brauche, eine Liste erstellt. Habe dann erstmal 2 Eigenschaften der Spieler definiert, Spielstärke und Name.

    VB.NET-Quellcode

    1. Public Class Spieler
    2. Dim listespieler As List(Of Spieler)
    3. Dim staerke As Integer
    4. Dim name As String
    5. End Class


    Jetzt möchte ich in anderen Formen darauf zugreifen können, z.B. neue Spieler hinzufügen, Spielergebnisse mittels dieser Daten ermitteln, ... In einer Form (ein Unterpunkt des Spiels, in dem man seine Spieler verwalten kann) habe ich versucht, mittels Button einen Spieler hinzuzufügen. Leider kann VB mit meinem Begriff aktuellerspieler.staerke bzw. aktuellerspieler.name nichts anfangen. Was habe ich falsch gemacht? Wie kann ich es stattdessen machen?

    VB.NET-Quellcode

    1. Public Class MenuSpieler
    2. Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
    3. Dim aktuellerspieler As New Spieler
    4. aktuellerspieler.staerke = 10
    5. aktuellerspieler.name = "xxx"
    6. listespieler.Add(aktuellerspieler)
    7. End Sub
    8. End Class


    Thx in advance
    ole
    Du solltest die Stärke, und Name ebenfalls mit Public deklarieren. Ansonsten sind diese Variablen nur innerhalb der Klasse Spieler ansprechbar.

    VB.NET-Quellcode

    1. Public Class Spieler
    2. Public listespieler As List(Of Spieler)
    3. Public staerke As Integer
    4. Public name As String
    5. End Class

    der_Kurt schrieb:

    Du solltest die Stärke, und Name ebenfalls mit Public deklarieren. Ansonsten sind diese Variablen nur innerhalb der Klasse Spieler ansprechbar.

    Noch eine winzichkleinste Ergänzung: was hat die Liste aller Spieler so in Deiner Spielerklasse zu suchen ? Damit würdest Du ja in jeder Instanz den Spieler in seiner eigenen Liste haben und nur da ?

    Wenn dann bitte als Shared deklarieren, die ist dann nur einmal für alle Spieler da und bei allen identisch. Vielleicht solltest Du auch solche Properties wie Staerke und Name gleich beim Constructor mitgeben ?

    VB.NET-Quellcode

    1. Public Class Spieler
    2. Public Sub New(ByVal name As String, ByVal staerke As Integer)
    3. Me.name = name : Me.staerke = staerke
    4. ' evtl auch gleich in die Liste eintragen ?
    5. listespieler.Add(Me)
    6. End Sub
    7. Public Shared listespieler As New List(Of Spieler)
    8. Public staerke As Integer
    9. Public name As String
    10. End Class
    Vielen Dank schon mal für Deine erste Antwort, Kurt. Habe die Einträge so geändert und dann hat er die beiden Eigenschaften so angenommen. Das mit der Liste hat so aber nicht geklappt, sondern erst, als ich es in der MenuSpieler-Form statt in der Klasse deklariert habe.

    VB.NET-Quellcode

    1. Public Class MenuSpieler
    2. Public listespieler As New List(Of Spieler)
    3. Dim aktuellerspieler As New Spieler
    4. Dim i As Integer
    5. Public Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
    6. aktuellerspieler.staerke = 10 + i
    7. aktuellerspieler.name = "xxx"
    8. i = i + 1
    9. Label2.Text = aktuellerspieler.name
    10. Label3.Text = aktuellerspieler.staerke
    11. listespieler.Add(aktuellerspieler)
    12. End Sub
    13. End Class


    Er gibt mir jetzt zwar immer den letzten eingegebenen Spieler zurück, aber wie kann ich sicherstellen, dass er die alle in der Liste gespeichert hat? Kann ich mir die Liste in Textform wiedergeben lassen? Und vor allem, wie kann ich die einzelnen Spieler jetzt aufrufen. Nehmen wir an, ich wolle Spieler(3) jetzt einen Stärkepunkt hinzufügen, wie kann ich diesen ansteuern?

    Dir auch vielen Dank, Kangooroo. Das mit dem Public Shared hatte ich vergessen. Das mit dem Konstruktor ist Bonus, wenn ich das richtig verstanden habe, oder?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ole1er“ ()

    Vielen Dank.

    Unterdessen habe ich noch ein wenig nachgelesen in dem EBook "Visual Basic 2008" von Löffelmann. Ich dachte, einiges verstanden zu haben und habe meinen Plan, das über "List of" zu regeln dahingehend geändert, dass ich Klassen-Arrays verwenden möchte.

    Allerdings bin ich in meinem Optimismus bereits unmittelbar von VB gedämpft worden. Könntet Ihr mir erklären, warum?

    Meine Klasse beinhaltet nun Folgendes:

    VB.NET-Quellcode

    1. Public Class Spieler
    2. Private myStaerke As Integer
    3. Public Property Staerke() As Integer
    4. Get
    5. Return myStaerke
    6. End Get
    7. Set(ByVal value As Integer)
    8. myStaerke = value
    9. End Set
    10. End Property
    11. Private myName As String
    12. Public Property Name() As String
    13. Get
    14. Return myName
    15. End Get
    16. Set(ByVal value As String)
    17. myName = value
    18. End Set
    19. End Property
    20. End Class


    In meiner Form lautet es dann wie folgt. Hier erhalte ich dann einen NULL-Exception-Fehler.

    VB.NET-Quellcode

    1. Public Class MenuVerein
    2. Public Player(10000) As Spieler
    3. Public PZ As Integer = 0
    4. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    5. Player(PZ).Name = "Alfred Adler" & PZ
    6. Player(PZ).Staerke = 1800
    7. Label1.Text = Player(PZ).Name
    8. PZ += 1
    9. End Sub
    10. End Class
    In der Sub muß vor dem Eintragen der Eigenschaften ein Objekt "Spieler" erzeugt werden. Schreibe also als erstes Player(PZ)=new Spieler.

    Dein Array reserviert zwar Speicher für 1000 Spieler, aber es existieren keine Objekte, auf die mit ihren Eigenschaften zugegriffen werden kann. Beim Debuggen kannst du sie dir ansehen: Nothing

    Schu dich ma Hier um. Insbesonders ist hierwas über Klassen beschrieben.
    Fiel Fergnügen
    Vatter
    :thumbsup: Seit 26.Mai 2012 Oppa! :thumbsup:
    Also ich denke, dass selbst die Verwendung einer Datenbank nicht darum herum führt, eine Klasse Spieler mit den entsprechenden Propertys zu erstellen. das verwalten der Spieler kann natürlich in einer Datenbank erfolgen (wenn es denn wirklich soooooo viele sind)
    Aber die Frage des TE zielte doch mehr in Richtung Klassendesign und objektorientierte Programmierung.
    :thumbsup: Seit 26.Mai 2012 Oppa! :thumbsup:

    Vatter schrieb:

    Also ich denke, dass selbst die Verwendung einer Datenbank nicht darum herum führt, eine Klasse Spieler mit den entsprechenden Propertys zu erstellen

    *lach* und /sign

    Ob man nun einen Hammer oder einen Stein zum Einschlagen nimmt ist vollkommen egal wenn man keine Nägel hat. Ausserdem kann man eine List( OF Spieler) mit einpaar Zeilen Code prima in eine XML-Datei serialisieren und wieder laden.

    ole1er schrieb:

    und habe meinen Plan, das über "List of" zu regeln dahingehend geändert, dass ich Klassen-Arrays verwenden möchte

    halte ich für falsch: in .NET nimmt man eher List(of Spieler) als ein Array, da es einfcher zu verwalten ist. Versuche mal einen Player wieder aus Deinem Array zu entfernen :wacko:

    ole1er schrieb:

    Public Property Name() As String

    Für mich sieht das sehr nach einem Array Name() as string aus, Staerke() genauso - bestimmt nicht ganz was Du wolltest ?

    Properties kann man auch so anlegen wenn man eh nix besonderes im Get/Set macht, eine extra Private Variable legt der Compiler für Dich automatisch an:

    VB.NET-Quellcode

    1. Public Property Name as string
    Habe es nun doch wieder über Listof realisiert und bin bislang sehr zufrieden damit und auch schon ein Stück weitergekommen.
    Allerdings funktioniert das Entfernen von Items der Liste noch nicht:

    VB.NET-Quellcode

    1. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    2. Dim l As Integer
    3. Dim counter As Integer
    4. counter = MenuVerein.Player.Count - 1
    5. For l = counter To 0
    6. If MenuVerein.Player(l).Name = "Spieler 2" Then
    7. MenuVerein.Player.RemoveAt(l)
    8. End If
    9. Next
    10. Label1.Text = MenuVerein.Player.Count
    11. End Sub


    Habe es alternativ mal mit MenuVerein.Player(l).Name = "Der " & MenuVerein.Player(l).Name versucht
    und das hat funktioniert, also der erkennt meinen "Spieler 2", aber will ihn leider nicht löschen...
    Deine Schleife zählt nicht rückwärts, es sei denn, du gibst noch Step -1 an. Da du aber eine variable Listenlänge hast solltest du lieber Foreach verwenden und nach dem löschen mit Exit For die Schleife verlassen.
    Es gibt aber noch eine elegante Möglichkeit der Spielerverwaltung: Sieh dir ma die Dictionary-Klasse an. Wenn du den Namen des Spielers als Key und die Klasse als Value verwendest, kannst du sehr einfach doppelte Spielernamen vermeiden. Und löschen geht direkt über den Namen (Dictionary.Remove(Name))
    :thumbsup: Seit 26.Mai 2012 Oppa! :thumbsup:
    Danke, das mit dem step -1 fehlte...

    Warum soll ich foreach vorziehen? Und wie müsste ich das in diesem Fall formulieren?
    for each menuverein.player in spieler
    klappt nicht...

    VielenDank auch für den Dictionary-Tip, aber mir geht es gar nicht primär darum, (doppelte) Namen zu löschen, sondern ich wollte generell das Procedere kennen lernen, auch um Spieler nach Beendigung der Laufbahn (z.B. ab nem bestimmten Alter) zu löschen.

    VB.NET-Quellcode

    1. For Each <name> As <Typ> In <Typ()> ' muss kein Array sein ... kann auch eine Collection oder eine List(Of <Typ>) sein
    2. ' was machst damit =?
    3. Next

    Mit For Each wird jedes Elemt unabhängig vom Index drangenommen
    mit Step wird die Richtung und die Anzahl bestimmt. Standard ist Step 1. Mit Step -1 zählst du runter und mit Step 2 kannst du jedes 2. überspringen.
    For Each erlaubt eh keine Änderungen am IEnumerable (was überigens genau das Inteface ist, was es tatsächlich ermöglicht eine For--Each zu benutzen.
    Demnach geht die vorgeschlagene Methode sowieso nicht.

    Bei einem Dictornary wäre das Löschen ein einzeiler:

    VB.NET-Quellcode

    1. Players.Remove(PlayerName)
    Mit For Each zu löschende Elemente in eine neue kopieren und die neue Liste dann mit For Each durchgehen und die Elemente aus der eigentlichen Löschen:
    ...und den Speicher damit unnötig zumüllen.
    manchmal ist For i = n To m Step k einfach besser.
    wenn, dann:

    VB.NET-Quellcode

    1. For i = 0 To el.Count - 1
    2. If Löschen(el(i)) Then idxs.Add(i)
    3. Next
    4. For k = idxs.count - 1 to 0 step -1
    5. el.removeat(idxs(k))
    6. next


    Dann haben wir nur einen Zahlenwert pro Element und nicht gleich eine ganze, unnötige, Klasse
    stimmt natürlich ^^'
    wo ihr grad so beim For Each wart war ich da auch grade.