![]() |
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 |
Re: Springerproblem
kannst du mal genau beschreiben wo du nicht weiterkommst?
hab mal gegoogelt und meine der Link zeigt die Lösung: ![]() |
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.... |
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 |
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? |
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)
|
Re: Springerproblem
Ja,das ist mit dem Abbrechen gemeint.
Vielen dank schonmal für die Hilfe, ist super lieb! |
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.
|
Re: Springerproblem
Ja,ist ok.
Hauptsache ich habe schonmal einen Anhaltspunkt. thx |
Re: Springerproblem
Liste der Anhänge anzeigen (Anzahl: 1)
habs hinbekommen:
Delphi-Quellcode:
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.
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. 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. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:52 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz