![]() |
Snake - Ein Problem mit dynamischen Arrays
Hallo DPler,
Da ich nun Schulferien habe, dachte ich mir, dass ich mal etwas größeres in Angriff nehmen könnte. Gesagt Getan :lol: die Idee war ein Snake Spiel zue porgrammieren (Ja ich komme gleich zu meinem Problem, will nur meinen Gedankengang klar machen :roll: ) Jedenfalls hatten wir gerade in der Schule Arrays. Da mir der Stoff in der Schule nie wirkliche Probleme bereitet, habe ich mich auch diesmal etwas intensiever mit dem Thema befasst und mir neben statischen Arrays nun auch dynamische angesehen. Nun zu meinem eigentlichen Problem bei Snake: Ich hatte mir gedacht, dass die Schlange (frei erfunden) aus 5 Stücken besteht. jedes dieser Stücke soll als ein Rechteck auf einer PainBox gezeichnet werden. D.h. in dem dyn. Array muss es an jeder Stelle 4 Integer Werte geben für Canvas.RectAngle(X1,Y1,X2,Y2). Soweit so gut. Zur Bewegung habe ich mir gedacht, dass das Array um eins nach hinten verschoben wird (der letzte Wert soll bewusst verloren gehen) so entsteht an der ersten Stelle ein Doppelter wert, in dem dann die neue Position des ersten Vierecks gespeichert werden soll. Dort möchte ich dann den doppelten wert nehmen, und dann z.B. in die X-Richtung (also nach Rechts) 10 Addieren. Somit würde das Viereck dann 10 Pixel neben dem zweiten liegen. Das ganze geschieht bei mir in dem OnTimer Event eines Timers. Und Delphi (bzw. ich :oops:) kriege es nicht gebacken. Warum auch immer ändert er Array[0] UND Array[1] So hat er natürlich spätestens nach 5 durchläufen überall die gleichen Koordinaten. Wäre nett, wenn jemand meine Gedankengang nachvollziehen konnte und mir vllt. sagen kann wo mein Fehler im Kopf und/ oder der Programmierung liegt :)
Delphi-Quellcode:
/EDIT:
procedure TForm1.Bewegen(Sender: TObject);
var i: integer; begin // Array nach hinten verschieben, so dass die ersten beiden Werte gleich sind for i:=High(KO_Schlange) downto 1 do KO_Schlange[i] := KO_Schlange[i-1]; // gucken in Welche Richtung sich die schlange bewegen soll, und dann dementsprechend // die Koordinaten des ersten Vierecks ändern (KO_Schlange[0,XXX]) Case Richtung of 0: begin KO_Schlange[0,0] := KO_Schlange[0,0] -22; KO_Schlange[0,2] := KO_Schlange[0,2] -22; end; 1: begin KO_Schlange[0,1] := KO_Schlange[0,1] -22; KO_Schlange[0,3] := KO_Schlange[0,3] -22; end; 2: begin KO_Schlange[0,0] := KO_Schlange[0,0] +22; KO_Schlange[0,2] := KO_Schlange[0,2] +22; end; 3: begin KO_Schlange[0,1] := KO_Schlange[0,1] +22; KO_Schlange[0,3] := KO_Schlange[0,3] +22; end; end; ZeichneSchlange; end; Kann es sein, dass dyn. Arrays nicht die Werte enthalten sondern nur Zeiger ? (sorry wenn es tatsächlich so ist, aber von Zeigern/ etc. hat noch nie ein Infolehrer geredet..) das würde erklären warum immer die Teile vom Array geändert werden, die die selben Werte/ Zeiger besitzen. Denn am Ende würden dann alle auf den einen Wert im Speicher zeigen mit dem dann gerechnet wird. War nur eine Idee die mir gerade noch gekommen ist. |
AW: Snake - Ein Problem mit dynamischen Arrays
Ist ne interessante Vermutung. Bei soetwas weiß ich auch nie auf Anhieb, obs der Fall ist - einfach testen.
Sicherheitshalber kannste ja den Inhalt des Arrays "manuell" rüberkopieren
Delphi-Quellcode:
for i:=High(KO_Schlange) downto 1 do
Move(KO_Schlange[i-1,0], KO_Schlange[i,0], Length(KO_Schlange[i]) * sizeof(KO_Schlange[i,0])); |
AW: Snake - Ein Problem mit dynamischen Arrays
Jau so funktioniert das ganze :D
Danke dir Aphton. Schade, dass einem sowas in der Schule nicht vermittelt/ erklärt wird. Das einzige mal das ich von so einer Unterscheidung gehört habe war hier bzw. in anderen Delphi-Foren. Aber das Thema Schulbildung etc. ist ein gänzlich anderes Thema :roll: Vielen Dank nocheinmal. Bei Interesse würde ich den Programmcode noch etwas aufhübschen und dann hier hochladen 8-) |
AW: Snake - Ein Problem mit dynamischen Arrays
Wer High() sagt kann/sollte auch Low() sagen
|
AW: Snake - Ein Problem mit dynamischen Arrays
'Nabend
Ist das nicht letztendlich Jacke wie Hose ob ich nun downto Low(Array)+1 oder einfach nur downto 1 schreibe ? Oder verbirgt sich da ein Vorteil den ich bloß nicht sehe ? Wenn dem so ist werde ich mir diese Schreibweise mal eineignen. Wobei Komplizierter = cooler ist :lol: MfG |
AW: Snake - Ein Problem mit dynamischen Arrays
Bei einem dynamischen Array ist es Strump wie Socke, da hast du recht. Wenn es sich aber um eine statischenn Array handeln würde, würde der Code mit High()/Low() funktionieren, der mit einer festen Grenze aber nicht.
|
AW: Snake - Ein Problem mit dynamischen Arrays
Wobei sich die Frage stellt warum überhaupt ein Array für Snake? Ich habe vor einiger Zeit mal just4fun Snake geprogt, nur um zu sehen wie schnell ich so ein Game hinkriege, und dabei ist es mir aufgefallen, dass es Quatsch ist ein Array für Snake zu nehmen. Ich schätze man nimmt es weil es im ersten Moment logisch erscheint. Aber wenn man genau drüber nachdenkt, dann ist ein Array für Snake doppeltgemoppelt.
|
AW: Snake - Ein Problem mit dynamischen Arrays
Zitat:
|
AW: Snake - Ein Problem mit dynamischen Arrays
Zitat:
Zu allem Überfluss ist mein Laptop mit nem Bluescreen sbgeschmiert und hat das komplette Delphi Projekt zerschossen. Exakt in dem Moment, in dem ich auf Speichern geklickt habe :evil: auf ein neues |
AW: Snake - Ein Problem mit dynamischen Arrays
Wenn ich zuhause bei meinem Rechner sitze kann ich vielleicht einen kleinen Einblick geben ;)
|
AW: Snake - Ein Problem mit dynamischen Arrays
Servus,
Habe mir da mal ein Paar Gedanken zu dem Denkanstoß gemacht und etwas weitergedacht. Wenn man nun die Koordinaten aller Gegenstände von Snake (Schlangenteile, Äpfel, Wände etc.) in einem Array, also einer Art Karte, speichert, stellt sich mir das Problem, wie ich ihm sage wo sich die Schlange befindet und wo deren Kopf liegt (wobei letzteres noch einfach zu erledigen ist) Müsste dort nicht ein weiteres (kleineres) Array zum Einsatz kommen, wo nur Koordinaten der Schlange gespeichert werden ? Vllt. wäre es noch möglich die "Karte" zu durchsuchen um so an die Stellen zu gelangen, doch dies würde doch enorme Performance Verluste mit sich ziehen oder irre ich da ? :idea: Werde derweil mal weiter Basteln :-D |
AW: Snake - Ein Problem mit dynamischen Arrays
Statt
Zitat:
Deine Fehler sind für mich allein aus der Quelltextbetrachtung nicht nachvollziehbar. Ob dynamische Arrays intern "verzeigert" sind, ist mir nicht bekannt (zumindest gibt der Debugger keine Speicheradressen, sondern Variableninhalte aus), doch selbst wenn, daran können Deine Probleme m.E. nicht liegen. Ich würde an Deiner Stelle - rein aus Interesse - mit dem internen bzw. integrierten Debugger der Sache auf den Grund zu gehen versuchen. |
AW: Snake - Ein Problem mit dynamischen Arrays
Zitat:
Und was den Debugger anbelangt: Kenne mich mit dem nicht so wirklich aus :oops: wenn es sich um dieses Schritt für Schritt ausführen handelt, das man mit F7 Startet, dann habe ich es schon getestet. Dabei habe ich festgestellt, dass das Array genau so verschoben wird, wie ich es haben will. Allerdings kommt dann bei der neuen Wertzuweisung der Fehler: beide werden verändert und nicht nur die Werte an Stelle [0] (so kam ich ja auf die Idee, dass es sich bei dyn. Arrays um Zeiger handelt, und er somit 2mal mit den selben Werten arbeitet. :shock:) What ever. Da ich Notgedrungen (Bluescreen :roll:) eh alles neu machen darf, werde ich mich mal um die Version mit einer "Karte" kümmern. Vllt kommt mir ja noch eine Idee |
AW: Snake - Ein Problem mit dynamischen Arrays
Zitat:
![]() |
AW: Snake - Ein Problem mit dynamischen Arrays
Soso :roll: ständig lernt man mehr :D
Eine weitere Idee war zur Bewegung: Könnte man es mit einem Try .. exept Block lösen ? Wenn sich die Schlange nun aus dem Spielfeld beweg, also aus dem Bereich des Arrays, würde dies ja zu einer Zugriffsverletzung im Speicher führen. Wenn man ihm aber sagt, dass er dann (exept) ein Leben (oder was auch immer) abziehen soll und die Schlange neu positioniert, wäre doch alles in Ordnung oder ? Hoffe ihr versteht, was ich meine :lol: |
AW: Snake - Ein Problem mit dynamischen Arrays
Zitat:
|
AW: Snake - Ein Problem mit dynamischen Arrays
:shock: Das sollte man auch tun. Exceptions als Mittel zur Ablaufsteuerung sind eine ganz schlechte Wahl.
|
AW: Snake - Ein Problem mit dynamischen Arrays
Zitat:
Vllt blicke ich den Post auch nicht weil ich Kopfschmerzen habe :lol: /EDIT: Ahh, es bezog sich vermutlich auf den vorherigen Beitrag, dass man es auch sauberer lösen kann. Hat sich also erledigt ;) |
AW: Snake - Ein Problem mit dynamischen Arrays
Zitat:
[edit] Sry, ich wollte editieren und nicht neu posten. Immerhin sollte der Bezug meiner Aussage nun klarer sein. [/edit] |
AW: Snake - Ein Problem mit dynamischen Arrays
Spontan und sauberer wäre folgendes - Pseudocode:
Code:
- Kopf der Schlange mit dem nächsten Feld vergleichen
- wenn frei dann darf ich mich dahin bewegen - wenn nicht frei - gucken ob es Futter ist > Schlange wachsen lassen usw - gucken ob es die Wand ist - wenn ja dann verloren |
AW: Snake - Ein Problem mit dynamischen Arrays
Zitat:
|
AW: Snake - Ein Problem mit dynamischen Arrays
Du hast nur dann einen Vorgänger, wenn der aktuelle Array-Index > Low(Array) und nur dann einen Nachfolger, wenn der Index < High(Array) ist. Das kann man abfragen, dazu braucht es kein extra Exception-Handling.
|
AW: Snake - Ein Problem mit dynamischen Arrays
Ahhh *klick* Somit müsste ich also vor jeder Bewegung überprüfen lassen, ob in der aktuellen Richtung ein Block vorhanden ist -> falls nicht Leben abziehen/ Beenden. Habe hier ebenfalls auf nicht auf die Syntax geachtet, aber so in etwa würde es dann ausschauen:
Delphi-Quellcode:
Jenachdem ob 'moeglich' True ist bewegt sich dann die Schlange - oder eben nicht. Hätte mir das jetzt eigentlich länger vorgestellt :lol: aber wären nicht "schnellere" Versionen mit Try..Exept zu bevorzugen ? :o Man muss ja nicht immer das Rad neu erfinden :-D
möglich = True
case Richtung of vorwärts: if Array[i+1] > High(Array) then moeglich = False; unten : if Array[i-1] < Low(Array) then moeglich = False; rechts : if Array[i,b+1] > High(Array[i]) then moeglich = False; links : if Array[i,b-1] < Low(Array[i]) then moeglich = False; end; |
AW: Snake - Ein Problem mit dynamischen Arrays
Zitat:
|
AW: Snake - Ein Problem mit dynamischen Arrays
Zitat:
Beispiel Array 40x40 als Byte (mehr braucht man nicht) Vereinbarung: 0 ist leeres Feld, 1 bis 126 Snake, wobei 1 der Kopf ist, 127 ist der Apfel, 128 Wand, Rest 129 bis 255 offen für Erweiterungen Eine Count Variable für die Länge der Schlange, wobei man auf die verzichten könnte, aber wir wollen es nicht zu kompliziert machen Neue Kopfposition berechnen, prüfen auf Kollision mit Apfel oder Wand, bei Apfel Count erhöhen, bei Wand Ende Mit zwei For-Schleifen (X/Y) das Ganze Array durchlaufen. Wert 0 und Werte größer 126 werden ignoriert Alle Werte zwischen 1 und (126 - 1) und 1 erhöhen Kopf-X/Y-Position übertragen und den Wert 1 zuweisen Werte größer Count löschen, bzw. 0 setzten Fertig In einer weiteren Prozedur mit den Werten zeichnen. |
AW: Snake - Ein Problem mit dynamischen Arrays
Zitat:
Warum sollte ich mich gegen das Aute stellen, wenn ich auch einfach die Bremse zum bremsen nutzen kann :gruebel: Viele Wege führen nach Rom ;) |
AW: Snake - Ein Problem mit dynamischen Arrays
Zitat:
|
AW: Snake - Ein Problem mit dynamischen Arrays
Tach,
aaaalso mein erster Post in einem Delphi-Forum ;-) Ich bin kein großer Praktiker und schon gar nicht für Delphi (meine Güte bin ich froh, dass ich nach der Schulzeit nie wieder etwas damit zu tun hatte), aber jetzt mal den *Klugscheiß-Modus an* und aus der Theorie geplaudert: Ein dynamisches Array ist schon eine nette Idee für die Schlange, allerdings gibt es schönere Datenstrukturen dafür. Z.B. eine FIFO (first in first out). Klassisch wäre dies wohl TQueue, ein Erbe von Collection. Was den Speicherplatz angeht: bei solchem "Kleinkram" achtet heute niemand mehr auf Speicher, trotzdem ist es schlechter Stil, Speicher zu verschwenden. Willst du also deine Schlange zwingend in einer eigenen Datenstruktur speichern, wäre es ratsam eine eigene Klasse Schlange anzulegen. Die Klasse bekommt intern einen Fifo, mit dem die aktuell belegten Felder gespeichert werden, und enthält Methoden um den Richtungswechsel zu verarbeiten, Position zurück zu geben ect. Hmm... Jetzt bin ich abgeschweift. Zurück zum FIFO: der Fifo muss nur X Elemente speichern, wobei X die Länge der Schlange ist. Du musst dir keine 4 Elemente Pro Schlangen-Abschnitt merken! Theoretisch reicht ein Punkt (x,y) oder noch schöner nur ein Wert Z. Dazu nummerierst du gedanklich deine Positionen durch. Hast du ein Feld, dass a breit ist und b hoch, so sagt dir z.b. x mod a die Zeile in der ein Element ist und x div b die Reihe. Somit musst du maximal pro Sclangen-Teil noch einen Integer speichern (schöner noch nen byte). *Klugscheiß-Modus aus* Naja, praxisnah war das wohl nicht, aber so wird der Quatsch heute noch an der Uni gelehrt ;-) Greetz |
AW: Snake - Ein Problem mit dynamischen Arrays
Zitat:
|
AW: Snake - Ein Problem mit dynamischen Arrays
Zitat:
Was ist bei deiner Teilnahme im Straßenverkehr die Regel und was die Ausnahme? a) Benutzung der Bremse b) Benutzung des Airbags So viel zu den Beispielen. |
AW: Snake - Ein Problem mit dynamischen Arrays
Das Exceptions zur Ablaufsteuerung genutzt werden, ist in diesem Fall sicher nicht korrekt.
Aber: Viel schlimmer ist, dass sich darauf verlassen wird, das es einen Speicherzugriffsfehler gibt, wenn man außerhalb des Arrays liest. Es ist nicht garantiert, dass der Speicherplatz um das Array herum nicht lesbar ist. Du könntest also durchaus lesbaren Speicher treffen. Noch schlimmer wird es dann, wenn du dann auch noch reinschreibst :pale: Mit einer Indexprüfung sollte dieses Problem zwar nicht auftreten, aber weder ist die standardmäßig nicht eingeschalten, noch sollte man sich darauf verlassen, dass das immer so ist. Zitat:
Verabschiede dich von dem Gedanken, dass dein Hinweis theoretisch war. Programmierer (also evtl. auch nicht-Informatiker) sollte eine Queue kennen und ohne viel nachzudenken programmieren können. |
AW: Snake - Ein Problem mit dynamischen Arrays
Liste der Anhänge anzeigen (Anzahl: 1)
Ich habe mal eben Just4Fun ein Snake-Spiel mit TMemo programmiert.
Ist nicht viel drin, nur ein Level. Gesteuert wird mit den Cursortasten. |
AW: Snake - Ein Problem mit dynamischen Arrays
Zitat:
Zitat:
Zitat:
|
AW: Snake - Ein Problem mit dynamischen Arrays
Zitat:
man bewege sich nach rechts und drücke schnell hintereinander [RUNTER] + [LINKS]. Dann kommt die Fehlermeldung, dass man sich in den Schwanz gebissen hat. Du hast zwar abgefangen, dass man nicht direkt einen Richtungswechsel in die entgegengesetzte Richtung unternehmen kann, allerdings kann man es mit 2 Bewegungen während des Timers Schaffen dis zu umgehen. Ich habe es bei mir so gelöst: Wenn eine Taste gedrückt wird -> Tastendruck := True Wenn nun Tastendruck 'True' ist, können keine Weiteren Eingaben gemacht werden, bis im OnTimer Event Tastendruck wieder auf False gesetzt wird. Hat jemand einen besseren Vorschlag ? P.S.: Klar, dass das nur ein quick-and-dirty Programm ist, wie du schon sagtest. |
AW: Snake - Ein Problem mit dynamischen Arrays
Sooo.
Das Programm ist nun soweit fertig und muss felißig getestet werden :lol: Zu finden ist es hier in der Projekt Abteilung: ![]() |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:15 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