unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TPosRes =
record
AFields:
String;
Success: Boolean;
end;
TForm1 =
class(TForm)
Button1: TButton;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
private
function FSetPosTo(ACurPos: TPoint; AFields:
String; ADirection: Byte; AStep: Byte): TPosRes;
function FGetField(
const AFields:
String; AX, AY: Integer): Byte;
procedure FSetField(
var AFields:
String; AX, AY: Integer; AVal: Byte);
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function TForm1.FSetPosTo(ACurPos: TPoint; AFields:
String; ADirection: Byte; AStep: Byte): TPosRes;
var LNewPos: TPoint;
LCount: Integer;
begin
//ADirection ist die Variante/Richtung in die wir den Springer setzen
//Anhand der aktuellen Position und der Richtung(ADirection) berechnen wir wo der Springer nach dem Zug dann ist
case ADirection
of
//2 hoch und 1 links
0: LNewPos := Point(ACurPos.X - 1, ACurPos.Y - 2);
//2 hoch und 1 rechts
1: LNewPos := Point(ACurPos.X + 1, ACurPos.Y - 2);
//2 rechts und 1 hoch
2: LNewPos := Point(ACurPos.X + 2, ACurPos.Y - 1);
//2 rechts und 1 runter
3: LNewPos := Point(ACurPos.X + 2, ACurPos.Y + 1);
//2 runter und 1 rechts
4: LNewPos := Point(ACurPos.X + 1, ACurPos.Y + 2);
//2 runter und 1 links
5: LNewPos := Point(ACurPos.X - 1, ACurPos.Y + 2);
//2 links und 1 runter
6: LNewPos := Point(ACurPos.X - 2, ACurPos.Y + 1);
//2 links und 1 hoch
7: LNewPos := Point(ACurPos.X - 2, ACurPos.Y - 1);
end;
//In LNewPos ist jetzt die Position wo der Springer sein würde wenn wir den Zug durchführen
//Wenn die neue Position innerhalb des Spielfeldes ist und wir auf diesem Spielfeld noch nicht waren dann gehts weiter
if (LNewPos.X > 0)
and (LNewPos.Y > 0)
and (LNewPos.X < 6)
and (LNewPos.Y < 6)
and (FGetField(AFields, LNewPos.X, LNewPos.Y) = 0)
then
begin
FSetField(AFields, LNewPos.X, LNewPos.Y, AStep);
//Wenn dies der letzte zug war (25te) und somit kein weiteres Feld mehr unbenutzt ist geben wir "Erfolg" zurück
if AStep = 5 * 5
then
begin
//Das Ergebnis beinhaltet die Felder (damit die Reihenfolge)
result.AFields := AFields;
//Und natürlich dem Boolean das es erfolgreich war
result.Success := True;
end else begin
//der aktuelle Spielzug war erfolgreich, jetzt kommt die Rekursion ins Spiel
LCount := 0;
repeat
//Wir probieren von dem Feld aus wo sich der Springer jetzt befindet wieder alle möglichen Spielzüge aus bis ein Spielzug erfolgreich war (und somit auch die folgenden (reskursion)) oder bis es keinen alternativen Spielzug mehr gibt
result := FSetPosTo(LNewPos, AFields, LCount, AStep + 1);
//Spielzugvariante incrementieren
inc(LCount);
until (LCount = 8)
or (result.Success);
end;
end else //Wenn die berechnete neue Position außerhalb des Spielfeldes liegt oder schon mal besucht wurde gehts nicht weiter
result.Success := False;
end;
function TForm1.FGetField(
const AFields:
String; AX, AY: Integer): Byte;
begin
result := Byte(AFields[(AY - 1) * 5 + AX]);
end;
procedure TForm1.FSetField(
var AFields:
String; AX, AY: Integer; AVal: Byte);
begin
AFields[(AY - 1) * 5 + AX] := char(AVal);
end;
procedure TForm1.Button1Click(Sender: TObject);
var LCount, LCount2: Integer;
//Count-Zählvariblen für Schleifen
LRes: TPosRes;
//LRes = Lokale Variable -> Resultat (Ergebnis)
LFields, LAusgabe:
String;
LStartPos: TPoint;
//Startposition wo Springer sich am Anfang befindet
begin
//Stringgröße 5*5=25 Felder setzen
SetLength(LFields, 5 * 5);
//Alle Felder des Spielfeldes mit 0 beschreiben (0 = unbetreten)
FillChar(LFields[1], 5 * 5, 0);
//Hier legen wir fest wo der Springer am Anfang steht
LStartPos := Point(1, 1);
//Und jetzt tragen wir das noch auf dem Spielfeld ein. Feld X=1 Y=1 bekommt also den Wert 1 was bedeutet das dieses Feld im ersten Schritt betreten wurde
FSetField(LFields, LStartPos.X, LStartPos.Y, 1);
//LCount steht für die verschiedenen Spielzüge (man könnte auch ein enumerationtyp nutzen)
//0 = 2 hoch und 1 links
//1 = 2 hoch und 1 rechts
//2 = 2 rechts und 1 hoch
//3 = 2 rechts und 1 runter
//4 = 2 runter und 1 rechts
//5 = 2 runter und 1 links
//6 = 2 links und 1 runter
//7 = 2 links und 1 hoch
LCount := 0;
repeat
//Versuchen den Springer in die Richtung zu setzen, anschließend steht in LRes obs geklappt hat
LRes := FSetPosTo(LStartPos, LFields, LCount, 2);
//nächste Richtung in die wir den Spielzug probieren wollen
inc(LCount)
//die Schleife wird solange ausgeführt bis der Spielzug erfolgreich war oder keine Spielzugvariante weiter vorhanden ist die wir probieren könnten
until (LCount = 8)
or (LRes.Success);
if LRes.Success
then
begin
LAusgabe := '
----------------'#13#10;
//Y
for LCount := 1
to 5
do
begin
//X
LAusgabe := LAusgabe + '
|';
for LCount2 := 1
to 5
do
LAusgabe := LAusgabe + FormatFloat('
00', Byte(LRes.AFields[(LCount - 1) * 5 + LCount2])) + '
|';
LAusgabe := LAusgabe + #13#10 + '
----------------' + #13#10;
end;
Label1.WordWrap := True;
Label1.Font.
Name := '
Courier New';
Label1.Caption := LAusgabe;
end else
ShowMessage('
Mit dieser Startposition war es nicht möglich mit nur einem Bereten je Feld alle Felder zu betreten.');
end;
end.