So, eine Stunde Deutsch ist um und hatte somit genug Zeit, über meine Idee nachzudenken
Kurz eine Erklärung zum Prinzip von Distances und Directions:
Jede Figur kann in bestimmte Richtungen bewegen. Der Turm nur Waag- und Senkrecht, der Läufer nur Diagonal, Königin und König beides; Der Springer nur in einem anderen Winkel, und den Bauern sehn wir mal als Ausnahme.
Damit können wir uns folgendes Set von Richtungen Definieren
TChessDirection = (cdRook, cdKnight1, Knight2, cdBishop, cdNone);
die None-Direction brauchen wir für den Fall, dass die Richtung keiner Bekannten entspricht, und wir haben 2 Richtungen für den Springer, warum sehen wir später
Um nun angeben zu können, wer wohin laufen kann, brauchen wir ein set of, wo wir dann auch die Richtungen der Figuren bereits definieren können
Delphi-Quellcode:
TChessDirections = set of TChessDirection;
TChessFigures = (cfPawn, cfRook, cfKnight, cfBishop, cfQueen, cfKing);
const
PossibleDirections: array[TChessFigures] of TChessDirections =
([], //Pawn - Ausnahme
[cfRook], //Rook
[cfKnight], //Knight
[cfBishop], //Bishop
[cfRook, cfBishop], //Queen
[cfRook, cfBishop]); //King
Damit das nun langsam Werte werden, die wir brauchen können, definieren wir Konstanten, welche Richtung welchem Winkel entspricht:
Delphi-Quellcode:
const
DirectionAngles: array[TChessDirection] of integer = (1570, 463, 1107, 785, 21351);
Hier brauchen wir für den Springer eben nur 2 Richtungen, weil er im Bereich von 90° in 2 Richtungen laufen kann. (2 nach oben, 1 links, oder 1 nach oben und 2 links)
Damit wir nun aber das aber auch was bringt, brauchen wir eine Funktion, die uns sagt, welche Richtung das ist.
Delphi-Quellcode:
function GetDirection(Source: TPoint; Destiny: TPoint): TChessDirection;
var
angle: real;
i: TChessDirection;
begin
result := cdNone;
//Winkel ausrechnen
angle := arcsin(abs(Source.Y - Destiny.Y) / sqrt(sqr(Source.X - Destiny.X) + sqr(Source.Y - Destiny.Y))) + 4*Pi;
//Hier bin ich mir nicht sicher, ob der folgende Teil stimmt. am ende soll halt folgendes gelten: 0 < angle <= Pi / 2
while angle > 1.5707 do
angle := angle - 1.570
for i := cdRook to cdBishop do
if trunc(angle * 1000) = DirectionAngles[i] then
result := i;
end;
Hier wird nun rausgefunden, welche Richtung bewegt wurde. Im fall dass nix passt, ist es cdNone. Dafür brauchen wir das. Wenn nun bei PossibleDirections irgendwo cdNone vorkommt, kann er überall hinbewegen, wo sonst keiner hin kann.
Damit hätten wir mal die Richtungen abgeschlossen.
Nun brauchen wir noch die Distanzen:
Jede Figur hat eine Maximale Reichweite. Der König kann maximal 1 Feld gehen, auch diagonal, also ist die Maximale distanz ca. 1.5, Der Springen kann schon etwas weiter laufen, ca. 2.3, und die restlichen Figuren (Der Bauer ist immernoch die Ausnahme) können auch 15 Felder laufen, wenn nicht das Spielfeld vorher fertig wär
Die Distanzen können wir ganz einfach in einer Konstante speichern:
Delphi-Quellcode:
const
MaxDistances: array[TChessFigures] of real = (1, 15, 2.3, 15, 15, 1.7);
Ob nun die Bewegung von der Distanz her auch passt, können wir ganz einfach überprüfen:
Delphi-Quellcode:
function GetDistance(Source: TPoint; Destiny: TPoint): real;
begin
result := sqrt(sqr(Source.X - Destiny.X) + sqr(Source.Y - Destiny.Y));
end;
Mit diesem ganzen Rast können wir nun (bis auf unsre Ausnahme, den Bauern) überprüfen, ob der Zug möglich ist
Delphi-Quellcode:
function IsDirectionPossible(Source: TPoint; Destiny: TPoint; Figure: TChessFigure): boolean;
begin
result := (GetDirection(Source, Destiny) in PossibleDirections[Figure]) //die Richtung
and (GetDirection(Source, Destiny) < MaxDistance[Figure]); //und die Entfernung muss passen
end;
Was du noch überprüfen musst ist, ob eine Figur auf dem Zielfeld steht, und v.a. ob sich eine Figur dazwischenbefinden, wofür dir die Directions auch zuhilfe kommen könnten
Die ganzen Quellcodes hab ich nicht probiert, als keine Garantie, dass sie laufen. Das ganze soll eine Anregung sein, wie du sowas machen könntest. Und Fragen dazu kannst du mir jederzeit stellen
[edit=sakura] *wuppdi* Mfg, sakura[/edit]