Einzelnen Beitrag anzeigen

Benutzerbild von JasonDX
JasonDX
(CodeLib-Manager)

Registriert seit: 5. Aug 2004
Ort: München
1.062 Beiträge
 
#6

Re: Schach: Überprüfung, ob Zug erlaubt

  Alt 4. Jun 2005, 09:37
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]
Mike
Passion is no replacement for reason
  Mit Zitat antworten Zitat