Einzelnen Beitrag anzeigen

oki

Registriert seit: 30. Dez 2002
Ort: Brandshagen
1.819 Beiträge
 
Delphi 2007 Professional
 
#29

Re: Neue Komponente mit 2 TEdit Komponenten

  Alt 5. Jun 2009, 08:45
Hallo,
ich sehe das mit der Auswertung nicht so problematisch. Sobald ein Ergebnis in eingegeben wird ist ja klar, wer gewonnen hat. Somit ist auch gleich eindeutig, in welchem Feld (G, V usw.) der entsprechende Spieler eingetragen wird. Auch die Numerik für das entsprechende Spiel ist logisch nachvollziehbar, unabhängig von der Anzahl der Spieller und Runden. So gehen z.B. die Gewinner der Runde R1-1 und R1-2 in die Runde G1-1, aus R1-3 und R1-4 in G1-2 usw. Das ist imho wieder eine 2 zu 1 Beziehung in einer weiteren Ebene. Diese Gewinner gehen in G2-1 auf(Gewinner aus G1-1 und G1-2 nach G2-1). Wieder eine 2 zu 1 Beziehung. Der Vorteil ist sogar, dass somit ein relativ einfaches mathematisches Prinzip abgebildet werden kann. Und das gilt dann eigentlich sehr universell. Aus zwei mach eins eine Ebenen höher. Rieht ganz deutlich nach einer universellen Funktion mit einem simplen Vergleich und Inkrementieren der Spielebene.

Wenn man das im Griff hat, kann man die Ermittlung des neuen Eintragfeldes für einen Spieler recht universell über eine Funktion ermitteln, bei der man die Aktuelle Runde, beide Spielpartner und den Spielstand übergiblt. Zurück bekommt man die Bezeichner der Felder, in die die Spieler neu einzutragen sind.

Für die Übersicht des aktuellen Standes würde ich über die Spieler und die Spielerliste gehen. Dazu würde ich noch eine zusätzliche Liste der Spiele anlegen. Das in etwa so:
Delphi-Quellcode:
  TPlayResult : TPoint; // TPoint zweckentfremden für Spielstand oder gleich eigener Typ
  // Vorward-Declaration
  TPlayerClass : class;

  TPlayClass = class(TObject)
  private
    FPlayResult : TPlayResult;
    FPlayer1: TPlayerClass;
    FPlayer2: TPlayerClass;
    FRound : String;
  ....
  end;
  
  // Liste der durchgeführten Spiele jedes Spielers
  TPlayList = class(TObjectList)
  ...
  end;

  TPlayerClass = class(TObject);
  private
    FParentList : TPlayList;
    FPlayerName : String;
    ....
    FPlayList : TPlayList;
    FPosition : Integer; // aktueller Platz des Spielers im Turnier
    ...
  end;

  // Liste aller Spieler
  TPlayerList = class(TObjectList)
  private
    FParentControl : TMyControl;
  ....
  end;
Jetzt hast du folgende Möglichkeiten. Deine neues Control hat die Eigenschaften PlayerList. Wird PlayerList verändert, so kann dein Control aus dem Member Count der PlayerList den Spielaufbau generieren. Alle weiteren Eigenschaften wie zufällige Spielpaarzusammenstellung usw. lassen wir mal außer acht. Das ist Finetuning und berührt die generelle Funktion der Komponente nicht.
Über das Programm kannst du die Bearbeitung der PlayerListe incl. des einzelnen Players steuern. Ähnlich, als ob du mit einer Datenbank arbeitest. Durch die Zuweisung, Änderung reagiert deine Komponente. Willst du das automatisieren, so erhält deine PlayerList noch einen Member ParentControl. Der kann dann vom Typ deiner Komponente sein. Ist dieser Member ungleich nil, so informiert die PlayerListe automatisch das ParentControl über Änderungen, damit diese sich in der Ansicht aktualisieren kann. Das gleiche kannst du natürlich auch mit der PlayerClass machen. Der Witz währe folgender.
Mitten im Spiel bemerkt ein Spieler, dass seine Name Falsch eingetragen ist. Du änderst über die Eingabemaske den Namen in seinem zugehörigen Klassenobjekt TPlayerClass. Der Setter für den Namen ruft eine eigene Methode ChangePlayer der PlayerList auf, die ja als Member in TParentList abgelegt ist. Diese wiederum ruft die eigene Methode Change der ParentComponent auf. Die Parent Component zeichnet sich damit neu. Dabei macht es dann Sinn, wenn die Edits zusätzlich einen Member der Player haben, denen das entprechende Player-Object zugewiesen wurde. Du trägst also nicht den Namen des Spielers ein, sondern weist einen zu. Der Name wird beim zeichnen also aus der Eigenschaft PlayerName des PlayerObjectes eingetragen. Durch die Methode Change wird ja die Componente neu gezeichnet. Der Name in PlayerName des Edits hat sich in der Zwischenzeit geändert und somit neu gezeichnet.
Alles automatisch, keiner rekursiven Funktionen nötig, ändern an der Stelle wo man ändern muss, neu zeichnen und alles fertig und up to date. Großer Zauber Manitu.

Hast du in den Edits die neuen Spielstände eingetragen, so wird über die EditChange-Methode die oben beschriebene Auswertefunktion angestoßen. Ein Object der TPlayClass wird erstellt, dem Player zugewiesen, den neuen Eintragsfeldern (Edits) das richtige Playerobject zugewiesen, refresh (Change deiner Komponente) fertig.

Aktuelle Listen für Spielstand, Platz jedes Spielers usw. implementierst du als Funktionen deiner PlayerList, die du über das Hauptprogramm aufrufst und das entsprechende Ergebnis von der Funktion zurück bekommst.

Im Prinzip passiert hier folgendes. Du hast:
- Datenklassen wie TPlayClass, TPlayList (Spiel, Spielliste), TPlayerClass, TPlayerList (Spieler, Spielerliste).
- Visualisierungsklassen -> deine Komponente
- Ein-/Ausgabeklassen; deine Komponente für Spielstände, Eingabemaske für die Spieler
- GUI; Hauptprogramm, auf dem die visuellen Komponenten platziert sowie die Menüs und Buttons für die Spielsteuerung und Einstellungen platziert sind.

Joo, so würde ich es in etwa machen. Das Thema mit den PlayClass ist mir noch nicht ganz sauber. Finde im Moment aber keinen Ansatz das zu vereinfachen oder zu zentralisieren. Ich habe den Eindruck, man muss das über die PlayList aufziehen und denen die Player zuweisen und nicht umgekehrt. Kann man ja noch drüber nachdenken. Aber ich glaube so ist es richtig.

Gruß oki
42
  Mit Zitat antworten Zitat