Hallo optiplex,
soweit habe ich den Spielplan verstanden. Der Punkt ist, dass es Sinn macht ein allgemeines Zuordnungsprinzip, einen Algorithmus zu finden, mit dem man mathematisch das nächste Spiel ermitteln kann. Somit wird die procedure universell und gilt für alle Anzahlen von Spielern, egal ob 8, 16, 32 usw. Man muss halt nicht für jede Anzahl von Spielern eine eigene Zuordnungsprocedure schreiben. Das habe ich versucht, bin an der erwähnten Stelle gescheitert. Da hatte ich auch noch nicht begriffen, dass das KO-System auf eine Spieleranzahl zur Basis 8 definiert ist.
Ich erkläre mal meine Vorgehensweise für den Teil den ich bis jetzt in den Griff bekommen haben (dabei war die Annahme, dass ausschließlich eine gerade Anzahl von Spielern notwendig ist).
[edit] Sorry, hier noch mal was die Eigenschaften bei TPlayClass (und somit für den Parameter APlayClass) bedeuten.
Delphi-Quellcode:
FGame: Char; // Spiel; R, V, G
FNumber: Integer; // Spielnummer 1..x
FPlayer1: TPlayerClass; // Spieler 1
FPlayer2: TPlayerClass; // Spieler 2
FPlayList: TPlayList; // übergeordnete PlayList
FPlayResult: TPlayResult; // Ergebnis des Spiels
FRound: Integer; // Runde
FStatus: TPlayState; // Spielstatus
Bsp.:
R1-2
R = Game
1 = Round
2 = Number
- = nur optischer Trenner im String.
[/edit]
In der procedure wird der Spieler der einem neuen Spiel zugeordnet werden soll, das aktuell gespielte Spiel sowie ein Flag ob der übergebene Spieler der Gewinner der Partie war übergeben:
procedure TPlayList.ChangePlay(APlayClass: TPlayClass; AProperty : String);
Als erstes prüfe ich, ob der Spieler der einem neuen Spiel zugeordnet werden soll ein Gewinner ist:
Delphi-Quellcode:
if winning then begin
// Spieler ist Gewinner des alten Spieles
Jetzt berücksichtige ich, welches Spiel das gerade gespielte Spiel war:
Delphi-Quellcode:
case ORD(AOldPlay.FGame) of
ORD('R') : begin
// Gewinner der ersten Runde
Also, der Spieler hat in einer Runde 'R' (erste Spielrunde aller Spieler) gewonnen. Anhand des Spielplanes hab ich eine recht einfache logische Folge entdeckt. Der Gewinner einer Runde "R" geht wie folgt als Spieler in ein Spiel der Runde "G" :
Gewinner aus:
R1 wird erster Spieler G1
R2 wird zweiter Spieler G1
R3 wird erster Spieler G2
R4 wird zweiter Spielr G2
.... und endlos so weiter.
Daraus folgt, das der Gewinner aller ungeraden Spielnummern für "R" immer der erste Spieler des folgenden Gewinnerspieles wird und der Gewinner mit den geraden Spielnummern für "R" immer der zweite Spieler. Die Nummer des zu ermittelnden "G"-Spieles ist immer das Ergebnis die auf eine gerade Zahl aufgerundete Spielnummer von "R" geteilt durch 2.
R-Nummer wird zur G-Nummer
1 -> 1
2 -> 1
3 -> 2
4 -> 2
.........
17 -> 9
18 -> 9
19 -> 10
20 -> 10
.........
somit entstehr folgender Code:
Delphi-Quellcode:
if Odd(AOldPlay.Number) then begin // Gewinner einer ungeraden Spielrunde
NewPlay := GetPlay('G', 1, (AOldPlay.Number+1) div 2); // das Spiel "G1-x" holen, wobei x gleich (y+1)/2 aus R1-y für das ungerade Spiel ist
if Assigned(NewPlay) then
NewPlay.FPlayer1 := APlayer; // wird Spieler 1
end else begin // Gewinner einer geraden Spielrunde
NewPlay := GetPlay('G', 1, (AOldPlay.Number) div 2); // // das Spiel "G1-x" holen, wobei x gleich y/2 aus R1-y für das gerade Spiel ist
if Assigned(NewPlay) then
NewPlay.FPlayer2 := APlayer; // wird Spieler 2
end;
Soweit so gut. Das lässt so einfach für alle Spieler ermitteln, die Gewinner einer Runde sind, Egal ob sie vorher einmal verloren haben. Ich denke unter dieser Erläuterung sollte der Code für die gewonnenen "G" und "V"-Spiele nachvollziehbar sein, auch wenn er einer etwas anderen Logik folgt.
In den weiteren Spielrunden für "G" und "V" prüfe ich zusätzlich, ob wirklich ein neues Spiel gefunden wurde. Ist dies nämlich nicht der Fall, so ist der Gewinner ein Teilnehmer für das Finale. Da gibt es keinen Ausweg.
Delphi-Quellcode:
if Assigned(NewPlay) then begin
NewPlay.FPlayer1 := APlayer;
end else begin
// das war das letzte Gewinnerspiel, ab ins Finale
NewPlay := GetPlay('F', 0, 0);
if Assigned(NewPlay) then
NewPlay.Player1 := APlayer;
end;
Dabei ist recht einfach zu erkennen, dass der Gewinner eines "G"-Spieles der erste Spieler des Finales und der Gewinner des "V"-Spieles der zweite Spieler des Finales wird (für mich ist das aber wurscht, es bleiben eh nur zwei übrig; wer das erster oder zweiter Spieler ist scheint wohl nur für die Profis wichtig zu sein).
Soweit war das alles recht logisch. Meine Probleme fangen mit den Verlierern der "G" und "V"-Spiele an. Für die Verlierer der R-Spiele ist das so einfach wie oben beschrieben bei den Gewinnern.
Ich habe folgendes gesehen (für 16 Spieler) Verlierer des Spiels geht in Spiel:
Gx-y -> Va-b
G1-1 -> V2-4 2.Spieler
G1-2 -> V2-3 2.Spieler
G1-3 -> V2-2 2.Spieler
G1-4 -> V2-1 2.Spieler
G2-1 -> V4-2 2.Spieler
G2-2 -> V4-1 2.Spieler
G3-1 -> V6-1 2.Spieler
da steckt auch ein System dahinter. Schau mal, ob du das umgesetzt bekommst. Das sollte rein mathematisch gehen. Ein Ansatz ist, dass für 16 Spieler 4 G1 Spiele existieren, wobei das Va-b Spiel a=x*2 und b=16/4-y-1 ist. x und y entnimmt man Gx-y. Jo, so klappts.
Das ganze muss jetzt noch für die Verliererspiele ausgetüftelt werden.
Läßt sich mit dem neu ermittelten Spielnamen kein Spiel in der Spielliste finden, so ist das Turnier für diesen Spieler zu ende. Die Berechnung der Platzierung ist bei mir noch falsch, aber dazu später.
Gruß oki