![]() |
Labyrinth darstellen
Hi,
möchte probieren, ein Programm zu erstellen, welches zufällig ein Labyrinth erstellt. Es soll am Rand einen Ausgang geben und in der Mitte soll eine Maus starten und alleine den Weg nach draußen finden. So viel zur Theorie. Mein Info-Lehrer hat mir diese Aufgabe gestellt und gesagt, dass noch nie einer seiner Schüler diese Aufgabe zufriedenstellend gelöst hat. Aber jetzt komm ich :mrgreen: Falls ihr jetzt denkend solltet dass ich wieder so einer bin, der seine HA gemacht haben möchte, am besten noch mit Code, der irrt. Erstens ist es keine HA und zweitens möchte ich euch nur fragen, wie ihr das Labyrinth darstellen würdet. Es muss ziemlich groß sein und sollte eine 2D-Draufsicht darstellen. Wie würdet ihr das Labyrinth zeichnen lassen? mit Strichen die die Wände zeigen? Oder das Programm in kleine Felder einteilen und die Felder dann mit einem Bitmap füllen? Wie würdet ihr vorgehen? Hoffe ihr habt da mal eine gute Idee. Ich will keinen Designpreis gewinnen, sondern eher ein simples Labyrinth haben, welche leicht in den noch nicht vorhandenen Algorithmus eingefügt werden kann. Thx! :-D |
Re: Labyrinth darstellen
OK! Das mit dem zeichnen finde ich einfach: Hier mein Code (/Idee)
Nur das erstellen von dem Labyrith is ned so einfach! (finde ich) Wenn du also eine Lösung gefunden hast dann poste bitte den Code
Delphi-Quellcode:
unit Unit1;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, ImgList, StdCtrls; type TForm1 = class(TForm) Image1: TImage; Button2: TButton; procedure Button2Click(Sender: TObject); procedure FormCreate(Sender: TObject); private procedure ReDraw(); { Private-Deklarationen } public { Public-Deklarationen } end; var Form1: TForm1; Spielfeld: array[0..50,0..50] of integer; implementation {$R *.dfm} procedure TForm1.ReDraw; var x,y:longint; a,b:longint; begin for x:=0 to 50 do begin for y:=0 to 50 do begin if Spielfeld[x,y]= 1 then begin for a:=0 to 10 do begin for b:=0 to 10 do begin Image1.Canvas.Pixels[x*10+a,y*10+b]:=clred; end; end; end; if Spielfeld[x,y]= 2 then begin for a:=0 to 10 do begin for b:=0 to 10 do begin Image1.Canvas.Pixels[x*10+a,y*10+b]:=clblue; end; end; end; end; end; end; procedure TForm1.Button2Click(Sender: TObject); begin randomize; Spielfeld[random(50),random(50)]:=2; Spielfeld[random(50),random(50)]:=1; end; procedure TForm1.FormCreate(Sender: TObject); begin ReDraw; end; end. |
Re: Labyrinth darstellen
thx, werds gleich mal ausprobieren. Das das zeichnen nicht so schwierig wird, ist mir klar, das schwierige wird der Code nachher*g* Wollte ja mal wissen wie ihr das realisieren würdet. Ich mein man kann das Problem ja sehr verschieden angehen.
Wenn ich das irgendwann fertig hab poste ich das auf jeden Fall mal. |
Re: Labyrinth darstellen
ich würd die fläche des labyrinths kacheln (zb mit panels(nat. ohne rahmen...muss der User ja net sehen!) und dann an jeder seite n shape zeichnen...dann ne menge verschachtelter if...then bedingungen...FERTIG! :D
|
Re: Labyrinth darstellen
sollte man aus performencegründen zum zeichnen nicht lieber scanlines verwenden ?
|
Re: Labyrinth darstellen
Delphi-Quellcode:
;)
SleepyMaster<>Performence
|
Re: Labyrinth darstellen
Mit den Kacheln hatte ich auch schon vor...finde das ist einfacher zu handhaben. Vor allem für die spätere Wegfindung. Als Problem seh ich hier allerdings die Perfomance. Hatte vor das Spielfeld 50x50 zu machen. Das wären dann 2.500 Panels :wall: Ich schätz einfach mal das das Programm damit nicht so irre glücklich wäre. Eine Einteilung in Kacheln wäre aber schön. Wie könnte ich das sonst noch lösen?
|
Re: Labyrinth darstellen
Ich würds ehrlich gesagt so machen:
Das gleiche wie oben (nur en bissel überarbeitet!) Das einzige was du machen musst ist in das array Spielfeld deine Integerwerte reinspeichern (Das array Stellt dein Spielfeld da) und dann die procedure redraw ausführen!
Delphi-Quellcode:
unit Unit1;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, ImgList, StdCtrls; type TForm1 = class(TForm) Image1: TImage; Button2: TButton; Button1: TButton; Button3: TButton; procedure FormCreate(Sender: TObject); procedure Button1Click(Sender: TObject); procedure Button3Click(Sender: TObject); private Spielfeld: array[0..50,0..50] of integer; procedure ReDraw(); procedure Clear(); { Private-Deklarationen } public { Public-Deklarationen } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Clear; var x,y:longint; begin Image1.Canvas.Brush.Color:=clwhite; Image1.Canvas.Rectangle(0,0,Image1.Width,Image1.Height); for x:=0 to 50 do begin for y:=0 to 50 do begin SpielFeld[x,y]:=0; end; end; end; procedure TForm1.ReDraw; var x,y:longint; a,b:longint; begin for x:=0 to 50 do begin for y:=0 to 50 do begin if Spielfeld[x,y]= 1 then begin Image1.Canvas.Brush.Color:=clred; Image1.Canvas.Rectangle(x*10,y*10,x*10+10,y*10+10); end; if Spielfeld[x,y]= 2 then begin Image1.Canvas.Brush.Color:=clblue; Image1.Canvas.Rectangle(x*10,y*10,x*10+10,y*10+10); end; end; end; end; procedure TForm1.FormCreate(Sender: TObject); begin clear; end; procedure TForm1.Button1Click(Sender: TObject); var a,b:longint; begin Clear; end; {function ran:boolean; begin if random(2)= 1 then result := true else result:=false; end; procedure TForm1.Button3Click(Sender: TObject); var I:longint; a,b:integer; begin randomize; a:=Random(50); b:=Random(50); for i:=10 to 200 do begin if ran then if ran then b:=b+1 else b:=b-1 else if ran then a:=a+1 else a:=a-1; SpielFeld[a,b]:=1; end; SpielFeld[a,b]:=1; Redraw; end;} end. |
Re: Labyrinth darstellen
würd mich sowieso ma interessieren...:
Kann man objekte nicht in schleifen ansprechen? Bsp: ich hab die panels 1-2500 (Panel_1,Panel_2.usw..
Delphi-Quellcode:
[edit=r_kerber]Delphi-Tags korrigiert. Mfg, r_kerber[/edit]
for <Panels 1-2500> do
begin bla; blubb; bla; end; |
Re: Labyrinth darstellen
Ich würds vermutlich mit nem Array aus Bitmap im Vormat 50*50 machen und dann später einfach mit for i:= 1 to Anzahl der Felder schauen ob der nächste zug der Maus die wand rammt.
Hab schon mal ein Labyrinth gemacht(opensource), aber ohne KI, das war mir dann doch zu ...zeitaufwendig...Naje wennst das gschaft hast, kannst ja mal den prog posten |
Re: Labyrinth darstellen
@XeRo: Jo, so wäre es noch recht einfach zu realisieren...
@SleepyMaster: Könntest du mal die Project Files uppen? Morgen krieg ich 3D-Programmierung mit Delphi...für Kids :mrgreen: (wegen Delphi 8, damit ich updaten kann) Vielleicht steht da was drin...2D Spiele werden IMHO auch oft mit kleinen Kästchen programmiert. Das wäre ja genau das richtige... |
Re: Labyrinth darstellen
So gehts auch: (Etwas überarbeitet)
Delphi-Quellcode:
function Farbcode(Code: integer):TColor;
begin result := clwhite; case Code of 1 : result := clred; 2 : result := clblue; 3 : result := clgreen; 4 : result := cllime; end; end; procedure TForm1.ReDraw; var x,y: longint; const Groesse = 20; //Größe der kacheln begin Image1.Canvas.pen.Color := clwhite; for x :=0 to 50 do for y :=0 to 50 do begin Image1.Canvas.brush.Color := Farbcode(Spielfeld[x,y]); //Farbcode Image1.Canvas.Rectangle(x*Groesse,y*Groesse, x*Groesse+Groesse,y*Groesse+Groesse); end; end; |
Re: Labyrinth darstellen
Man könnt's auch mit nem DrawGrid, bei dem man die Zellen als Wand einfärbt und als Weg, da wär auch das Abfragen ob Wand oder nicht kein großes Problem.
|
Re: Labyrinth darstellen
Sehr gut Fib! Das kommt in die nähere Auswahl. Das ist nun echt einfach zu handhaben. Überleg mir aber noch bis morgen wie genau ich das löse. Also mehr Ideen müssen her :-D Hoffentlich komm ich dann morgen auch dazu ein bisschen rumzuprobieren...
|
Re: Labyrinth darstellen
Hallo Getcool,
für die KI (das Routefinding) der Maus schlage ich dir folgendes vor: Erstelle einen Array of Integer in der Größe des Labyrinths, so dass zu jeder Kachel ein Integer gehört. Setzte alle diese Integer auf -1 (beispielsweise) und das Feld auf dem die Maus steht auf 0. Nun brauchst du eine Schleife die den Array so ausfüllt, dass in jedem Feld die Anzahl der Schritte steht, die das Feld im Labyrinth von der Maus entfernt ist. d.h. die Felder über, unter und neben der Maus bekommen eine 1, sofern keine Wand dazwischen ist usw... Die Schleife könnte beispielsweise eine for-Schleife sein, wobei der Laufindex ich nenn ihn mal i,dann die Zahl ist, die überprüft werden muss und das geht so: In diese Schleife setzt du wieder zwei Schleife, um so alle Felder des Labyrinths durchzugehen. Steht in irgendeinem Feld die Zahl i, dann schaust du ob die umliegenden Felder (oben, unten, rechts, links) direkt von diesem Feld aus erreichbar sind (d.h. keine Wand ist dazwischen) und ob darin noch keine Zahl steht, die kleiner als i ist. Ist dies der Fall, schreibst du in die entsprechenden Felder die Zahl i+1. Nach Maximal 2500 Durchläufen ist das ganze Labyrinth mit diesen Zahlen gefüllt, wobei die nicht erreichbaren Felder immernoch -1 enthalten. Der Kürzeste Weg zum Ausgang lässt sich dann so finden: Starte bei der Betrachtung des Wegs beim Ausgang. Gehe nun auf das benachbarte Feld, dessen Wert um 1 kleiner ist als auf diesem Feld... usw. Irgendwann kommst du dann bei der Maus an. Das ganze ist natürlich eigentlich keine KI, sonder Routefinding, d.h. wenn die Aufgabe ist, eine Maus zu programmieren, die nicht das ganze Labyrinth kenn, sondern nur den Teil, wo sie schon war, dann musst du es anders machen. Grüße Seniman |
Re: Labyrinth darstellen
Zitat:
|
Re: Labyrinth darstellen
Wenn die Maus das Labyrinth nicht kennt, dann machs wirklich mit einem Array aus bitmaps, dann versuch zuerst ob die maus nach rechts gehen kann, wenn nicht dann nach links,...
Dann muss sie sich noch irgendwie merken, wo sie schon war und wo eine sackgasse ist,... Aber so ungefähr könnt ich mir das vorstellen...und es ist nicht wirklich kompliziert so zu prog. |
Re: Labyrinth darstellen
Zitat:
|
Re: Labyrinth darstellen
wollte sagen dass das "WIE KÖNNTE ES GEHEN" nicht schwer ist...
...dass das Prog ziemlich umfangreich wird ist klar, aber wenn dein Lehrer eine gute und saubere Lösung will muss er mit sowas rechnen... :roll: |
Re: Labyrinth darstellen
|
Re: Labyrinth darstellen
Ein gutes Zufallslabyrinth zu erstellen st sehr schwer, das wirst du nicht so einfach hinbekommen ;)
Siehe mein Thread: ![]() |
Re: Labyrinth darstellen
Du machst einem ja viel Mut :evil: :zwinker:
Aber wie schon gesagt, mein Info-Lehrer meint es hätte noch keiner seiner Schüler geschafft. Grund genug sich da hinter zu klemmen. Außerdem wäre es ja nicht interessant wenn es nicht kompliziert/schwierig wäre. |
Re: Labyrinth darstellen
Hi GetCool
ich habe mal aus langeweile ein zufallslabyrinth programmiert, vieleicht hilfst dir weiter, die lösung kann dabei auch angezeigt werden. Du brauchst nur ein Image1, ein Button1 und eine Checkbox1 auf dem formular
Delphi-Quellcode:
Unit Unit1;
Interface Uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls; Type TCellType = Set Of (cStart, cFinal, cSolution, cFree); TForm1 = Class(TForm) Button1: TButton; Image1: TImage; CheckBox1: TCheckBox; Procedure Button1Click(Sender: TObject); procedure CheckBox1Click(Sender: TObject); Private Cells: Array[0..49, 0..49] Of Record S, O: Boolean; CellType: TCellType End; Procedure GenerateMaze(StartX, StartY: Integer); Procedure DrawMaze(ShowSolution: Boolean); End; Var Form1: TForm1; Implementation {$R *.DFM} Procedure TForm1.Button1Click(Sender: TObject); Begin Randomize; //RandSeed:=0; Caption:=IntToStr(RandSeed); // Labyrinth erstellen mit der Startposition x=25 y=25 GenerateMaze(25,25); // Labyrinth anzeigen DrawMaze(CheckBox1.Checked); End; procedure TForm1.DrawMaze(ShowSolution: Boolean); Var x, y: Integer; begin Image1.Picture.Bitmap:=Nil; Image1.Width:=501; Image1.Height:=501; With Image1.Canvas Do Begin Brush.Color:=clBlack; FrameRect(ClipRect); Pen.Width:=1; Pen.Color:=clBlack; For x:=0 to 49 Do For y:=0 to 49 Do Begin If Cells[x,y].O Then Begin MoveTo((x+1)*10, y*10); LineTo((x+1)*10, (y+1)*10+1) End; If Cells[x,y].S Then Begin MoveTo(x*10, (y+1)*10); LineTo((x+1)*10+1, (y+1)* 10) End; If cStart In Cells[x,y].CellType Then Ellipse(x*10+2, y*10+2, x*10+8, y*10+8); If cFinal In Cells[x,y].CellType Then Ellipse(x*10+2, y*10+2, x*10+8, y*10+8); If ShowSolution And (cSolution In Cells[x,y].CellType) Then Ellipse(x*10+4, y*10+4, x*10+6, y*10+6); End; End; end; Procedure TForm1.GenerateMaze(StartX, StartY: Integer); CONST N=0; S=1; W=2; O=3; Function ValidCell(x, y: Integer): Boolean; Begin Result:=(x>=0) And (y>=0) And (x<=49) And (y<=49); End; Function ValidWay(x, y: Integer): Boolean; Begin If ValidCell(x,y) Then Result:=cFree In Cells[x,y].CellType Else Result:=False; End; Function NewWay(x, y, r: Integer): Boolean; Var WegNr: Array[0..3] Of Boolean; Solution: Boolean; Nr: Byte; Begin // die aktuelle Zelle als belegt markieren Cells[x,y].CellType:=Cells[x,y].CellType-[cFree]; // die Wand entfernen, aus der Richtung der wir gekommen sind Case r Of S: If ValidCell(x,y-1) Then Cells[x,y-1].S:=False; N: Cells[x,y].S:=False; O: If ValidCell(x-1,y) Then Cells[x-1,y].O:=False; W: Cells[x,y].O:=False; End; // Zufällige Reihenfolge der Richtungen berechnen For Nr:=0 To 3 Do WegNr[Nr]:=False; Solution:=False; Repeat Nr:=Random(4); Case Nr Of N: If ValidWay(x,y-1) Then Solution:=NewWay(x,y-1,N); S: If ValidWay(x,y+1) Then Solution:=NewWay(x,y+1,S); W: If ValidWay(x-1,y) Then Solution:=NewWay(x-1,y,W); O: If ValidWay(x+1,y) Then Solution:=NewWay(x+1,y,O); End; WegNr[Nr]:=True; If Solution Then With Cells[x,y] Do CellType:=CellType+[cSolution]; Until WegNr[0] And WegNr[1] And WegNr[2] And WegNr[3]; Result:=(cSolution In Cells[x,y].CellType) Or (cStart In Cells[x,y].CellType); End; Var x, y: Integer; Begin For y:=0 To 49 Do For x:=0 To 49 Do Begin Cells[x,y].S:=True; Cells[x,y].O:=True; Cells[x,y].CellType:=[cFree]; End; With Cells[StartX,StartY] Do CellType:=CellType+[cStart]; // ein zufälliges Ziel x:=Random(50); y:=Random(50); // das Ziel an den Rand verschieben Case Random(4) of N: y:=0; S: y:=49; W: x:=0; O: x:=49; End; With Cells[x,y] Do CellType:=CellType+[cFinal]; // Anfangszelle setzten NewWay(x,y,-1); End; procedure TForm1.CheckBox1Click(Sender: TObject); begin DrawMaze(CheckBox1.Checked); end; End. |
Re: Labyrinth darstellen
Frag mal Phanntom1, der hat dieses geile Laser-Labyrinth geschrieben, villeicht kann er dir nen paar Tips geben..
![]() |
Re: Labyrinth darstellen
Ich erinnere mich an eine applicaktion für den Atari ST. Diese hat ein labyrint gemalt indem es recursiv immer wieder nach einer Zuflasszahl mit eine einem abzweig angefangen. Wenn es an eine grenze gestossen ist an der es nicht vorbei kamm recursion beenden und beim Aufrufer weiter machen.
Ich kann micht nicht mehr genau an den code erinnern - dies also nur als denk anstoss. Julian Ziersch |
Re: Labyrinth darstellen
@jziersch: ich kenne zwar das programm nicht was du beschrieben hast, aber bei dem code den ich oben gepostet habe, habe ich auch rekursive aufrufe verwendet :wink: das ist warscheinlich das einfachste
|
Re: Labyrinth darstellen
Hey Phantom!
Werds mir mal angucken. Vielen Dank schonmal! |
Re: Labyrinth darstellen
HI ,
Routfinding und ki mann überflüssig machen, Wenn man festlegt das ein sogenanntes "Griechische Labyrinth" generiert werden soll. D.h. es gibt keine Inseln von Wänden, alle Wände sind mit der das Labyrinth umlaufenden Wand verbunden. Dann muss die Maus: 1.Einfach laufen bis sie auf eine Wand trifft 2.der Wand solange Folgen bis sie den Ausgang erreicht hat. :cheers: p.s. Für solche Aufgaben eignen sich Programme wie Niki(der Roboter). :chat: |
Re: Labyrinth darstellen
Hmm...nö, das wäre zu einfach. Fänd das käme fast schummeln gleich, da die Maus ja wirklich gar nichts machen muss. Man legt das ja von anfang an schon fest wie sie nach draußen kommt. Da mach ich lieber eine kleine KI... :-D
|
Re: Labyrinth darstellen
@GetCool: jetzt muss ich nochmal fragen, soll die maus direkt zum ausgang laufen? oder erst das ganze Labyrinth systematisch ablaufen bis sie dann den ausgang erreicht?
Falls sie direkt zum ausgang laufen soll, bräuchtest du nix mehr machen, da ich bei meinem code den Lösungsweg schon berechnet und ins Array geschrieben habe :) |
Re: Labyrinth darstellen
Muss den Weg erst finden...aber ich will von dir auch keine Lösung haben, das mach ich schon alleine :mrgreen: Sonst ist die Herausforderung ja weg...
|
Re: Labyrinth darstellen
Hallo getcool,
mein Vorschlag für die KI: 1) Die Maus überlegt sich "Wie viele Ausgänge hat das Feld auf dem ich stehe? Sind es mehr als einer, dann merke ich mir das Feld, weil ich später noch die anderen Ausgänge prüfen muss." 2) Die Mausl läuft in irgendeine mögliche Richtung, in die sie von diesem Feld aus noch nicht gelaufen ist. 3) Falls das neue Feld mindestens einen Ausgang hat, den die Maus noch nicht benutzt hat, dann fahre bei 1) fort. Ansonsten: Gehe zu einem beliebigen Feld, dass die Maus sich im Schritt 1) gemerkt hat. Den Weg dorthin kennt die Maus, denn sie war ja schonmal dort. Von dort aus führe Schritt 1) aus. So sollte die Maus, nach einiger Rennerei alle Felder, die sie erreichen kann einmal betreten haben, insbesondere den Ausgang. Grüße Seniman |
Re: Labyrinth darstellen
Hi Seniman,
ja, so hab ich mir das auch gedacht. Mal sehen wie das dann in der Realität aussieht. Leider hatte ich die letzten Tage und heute keine Zeit um zu programmieren, aber ab morgen wird rangerauscht und dann sollte es auch nicht mehr all zu lange dauern. Bis jetzt hab ich gerade einmal das Spielfeld mit der Außenwand und der richtige Weg wird auch schon eingezeichnet. Ist allerdings noch nicht so ausgefeilt d.h. der Weg ist mir noch nicht kompliziert genug. Aber das lass ich erstmal so, da der Code Änderungen ohne Probleme zulässt. Sowieso versuch ich das Programm in viele einzelne Procedures und Funktionen zu unterteilen, damit man immer wieder Teilbereiche ohne große Probleme verändern kann. Bis jetzt ist mir das glaube ich ganz ordentlich gelungen. Aber wie schon gesagt, hab noch nicht wirklich viel geschafft (blöde Schule :evil: :mrgreen: ) Wie versprochen kommt der Code hier sowieso rein, wenns fertig ist. Verwende aber keine Codes von euch, das wird schön selber gemacht. Trotzdem bin ich über jede Anregung dankbar. Auch wenn es nur n kleiner Hinweis oder ein kleiner Tipp ist. Schließlich ist es ratsam sich vor dem coden zu überlegen wie man etwas anstellt und die Lösung muss möglichst gut sein, damit man einige Freiheiten für eventuelle Änderungen hat. @Phantom: Hab mir deinen Code jetzt mal genauer angeguckt. Ist echt nicht schlecht, gefällt mir. Mach es aber etwas anders als du, da ich Kästchen nehme und diese je nachdem ob es eine Wand oder so ist farblich kennzeichne (später wirds wohl ein bmp sein, sieht besser aus). Trotzdem glaub ich das der Code mir noch helfen wird. Vielen dank nochmal! |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:02 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-2025 by Thomas Breitkreuz