Einzelnen Beitrag anzeigen

oki

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

Re: Neue Komponente mit 2 TEdit Komponenten

  Alt 7. Jun 2009, 11:03
Hi,

ich hab mal die Klassen für die Spieler, Spielerliste, Spiele und Spielliste fertig gestellt. Leider hab ich das System für den Eintrag eines Spielers in ein neues Spiel noch nicht ganz durchschaut. Für die Gewinner ist das ja recht einfach. Bei den Verlierern hab ich da so meine Probleme. Ich pack hier mal die Procedure rein.
Delphi-Quellcode:
procedure TPlayList.ChangePlay(APlayClass: TPlayClass; AProperty : String);
var AWinner, ALooser : TPlayerClass;

  procedure PlayerinGame(APlayer : TPlayerClass; AOldPlay : TPlayClass; winning : Boolean);
  var NewPlay : TPlayClass;
  begin
    if winning then begin
      // Spieler ist Gewinner des alten Spieles
      case ORD(AOldPlay.FGame) of
        ORD('R') : begin
          // Gewinner der ersten Runde
          if Odd(AOldPlay.Number) then begin
            NewPlay := GetPlay('G', 1, (AOldPlay.Number+1) div 2);
            if Assigned(NewPlay) then
              NewPlay.FPlayer1 := APlayer;
          end else begin
            NewPlay := GetPlay('G', 1, (AOldPlay.Number) div 2);
            if Assigned(NewPlay) then
              NewPlay.FPlayer2 := APlayer;
          end;
        end;
        ORD('G') : begin
          if Odd(AOldPlay.Number) then begin
            NewPlay := GetPlay('G', AOldPlay.FRound+1, (AOldPlay.FNumber+1) div 2);
            if Assigned(NewPlay) then begin
              NewPlay.FPlayer1 := APlayer;
            end else begin
              // das war das letzte Gewinnerspiel, ab ins Filale
              NewPlay := GetPlay('F', 0, 0);
              if Assigned(NewPlay) then
                NewPlay.Player1 := APlayer;
            end;
          end else begin
            NewPlay := GetPlay('G', AOldPlay.FRound+1, (AOldPlay.FNumber) div 2);
            if Assigned(NewPlay) then begin
              NewPlay.FPlayer2 := APlayer;
            end else begin
              // das war das letzte Gewinnerspiel, ab ins Filale
              NewPlay := GetPlay('F', 0, 0);
              if Assigned(NewPlay) then
                NewPlay.Player1 := APlayer;
            end;
          end;
        end;
        ORD('V') : begin
          NewPlay := GetPlay('V', AOldPlay.Round + 1, 1);
            if Assigned(NewPlay) then begin
              NewPlay.FPlayer1 := APlayer;
            end else begin
              // das war das letzte Gewinnerspiel, ab ins Filale
              NewPlay := GetPlay('F', 0, 0);
              if Assigned(NewPlay) then
                NewPlay.Player2 := APlayer;
            end;
        end;
      end;
    end else begin
      // Spieler ist Verlierer des alten Spieles
      case ORD(AOldPlay.FGame) of
        ORD('R') : begin
          // Gewinner der ersten Runde
          if Odd(AOldPlay.Number) then begin
            NewPlay := GetPlay('V', 1, (AOldPlay.Number+1) div 2);
            if Assigned(NewPlay) then
              NewPlay.FPlayer1 := APlayer;
          end else begin
            NewPlay := GetPlay('V', 1, (AOldPlay.Number) div 2);
            if Assigned(NewPlay) then
              NewPlay.FPlayer2 := APlayer;
          end;
        end;
        ORD('G') : begin
          // jo, da hab ich noch kein System entdeckt ???????????

        end;
        ORD('V') : begin
          // das wars dann, kein weiteres Spiel :-(
          // oder doch? :-) hab ich das System aber auch noch nicht durchschaut
        end;
      end;
    end;
  end;

begin
  // ein Spieler ist ein Freilos?
  if ((AProperty = 'Player1') or (AProperty = 'Player2')) and
     (Assigned(APlayClass.Player1) and Assigned(APlayClass.Player2)) and
     ((APlayClass.Player1.FPlayerType = pt_Looser) or (APlayClass.Player2.FPlayerType = pt_Looser)) then begin
    if APlayClass.Player1.FPlayerType = pt_Looser then begin
      // Player2 hat gewonnen
      AWinner := APlayClass.FPlayer2;
      ALooser := APlayClass.FPlayer1;
    end else begin
      // Player1 hat gewonnen
      AWinner := APlayClass.Player1;
      ALooser := APlayClass.Player2;
    end;
    // neues Spiel für Gewinner ermitteln
    PlayerinGame(AWinner, APlayClass, True);
    // neues Spiel für Verlierer ermitteln
    PlayerinGame(ALooser, APlayClass, False);

    // Counter der gespielten Spiele der Spieler erhöhen
    AWinner.PlayCount := AWinner.PlayCount + 1;
    ALooser.PlayCount := ALooser.PlayCount + 1;

    // aktuelle Platzierung der Spieler setzen
    AWinner.Position := FPlayerList.Count - AWinner.PlayCount;
    ALooser.Position := FPlayerList.Count - ALooser.PlayCount - 1;

    // Spielstatus auf beendet
    APlayClass.Status := ps_finish;
    Exit;
  end;

  // der Spielstand hat sich geändert
  if AProperty = 'PlayResultthen begin
    if (APlayClass.FPlayResult.Player1 <> 0) or (APlayClass.FPlayResult.Player2 <> 0) then begin
      // es gibt einen Spielstand <> 0
      if APlayClass.FPlayResult.Player1 > APlayClass.PlayResult.Player2 then begin
        // Player1 hat gewonnen
        AWinner := APlayClass.Player1;
        ALooser := APlayClass.Player2;
      end else begin
        // Player2 hat gewonnen
        AWinner := APlayClass.Player2;
        ALooser := APlayClass.Player1;
      end;
      // neues Spiel für Gewinner ermitteln
      PlayerinGame(AWinner, APlayClass, True);
      // neues Spiel für Verlierer ermitteln
      PlayerinGame(ALooser, APlayClass, False);

      // Counter der gespielten Spiele der Spieler erhöhen
      AWinner.PlayCount := AWinner.PlayCount + 1;
      ALooser.PlayCount := ALooser.PlayCount + 1;

      // aktuelle Platzierung der Spieler setzen
      AWinner.Position := FPlayerList.Count - AWinner.PlayCount;
      ALooser.Position := FPlayerList.Count - ALooser.PlayCount - 1;

      // Spielstatus auf beendet
      APlayClass.Status := ps_finish;
    end;
  end;
end;
Hier noch einige Bemerkungen zum Ablauf. Wird in einem Spiel ein Spielstand (oder eine andere Eigenschaft) geändert so ruft das Spiel die Procedure ChangePlay seiner PlayList auf und übergibt sich selbst sowie den Namen der Eigenschaft an die Procedure.
Die Procedure der PlayList macht jetzt folgendes. Erstens wird geschaut, ob der geänderte Parameter des Spiels der Spielstand oder der Typ des Spielers ist (Freilos bei Spieler). Ist ein gültiger Spielstand eingetragen, so wird der Gewinner und Verlierer des Spiels ermittelt. Dann werden diese an die Procedure PlayerinGame übergeben. Diese erhält folgender Werte:
APlayer = Spieler der in ein neues Spiel eingetragen werden soll
AOldPlay = Spiel das gerade zu Ende gespielt wurde
winning = gibt an, ob der Spieler der Gewinner oder Verlierer des Spieles ist.

Nun prüft die Procedure erst mal, welches Spiel das gerade gespielte Spiel ist, um das neue Spiel zu ermitteln, in das der aktuelle Spieler jetzt eingetragen werden soll.
Der erste Block der Abfrage für den Gewinner sollte eigentlich soweit ok sein. Keinen Plan hab ich noch für den zweiten Block, Eintrag des Verlierers. Das vorallem wenn er ein V- oder G-Spiel verloren hat.

Da die Procedure eine eigene Methode der PlayList ist, wird hier auf eigene Hilfsfunktionen zugegriffen. Das ist z.B. die Funktion GetPlay. GetPlay sucht in der Liste nach einem Spiel mit der angegebenen Bezeichnung und gibt die Instanz dieses Spieles als Ergebnis zurück. Wurde kein Spiel mit dieser Bezeichnung gefunden, so liefert die Funktion nil.
Das ergibt natürlich, dass in der Liste alle Spiele schon eingetragen sind. Erledigt wird das bei der Übergabe der Spielerliste an die PlayList. Dabei wird auf Basis der Anzahl der in der PlayerList eingetragenen Spieler der gesamte Spielplan automatisch erstellt und alle Spiele eingetragen. Das ist auch schon fertig und hat so keine großen Probleme bereitet. Hier mal diese Funktion zur Kontrolle:
Delphi-Quellcode:
procedure TPlayList.UpdatePlayCount;
var APlayerCount : Integer;
    Counter, CRound : Integer;

  procedure AddPlays(AGame : Char; ARound, ANumberCount : Integer);
  var BCounter : Integer;
  begin
    for BCounter := 1 to ANumberCount div 2 - 1 do begin
      if not Assigned(GetPlay(AGame, ARound, BCounter)) then begin
        // Spiel ist noch nicht angelegt
        Add(TPlayClass.Create(AGame, ARound, BCounter));
      end;
    end;
  end;

begin
  if not Assigned(FPlayerList) or (FPlayerList.Count = 0) then begin
    Clear;
  end else begin
    Clear;
    APlayerCount := FPlayerList.Count;
    // bei ungerade Anzahl von Spielern einen dazu
    if odd(APlayerCount) then
      inc(APlayerCount);

    // R-Spiele anlegen
    AddPlays('R', 1, APlayerCount div 2);

    // G-Spiele anlegen
    Counter := APlayerCount div 4;
    CRound := 1;
    while (Frac(Counter/2) = 0) do begin
      AddPlays('G', CRound, Counter);
      inc(CRound);
      Counter := Counter div 2;
    end;

    // V-Spiele anlegen
    Counter := APlayerCount div 4;
    CRound := 1;
    while (Frac(Counter/2) = 0) do begin
      AddPlays('V', CRound, Counter);
      inc(CRound);
      if not odd(CRound) then
        Counter := Counter div 2;
    end;

    // Finale anlegen
    Add(TPlayClass.Create('F', 0, 0));
  end;
end;
Du brauchst die Methoden hier nicht rauskopieren. Ich hab die Unit mit den Klassen schon fertig und hänge sie hier bei einem der nächsten Beiträge mit ran, dann kannst du sie dir direkt downloaden.

Ja, somit müssen wir nur noch die kleinen Probleme mit der Spielzuordnung für die Verlierer lösen und das Datenmodell ist fertig.
Dann können wir uns um den visuellen Teil kümmern.

Dann bis die Tage,

Gruß oki
42
  Mit Zitat antworten Zitat