Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Springerproblem (https://www.delphipraxis.net/60024-springerproblem.html)

Nina1310 1. Jan 2006 23:14


Springerproblem
 
Hy,
Ich muss das Springerproblem mit Delphi programmieren und komme absolut nicht klar, brauche dringend hilfe,sonst bin ich verloren. :cry:
Wäre echt toll,wenn mir da jemand helfen kann, da ich totaler Anfänger in der Geschichte bin!!!!
Ich muss ein 5x5 Feld errichten und mit Heuristik schnell zu einer Lösunhg kommen.
Bitte hilft mir, hab nur noch 1 Woche Zeit!
Lieben Gruß Yanina

*Danke im Vorraus*

Die-Nina@gmx.de

SirThornberry 1. Jan 2006 23:19

Re: Springerproblem
 
kannst du mal genau beschreiben wo du nicht weiterkommst?
hab mal gegoogelt und meine der Link zeigt die Lösung:
http://www.axel-conrad.de/springer/springer.html

Nina1310 1. Jan 2006 23:52

Re: Springerproblem
 
Auf der Seite war ich auch schon, verstehe ja,was ich machen muss und wie es geht, kann es aber mit delphi nicht umsetzen. Es klemmt also am Programmieren.
Hab jetzt mal versucht mein Feld zuerstellen, weiß aber nicht,wie ich die einzelnen Felder ansprechen soll und wie ich dem Programm sagen soll wo das Pferd(Springer) steht....

SirThornberry 1. Jan 2006 23:56

Re: Springerproblem
 
du schreibst das du mit "heuristik" zur lösung kommen mist? Also nicht in dem du alle Möglichkeiten durchprobierst? Ich hätte sonst vorgeschlagen eine Funktion welche sich rekursiv selbst aufruft und die nächsten schritte prüft (schleife). Wenn ein schritt erfolgreich war bedeuted das damit auch das der weg gefunden wurde.
Für das Feld könntest du zum Beispiel ein Array[1..25] of Boolean nehmen und damit vermerken wo du schon warst. in einer zusatzvariablen kannst du dann noch speichern auf welchem feld du zurzeit bist. oder du nimmst anstelle von boolean ein Byte oder Enum und merkst dir anhand dessen wo du gerade bist

Nina1310 2. Jan 2006 00:05

Re: Springerproblem
 
Muss nicht Heuristik miteingebaut werden, aber hab ich mir gedacht, wir sollen halt schnell zu einer Lösung kommen und "Intelligenz" in das Programm bauen. Es soll irgendwie was berechnen, wenn ein Feld nicht mehr zu erreichen ist soll der letzten Schritt abgebrochen werden und nochmal neu probiert werden mit einem anderen Spielzug.
Kannst du damit was anfangen?

SirThornberry 2. Jan 2006 00:14

Re: Springerproblem
 
ich probier grad rum, mal sehen ob ichs in der nächsten halben stunde hinbekomme. Mit dem abbrechen wird wohl gemeint sein das die rekursion dann nicht weiter probiert wird (was ja logich ist)

Nina1310 2. Jan 2006 00:18

Re: Springerproblem
 
Ja,das ist mit dem Abbrechen gemeint.
Vielen dank schonmal für die Hilfe, ist super lieb!

SirThornberry 2. Jan 2006 00:42

Re: Springerproblem
 
bin noch am basteln, irgnedwie wird bei mir kein gültiger weg gefunden. Werd spätestens morgen im laufe des tages den beitrag editieren und es reinstellen. Wenns damit nicht klappt dann stell ichs trotzdem rein als anregung wie es nicht geht.

Nina1310 2. Jan 2006 00:45

Re: Springerproblem
 
Ja,ist ok.
Hauptsache ich habe schonmal einen Anhaltspunkt.
thx

SirThornberry 2. Jan 2006 00:54

Re: Springerproblem
 
Liste der Anhänge anzeigen (Anzahl: 1)
habs hinbekommen:
Delphi-Quellcode:
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.
für das Spielfeld nehme ich einfach einen String mit einer Länge von 25 Zeichen (5*5 Felder). Jedes Zeichen des Strings representiert also ein Feld. Am Anfang werden alle Zeichen mit 0 initialisiert und dann beim probieren wenn ein feld noch 0 ist wird aus der 0 der Step, also der wievielte zug es ist. Ich kommentier den Quelltext erstmal nicht weiter da er nur als Ansatz dienen soll, das kommentieren folgt dann später.
Fragen was, was bedeutet in bezug auf die Funktionsweise sind willkommen (muss ja auch verstanden werden wenn es als anhaltspunkt dienen soll).

Um das Beispiel nachzubauen einfach ein Label aufs form packen (Label1) einen Button (Button1) den Source aus meinem Buttonclick in das OnClick des Button1 übernehmen und die restlichen functionen einfach als private funktionen deklarieren.

SirThornberry 2. Jan 2006 09:57

Re: Springerproblem
 
nach ein paar Stunden Schlaf hab ich mir das mit der Verwendung des Strings mal überlegt und verworfen. Und dafür wie in der Aufgabe beschrieben ("wenn ein Feld nicht mehr zu erreichen ist soll der letzten Schritt abgebrochen werden") wird der letzte Schritt rückgängig gemacht wenn die folgeschritte nicht möglich sind.

Hier nun der neue Quelltext:
Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TSchachFeld = Array[1..5,1..5] of Byte;

  TForm1 = class(TForm)
    Button1: TButton;
    Label1: TLabel;
    procedure Button1Click(Sender: TObject);
  private
    function FSetPosTo(ACurPos: TPoint; var AFields: TSchachFeld; ADirection: Byte; AStep: Byte): Boolean;
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function TForm1.FSetPosTo(ACurPos: TPoint; var AFields: TSchachFeld; ADirection: Byte; AStep: Byte): Boolean;
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 (AFields[LNewPos.X, LNewPos.Y] = 0) then
  begin
    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
      result := True
    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;
      //Wenn kein weiterer Zug erfolgreich war machen wir den Zug rückgängig
      if not(Result) then
        AFields[LNewPos.X, LNewPos.Y] := 0;
    end;
  end else //Wenn die berechnete neue Position außerhalb des Spielfeldes liegt oder schon mal besucht wurde gehts nicht weiter
    result := False;
end;

procedure TForm1.Button1Click(Sender: TObject);
var LCountX, LCountY: Integer; //Count-Zählvariblen für Schleifen
    LAusgabe: String;
    LStartPos: TPoint; //Startposition wo Springer sich am Anfang befindet
    LFields: TSchachFeld;
    LRes: Boolean;
begin
  //Alle Felder des Spielfeldes mit 0 beschreiben (0 = unbetreten)
  FillChar(LFields, 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
  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
  LCountX := 0;
  repeat
    //Versuchen den Springer in die Richtung zu setzen, anschließend steht in LRes obs geklappt hat
    LRes := FSetPosTo(LStartPos, LFields, LCountX, 2);
    //nächste Richtung in die wir den Spielzug probieren wollen
    inc(LCountX)
  //die Schleife wird solange ausgeführt bis der Spielzug erfolgreich war oder keine Spielzugvariante weiter vorhanden ist die wir probieren könnten
  until (LCountX = 8) or LRes;

  if LRes then
  begin
    LAusgabe := '----------------'#13#10;
    //Y
    for LCountY := 1 to 5 do
    begin
      //X
      LAusgabe := LAusgabe + '|';
      for LCountX := 1 to 5 do
        LAusgabe := LAusgabe + FormatFloat('00', LFields[LCountX, LCountY]) + '|';
      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.

Nina1310 2. Jan 2006 20:46

Re: Springerproblem
 
Hab jetzt ein StringGrid ein Label und einen Button auf das Form gestellt und deinen Quellcode kopiert.Wenn ich es laufen lassen will, kommt folgende Meldung: Im Projekt Project1.exe ist eine Exception der Klasse EClassNotFound aufgetreten. Meldung: 'Klasse TSringGrid nicht gefunden' , Prozess wurde angehalten. Mit Einzelne Anweisung oder Start fortsetzen.

Was genau will mir das jetzt sagen und was muss ich ändern?
Lieber Gruß

Daniel G 2. Jan 2006 20:54

Re: Springerproblem
 
Liste der Anhänge anzeigen (Anzahl: 1)
Was genau hast du gemacht? Ich habe eine Vermutung, behalte sie aber vorerst für mich, da das bei mir einwandfrei läuft.

Anbei SirThornberrys Code als Projekt, damit du nicht ganz auf dem Trockenen sitzt.

Nina1310 3. Jan 2006 00:23

Re: Springerproblem
 
Liste der Anhänge anzeigen (Anzahl: 1)
Schonmal gut,dass es läuft und dass die Lösungen angezeigt werden. Aber ich glauibe da muss noch etwas optisches getan werden. ich hänge als Bsp. mal das von meinem Informatiklehrer dran. Unsere Arbeit soll natürlich nicht so perfekt werden.
Lieber Gruß Yanina

Luckie 3. Jan 2006 00:31

Re: Springerproblem
 
Also so langsam hört es aber auf. Hier wurden dir schon deine kompletten Hausaufgaben gemacht. Es dürfte nicht zu viel verlangt sein, wenn du wemfalls etwas selber machst, nämlich den einfachen Teil mit der Darstellung.

Nina1310 3. Jan 2006 01:13

Re: Springerproblem
 
du hast ja recht, aber wie gesagt bin ich Anfänger und kriege ne bessere Darstellung alleine nicht hin!woher soll ich das können,wenn ich es noch nie beigebracht bekommen habe? wir kriegen ein programm in 5minuten vorgetippt und sollen es dann können,da ist nix mit erklärungen!

Luckie 3. Jan 2006 08:54

Re: Springerproblem
 
Dann wendet euch an euren Lehrer, dass da wohl was falsch läuft im Unterricht. Sei froh, dass du einen weiblichen nick hast, sonst wären die hier bestimmt nicht so hilfsbereit gewesen. ;)

ichbins 3. Jan 2006 09:37

Re: Springerproblem
 
Die eine EXE funzt nicht ganz: E6 (8x8) -> Endlosschleife

Daniel G 3. Jan 2006 12:04

Re: Springerproblem
 
Zitat:

Zitat von Luckie
Sei froh, dass du einen weiblichen nick hast, sonst wären die hier bestimmt nicht so hilfsbereit gewesen. ;)

Hör' ich da einen leisen Vorwurf? :mrgreen:

Nina1310 3. Jan 2006 12:27

Re: Springerproblem
 
Dieses Programm ist leider mehr als nur eine Hausaufgabe,es ist eine Hausarbeit, die mir 50% meiner Zeugnisnote ausmachen!
Ansonsten würde ich mir da auch nicht so einen Stress machen.

DGL-luke 3. Jan 2006 12:46

Re: Springerproblem
 
Zitat:

Zitat von Nina1310
Ansonsten würde ich mir da auch nicht so einen Stress machen.

Du machst den Stress ja uns ;)

Aber denkst du nicht, du darfst deinen lehrer fragen, wie man zum Beispiel visuelle Effekte macht? Der wird dir dann bestimmt (hoffentlich...) Sachen über Delphi-Referenz durchsuchenTPaintBox, Delphi-Referenz durchsuchenTCanvas und Delphi-Referenz durchsuchenTImage erzählen ;)

(dieses Buch-Symbol heisst, du sollst in deiner Delphi-Hilfe nachsehen ;) )

brechi 3. Jan 2006 12:59

Re: Springerproblem
 
Das wäre eigentlich ein Grund mehr dir nicht weiter zu helfen, bei 50% der Note (in der 12. / 13. Jahrgangstufe) sollte man schon ein bischen selbst machen. 30 Stunden kann man dann ja ca. einrechnen die du dafü investieren müsstest. Die visuellen Effekte kannst du ja dann mal selbst versuchen.

Nina1310 3. Jan 2006 19:57

Re: Springerproblem
 
Ich würde da gerne etwas selber machen! Ich bin normalerweise die letzte,die sich über solche Wege Hilfe holen muss. Ich bin nicht eine von der faulen Sorte,wie es anscheinend aufgefasst wird, sondern tue viel für die Schule wo ich nur kann.
Aber wenn ich keinen Anhaltspunkt in diesem Bereich habe und ebenfalls keine Vorkenntnisse besitze, komme ich in diesem Bereich leider nicht weit.
Ich habe schon drei ausgebildete Fachinformatiker nach Hilfe gefragt, doch keiner von diesen konnte mir annähernd helfen.
Als ich mich durchs Internet wühlte um etwas über das Programm zu erfahren bin ich hier gelandet und hab mir gedacht hier gibt es bestimmt Menschen,die davon eien Ahnung haben. Tut mir leid, wenn ich hier störe, das war nicht meine Absicht.
Mir tut es nur weh,wenn ich mir die Note wegen so einem Programm vermassel.
Ich habe vorher schon 12 Stunden lang versucht da was auf die Beine zu stellen, es kam aber nix bei rum.

DGL-luke 3. Jan 2006 20:00

Re: Springerproblem
 
Schau einfach in deine Delphi-Hilfe zu den von mir genannten Stichworten.... ( F1 drücken ;) )

mit TForm.canvas kannst du schon so gut wie alles, was grafisch möglcih ist, erreichen ;)


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:31 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz