Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Allgemeines Problem in meinem Programm/ Threads!? (https://www.delphipraxis.net/148436-allgemeines-problem-meinem-programm-threads.html)

Simme 1. Mär 2010 22:04


Allgemeines Problem in meinem Programm/ Threads!?
 
Hallo Leute,
ich habe ein Problem. Ich habe schon tausend Sachen probiert, aber mit meinen Informatikkenntnissen komme ich nicht mehr weiter...
Ich weiß nicht, wer von euch das Spiel "Bomberman" kennt. Das versuche ich auf alle Fälle zu programmieren. Ich bin auch schon sehr weit. Das einzige große Problem, für das ich keine Lösung finde, ist das Legen mehrerer Bomben. Wenn ich eine lege, geht alles wunderbar. Doch wenn ich eine weitere lege, bevor die erste gezündet hat, unterbricht er den Prozess zum Legen der ersten Bombe und beginnt den der zweiten Bombe. Ist er damit fertig, beendet er den Prozess der zweiten Bombe. Daraus ergeben sich zwei Probleme:
1. Die Bomben explodieren in entgegengesetzer Reihenfolge, als sie gelegt wurden.
2. Die erste Bombe braucht um einiges länger, als sie benötigen sollte (ist ja logisch, wenn der Prozess unterbrochen wird).

Ich habe einen Freund, der mit Java arbeitet, mir gelegentlich aber auch weiterhilft bei Delphi. Und er meinte, ich müsste mir das Thema "Threads" genauer anschauen. Das habe ich bereits gemacht, nur steige ich dabei überhaupt nicht durch, weil meine Informatikkenntnisse doch (noch) recht beschränkt sind. Deshalb habe ich es erstmal anders probiert.
Delphi-Quellcode:
  If ((GetAsyncKeyState(VK_Shift)) <> 0) And (zuendet = 0) Then //hier, wo man die Taste drückt
    begin
      For zeile := 1 To 11 Do For spalte := 1 To 11 Do
        begin
          links := (spalte - 1) * 65;
          oben := (zeile - 1) * 65;
          If ((links <= maennchen.X) And (links + breite >= maennchen.X) And (oben <= maennchen.Y) And (oben + hoehe >= maennchen.Y)) Then
            begin
              with TImage(FindComponent('Feld' + IntToStr(zeile) + '_' + IntToStr(spalte))) Do
                begin
                  Stretch := True;
                  Proportional := True;
                  Picture.LoadFromFile('Bilder&Animationen\bombe.jpg');
                end;
              x_wert := spalte;
              y_wert := zeile;
            end;
        end;
         bombegelegt := bombegelegt + 1;
         If ((bombegelegt >= laufzahl_bombe1) And (schluss = False)) Then zuendet := 1;
      Repeat
        Application.ProcessMessages;
        oft := oft + 1;
        Label3.Caption := IntToStr(oft);
      Until schluss = True;
      bombespiel := True;
      Label3.Caption := 'Ich bin durch!';
    end;
Also, einfach nur mal der Quellcode zur Reaktion auf einen Tastendruck zum Legen einer Bombe. Eigentlich ist für mein Problem nur der untere Teil von Belangen. In dem oberen Teil wird nur der Ort, an dem die Bombe gelegt werden soll, bestimmt. Legt man dann eine Bombe, kommt er hier ganz normal durch. Er kommt dann in eine If-Funktion, die ich in meinem Versuch ausgelagert habe. Dort wird die Variable schluss auf False gesetzt. Wenn nun also noch eine Bombe gelegt wird, sollte diese sich so lange in der Repeat-Until-Schleife aufhalten, bis die erste Bombe durch ist (denn am Ende dieser If-Funktion wird schluss wieder auf True gesetzt). Dann erst sollte die zweite Bombe da rein gehen. Das Problem: Es funktioniert nicht. Sobald die zweite Bombe gelegt wird, wird wieder der Prozess der ersten unterbrochen, was zu einer Endlosschleife führt, da ja schluss somit nicht auf True gesetzt werden kann.
Konntet ihr mir folgen?
Gibt es eine Möglichkeit, dies auf eine einfache Weise zu machen, wie ich es versucht habe, oder muss ich wirklich mit Threads arbeiten? Wenn ja, dann bräuchte ich eine wirklich richtig einfache Erklärung, damit ich das verstehe...

Es tut mir Leid für diese große Masse an Text. Ich hoffe, ihr könnt mir in irgendeiner Weise weiterhelfen, denn dies ist eine Projektarbeit für die Schule, das heißt, es gibt Noten drauf und ich muss das eigentlich in einer Woche fertig haben...

Liebe Grüße,
Simon =)

Klaus01 1. Mär 2010 22:17

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
Guten Abend,
Delphi-Quellcode:
      Repeat
        Application.ProcessMessages;
        oft := oft + 1;
        Label3.Caption := IntToStr(oft);
      Until schluss {= True};
Wann wird denn schluss true?
Wozu ist die Variable oft da?

Grüße
Klaus

Simme 1. Mär 2010 22:22

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
Hallo,
danke für die Schnelle Antwort. =)

Also, ich hatte vorher die Funktion, wo die Bombe expodiert usw. direkt bei der Tastendruckmethode mit drin. Die habe ich jetzt ausgelagert mit einer weiteren If-Funktion, bei der die Variable bombespiel auf True stehen muss. In dieser Funktion wird schluss ganz am Ende auf True gesetzt.

Die Variable oft hatte für mich nur den Sinn, um zu schauen, wann/ob er irgendwann wieder aus der Schleife rauskommt. Sie hat nichts mit dem Programm an sich zu tun. Soll also heißen, dass die Schleife nur dazu da ist, um das Weitergehen im Quelltext um eine bestimmte, nicht genau festlegbare Zeit zu verzögern.

Lg,
Simon =)

wicht 1. Mär 2010 22:27

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
Lass das mit der Verzögerung. Benutze dafür einen Timer oder das Idle-Event von TApplication.
Leite eine Klasse von TImage ab, was dann die Bombe darstellt, und gib dieser einen Zeitpunkt mit, wann sie explodieren soll. Dann checkst du im Timer/Idle-Event regelmäßig, ob dieser Zeitpunkt überschritten wurde. Wenn das so ist, lässt du die Bombe explodieren.

Edit: Ausserdem habe ich das Gefühl, dass du globale Variablen benutzt? Alle Werte sollten irgendwo an den "Spielfiguren" oder "Sprites" dranhängen. Wenn dein Spiel noch ein wenig komplexer wird wirst du mit dem jetzigen Ansatz ganz schnell die Übersicht verlieren - was auf lange Sicht evtl. dazu führt, alles über den Haufen zu werfen und neu anzufangen :stupid: - falls das mit den globalen Vars zutrifft.

Simme 1. Mär 2010 22:40

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
Okay, dann muss ich mich jetzt mal ganz dumm stellen. Ich habe schon mal hier irgend eine Frage gestellt und da wurde dann auch von einem Timer geredet. Ich weiß nur nicht, wie ein Timer funktioniert und wozu er im Allgemeinen zu gebrauchen ist. Und von einem Idle-Event habe ich leider auch noch nie was gehört. :(
Und ich habe jetzt erstmal angefangen zu verstehen, wie das mit den Klassen und so funktioniert. Da bin ich auch noch nicht besonders bewandert. Ich bin eben noch ein blutiger Anfänger. Selbst wenn ich schon seit 1 1/2 Jahren programmiere. Ich programmiere erst seit einem halben Jahr intensiv und interessiert, vorher war eben nur im Unterricht so ein par Basics. Deshalb arbeite ich im Moment nur in einer Klasse, und zwar der Form1. Mein Freund sagte mir auch schon, ich sollte mal anfangen, objektorientiert zu arbeiten. Nur glaube ich nicht, dass ich das schaffe, bis Freitag oder Montag umzustellen, zumal ich von dem Thema kaum Ahnung habe.

Bezüglich der Variablen: Einige davon sind lokal. Ich habe im Unterricht nie erklärt bekommen, was der Vorteil von lokalen Variablen ist. Das hat mir erst mein Freund vor einer Woche gesagt. Deshalb habe ich noch nicht so viele drin. Aber diese x_wert und y_wert, die praktisch die Stelle speichern, an der die Bombe gelegt wurde, sind beispielsweise lokal.

Und im Übrigen werde ich da noch weiter dran rumbasteln, auch nach der Abgabe. Und ich denke, dann werde ich auch mal überlegen, ob ich nicht das ganze über den Haufen werfe und nochmal von vorne anfange, wo das einfacherer und übersichtlicher ist.

Liebe Grüße,
Simon =)

wicht 1. Mär 2010 23:17

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
Ist natürlich nicht so gut, wenn du unter Zeitdruck bist. Ich versuche trotzdem für dich, ein bisschen Licht ins Dunkle zu bringen :) ...

Zitat:

Okay, dann muss ich mich jetzt mal ganz dumm stellen. Ich habe schon mal hier irgend eine Frage gestellt und da wurde dann auch von einem Timer geredet. Ich weiß nur nicht, wie ein Timer funktioniert und wozu er im Allgemeinen zu gebrauchen ist. Und von einem Idle-Event habe ich leider auch noch nie was gehört.
Den Timer findest du in der Palette unter "System". Den ziehst du einfach auf deine Form (wie alles andere auch). Im Objektinspektor siehst du dann, dass dieser mehrere Eigenschaften besitzt - die wichtigen wären "Enabled" und "Interval". Nun klickst du auf den Timer doppelt drauf - die Prozedur, die für dich dann generiert wird, wird alle Interval-Millisekunden aufgerufen, wenn Enabled=True ist. Du könntest den Timer zum Beispiel alle 100 MS aktiv werden lassen (deine hinterlegte Prozedur wird dann eben immer in dem Intervall aufgerufen), und dann bestimmte Dinge checken - zum Beispiel ob eine Bombe explodieren müsste. Das mit dem Timer ist zwar nicht optimal, aber wohl mehr als ausreichend.

Delphi-Quellcode:
Und ich habe jetzt erstmal angefangen zu verstehen, wie das mit den Klassen und so funktioniert. Da bin ich auch noch nicht besonders bewandert. Ich bin eben noch ein blutiger Anfänger. Selbst wenn ich schon seit 1 1/2 Jahren programmiere. Ich programmiere erst seit einem halben Jahr intensiv und interessiert, vorher war eben nur im Unterricht so ein par Basics. Deshalb arbeite ich im Moment nur in einer Klasse, und zwar der Form1. Mein Freund sagte mir auch schon, ich sollte mal anfangen, objektorientiert zu arbeiten. Nur glaube ich nicht, dass ich das schaffe, bis Freitag oder Montag umzustellen, zumal ich von dem Thema kaum Ahnung habe.
Zeitdruck ist nicht gut, aber es wird sich auf jedenfall auszahlen. Ich versuche das mal im Ansatz zu erklären. Du hast jetzt vermutlich ein paar TImage-Teile auf deine Form gezogen und arbeitest damit. Du benutzt also die Klasse TImage und benutzt Instanzen davon (z.B. deine Bomben, Männchen, Spielfelder..), die für dich automatisch erzeugt werden beim Programmstart (weil du sie per Designer auf die Form gezogen hast). Eine neue Klasse definierst du im "type" Abschnitt ganz oben. Das könnte für eine Bombe so aussehen:

Delphi-Quellcode:
type TBombe = class(TImage)
public
  ExplodierZeit: Cardinal; //Wann macht es Bumm?
end;
Das heißt, dass TBombe ein TImage ist, nur mit der zusätzlichen Eigenschaft "ExplodierZeit".
Damit du später auf die Bomben zugreifen kannst, könntest du dir eine einfache Liste dafür nehmen.
Das könnte dann so in deiner TForm1 aussehen:

Delphi-Quellcode:
type
  TForm1 = class(TForm)
  {...}
  private
    Bomben: TList;
  {...}
end;
Die Liste erzeugst du am besten im OnCreate deiner Form:

Delphi-Quellcode:
Bomben := TList.Create;
Jetzt müssen die Bomben natürlich noch erstellt werden. Dafür gehst du dahin, wo die Taste dafür gedrückt wird, und machst folgendes:

Delphi-Quellcode:
var
  Bombe: TBombe;
begin
  Bombe := TBombe.Create(Self); //Bombe erstellen
  Bombe.Parent := Self; //Bombe auf dem Fenster platzieren
  Bombe.Top := 10; //Koordinaten setzen
  Bombe.Left := 10;
  Bombe.Picture.LoadFromFile('bombe.jpg');
  Bombe.Visible := True; //Anzeigen
  Bombe.ExplodierZeit := GetTickCount + 5000; //Achtung: Bombe explodiert in 5 Sekunden!!!
  Bomben.Add(Bombe); // Der Liste hinzufügen, damit späterer Zugriff klappt
end;
Jetzt ist die Bombe da und du weißt immer, welche Bomben es gerade gibt, einfach über die Liste "Bomben". Damit erspart man sich auch später diesen FindComponent() Kram. Jetzt musst du eigentlich nur noch in deinen Timer gehen und dort folgendes machen:

Delphi-Quellcode:
var
  i: Integer;
begin
  for i := 0 to Bomben.Count - 1 do //Alle Bomben die es gibt durchgehen
  begin
    if GetTickCount > TBombe(Bomben[i]).ExplodierZeit then //Zeit erreicht?
      MessageBeep; //Boom, Bombe ist hochgegangen
  end;
end;
Wenn du dich damit nur ein klein bisschen beschäftigt wirds schnell klar. Ich habe jedenfalls auch lange genug ohne OOP gefrickelt und wenn man das irgendwann lernt, ist das wirklich wie eine Erleuchtung :mrgreen:
Du könntest deine Klassen noch erweitern - zum Beispiel könntest du eine SpielfeldX und SpielfeldY Koordinate an die Klassen packen, und wenn diese gesetzt werden, wird automatisch Top und Left gesetzt, quasi umgerechnet auf Form-Koordinaten aus Spielfeld-Koordinaten heraus. Eine eigene TMaennchen-Klasse könnte noch den Spielernamen beinhalten, Spielerfarbe, oder sonstwas.

Alles hier ist ungetestet, aber sollte den Ansatz hoffentlich klar machen. Ist ärgerlich unter Zeitdruck zu stehen, aber es lohnt sich auf jedenfall - wenn nicht jetzt, dann hoffentlich irgendwann :)


Gute Nacht.

Simme 2. Mär 2010 15:11

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
Hallo =)
Danke für diese umfangreiche Erklärung. Ich habe das jetzt ganz gut verstanden, schätz ich. Ich habe da auch schon einige Vorteile entdecken können. :-D
Aber wahrscheinlich habe ich das mit dem Timer noch nicht ganz geschnallt. Ich habe jetzt alles so umgestellt, wie du es erklärt hast. Ist auch compilierbar. Wenn ich dann die Taste drücke wird auch eine Bombe gelegt, bloß explodiert die nicht. Frage: Kann es sein, dass ich mit dem Timer nur irgendwas ausgeben kann und nicht irgendetwas berechnen oder zuweißen kann? Ich habe nämlich mal einen Test gemacht und einfach eine Variable reingeschrieben, die sich bei jedem Durchgang durch die Timer-procedure um eins erhöhen soll. Dies macht er aber nur ein Mal. Deshalb hatte ich zuerst die Vermutung, dass er nur einmal da reingeht. Ich habe dann aber mal das Label, das mir diese Variable anzeigt, bei dem Tastendruck zum Bombenlegen leer gemacht. Und kurz danach hat er mir die 1 wieder angezeigt. Also durchläuft er die Timer-procedure, ignoriert dabei aber scheinbar meine Zuweisung, die diese Variable immer um eins erhöhen soll. Liege ich da richtig?

Ansonsten verstehe ich sogar alles, was ich da jetzt geschrieben habe und denke auch, dass es klappen müsste, wenn das mit dem Timer dann klappt. Ich wäre über eine baldige Antwort sehr erfreut. =)

Lg,
Simon =)

wicht 2. Mär 2010 15:41

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
Erstmal schön, dass ich dir etwas weiterhelfen konnte.
Wo hast du denn die Variable, die hochgezählt werden soll, deklariert? Du solltest sie in den private-Abschnitt der Klasse TForm1 rein packen. Und die Variable im OnCreate der Form initialisieren (Variable = 0; oder so setzen).
Wenn das noch nicht weiter hilft - eventuell mit dem Debugger schauen oder in einem leeren Testprojekt mal ausprobieren? Wenn ich später Feierabend habe werde ich hier nochmal nachschauen :stupid: ..

HTH

Simme 2. Mär 2010 15:53

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
Ja, ich bin echt ein Brot. Es ist klar, dass da immer 1 steht, wenn ich sie als lokale Variable vereinbare! :D Naja, Denkblokade. :D
Also, ich habe jetzt den Fehler gefunden. Allerdings weiß ich nicht, wie ich ihn beheben kann. Der Wert von Bomben.Count bleibt auf 0. Folglich zählt er bei dem Timer auch nicht, wenn die zeit vorbei ist.
Delphi-Quellcode:
var
  i: Integer;
begin
  for i := 0 to Bomben.Count - 1 do //Alle Bomben die es gibt durchgehen [b]<-- Diese Stelle meine ich.[/b]
  begin
    if GetTickCount > TBombe(Bomben[i]).ExplodierZeit then //Zeit erreicht?
      MessageBeep; //Boom, Bombe ist hochgegangen
  end;
end;
Weißt du, woran das liegt.

Liebe Grüße,
Simon =)

Und wozu ist eigentlich dieses MessageBeep da?

Sir Rufo 2. Mär 2010 16:14

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich habe Dir im Anhang mal eine kleine Bomber-App geschrieben, die dir das mit dem Timer nochmals verdeutlicht.

Quelltext ist dokumentiert

Simme 2. Mär 2010 16:53

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
Tut mir Leid, aber das ist irgendwie zu hoch für mich. :D Kannst du mir nochmal grob erklären, wie das ganze arbeitet? ...

Sir Rufo 2. Mär 2010 17:11

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
Es wäre jetzt sehr hilfreich, wenn du sagen würdest, was du davon verstehst und was nicht.

Eigentlich wurde alles in dem Projekt hier im Thread schon angesprochen.

wicht 2. Mär 2010 18:01

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
Zu der Sache oben von dir:
Wenn Bomben.Count = 0 ist, dann wirst du irgendwo das

Delphi-Quellcode:
Bomben.Add(Bombe);
(nach Bombe := TBombe.Create, wie in meinem Beispiel) vergessen haben. Weil dies fügt die Bombe eben der Liste hinzu, die du in der Schleife im Timer abarbeiten willst. Wenn man sie nicht hinzufügt, bleibt Count (Anzahl der Elemente in der Liste) natürlich auf 0.

Simme 2. Mär 2010 18:18

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
Danke. Das explodieren klappt erstmal, aber das Problem ist, dass ja dann Count auf 1 bleibt und er somit immer wieder durchgeht durch die Schleife. Wie kann ich denn nur die eine Zeile der Liste wieder löschen, um nicht andere Bomben dabei zu beeinflussen?

Lg,
Simon =)

Sir Rufo 2. Mär 2010 18:27

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
Delphi-Quellcode:
idx := 0;
// Alle Bomben in der Liste bearbeiten
while idx < FBombList.Count do
  begin
    KillBomb := ... // Hier muss noch eine sinnvolle Abfrage rein, wenn die Bombe gelöscht werden soll!

    // Soll die Bombe gelöscht werden?
    if KillBomb then
      // Bombe aus der Liste entfernen
      FBombList.Delete( idx )
    else
      begin
        // Auf zur nächsten Bombe in der Liste
        Inc( idx );
      end;
  end;

Simme 2. Mär 2010 19:18

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
Naja, eigentlich soll er's ja immer nach einem Durchlauf löschen. Deshalb brauch ich ja keine Bedingung. Aber das mit Delete funktioniert auch nicht...

wicht 2. Mär 2010 20:53

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
Du brauchst die Abfrage. Du willst erst löschen, wenn die Zeit abgelaufen (Bombe.ExplodeTime oder wie es hieß) ist, oder an der Bombe eine Eigenschaft gesetzt wurde oder so. Bombe wird gelegt, Bombe explodiert, frühstens danach darf sie gelöscht werden.
Was heißt denn "mit Delete funktioniert auch nicht"? Etwas genauer bitte :) .. Hast du die TList benutzt, um die Bomben zu verwalten, oder die TObjectList mit OwnsObjects = True?

Simme 2. Mär 2010 21:10

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
Zitat:

Zitat von wicht
Du brauchst die Abfrage. Du willst erst löschen, wenn die Zeit abgelaufen (Bombe.ExplodeTime oder wie es hieß) ist, oder an der Bombe eine Eigenschaft gesetzt wurde oder so. Bombe wird gelegt, Bombe explodiert, frühstens danach darf sie gelöscht werden.

Ich setze Delete erst hinter die Funktion. Er löscht erst/nur, wenn er in die Funktion reinkommt und damit dann fertig ist.


Zitat:

Zitat von wicht
Was heißt denn "mit Delete funktioniert auch nicht"? Etwas genauer bitte :) ..

Dadurch, dass sich der Timer immer wiederholt, ist das, wenn einmal die Bombe gezündet wurde, eine Enlosschleife. Wenn ich Delete hinter die Funktion (also nach dem Durchlauf) setze, ist keine Veränderung zu sehen. Ich lasse mir ja während des Spielverlaufes immer den Wert von Count anzeigen. Und der wird nicht niedriger. Er bleibt dann immer auf 1.

Zitat:

Zitat von wicht
Hast du die TList benutzt, um die Bomben zu verwalten, oder die TObjectList mit OwnsObjects = True?

Ich verwende eine ganz normale TList, wie es bei dir am Anfang drin stand.

Liebe Grüße,
Simon =)

wicht 2. Mär 2010 21:39

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
Benutze die TObjectList mit OwnsObjects = True, wie in dem Beispiel im Anhang von Sir Rufo. Wenn du dort Delete aufrufst und OwnsObjects = True ist, löscht sie automatisch das Objekt mit. Das heißt der Speicher wird freigegeben und das Teil verschwindet von der Form (Ich habe das noch nie gemacht, aber ich vermute, dass es sich so verhält). Die normale TList kennt die Objekte nur und löscht sie nur aus der Liste beim .Delete, das Objekt an sich bleibt weiterhin bestehen und bleibt deshalb auch auf deiner Form.
Ich lese gerade, dass Count immer auf 1 bleibt - schau mal mit dem Debugger, wie oft dein Programm in BombenListe.Add() und BombenListe.Delete() reinläuft. Da wird was schiefgehen, der Count sollte nicht auf 1 bleiben. Oder die Stelle, die den Count anzeigt, wird zur falschen Zeit aufgerufen.. :stupid:

Simme 2. Mär 2010 22:11

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
Also, ich hab jetzt nochmal ein bisschen getüfftlet. Es funktioniert jetzt soweit. Nur kann ich keine TObjectList verwenden. Da kommt eine Fehlermeldung. Undefinierter Bezeichner. Also, entweder ist meine Delphi-Version zu alt oder es hat einen anderen Grund. Das wäre eigentlich der letzte zu behebende Fehler. Weil sonst überall die Images noch angezeigt werden.

Zitat:

Zitat von "wicht"
Da wird was schiefgehen, der Count sollte nicht auf 1 bleiben.

Das mit dem Count funktioniert jetzt auch.

Danke schon mal für alle Hilfe! Ich sehe dem ganzen hoffnungsvoll entgegen. Das wäre das letzte, was zu beheben wäre. ;)

Eine gute Nacht und ich hoffe, dass ihr da noch Hilfe bieten könnt!

Simon =)

wicht 2. Mär 2010 22:17

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
Ich habe die TObjectList noch nie verwendet.
Ist das eine Fehlermeldung beim Ablauf des Programms, oder noch davor - also beim kompilieren? Ich vermute letzteres?
Quelltext, bitte.

Simme 2. Mär 2010 22:27

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
Ja, der Fehler tritt noch beim Compilieren auf. Hier der Quelltext:
Delphi-Quellcode:
type
  TForm1 = class(TForm)
{...}
private
    { Private-Deklarationen }
    Bomben: TList; //Wenn ich hier TObjectList eingebe, kommt die Fehlermeldung. In der Hilfe-Datei ist die Liste aber vorhanden
    zahl : Integer;
    ja: Boolean;
  public
    { Public-Deklarationen }
  end;
Lg,
Simon =)

Sir Rufo 2. Mär 2010 22:37

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
Wenn so ein Fehler auftritt, dann liegt das daran, dass

a) deine Delphi-Version dieses nicht kennt

oder ... eher wahrscheinlicher

b) du nicht die korrekte Unit eingebunden hast

Um die Unit herauszufinden gibt es (speziell in diesem Beispiel) die Möglichkeit

a) schaue in meinen Quelltext, welche Units ich eingebunden habe und du nicht

oder (geht auch ganz hervorragend)

b) du nutzt die Früchte unseres Herrn und schaust mal dort vorbei Delphi-Referenz durchsuchenTObjectList

und schwupps (oder auch "wuppdi") stellen wir fest, das ominöse TObjectList verbirgt sich in der Unit "Contnrs"


Ich vermute mal, dass du das Programm von mir noch nicht versucht hast zu kompilieren, sonst wäre dir aufgefallen, dass dein Delphi TObjectList kennt.

olee 2. Mär 2010 22:40

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
Wenn man das mächtige Werkzeug namens 'HILFE' oder den Gott 'F1' nutzt,

erfährt man schnell, das TObjectList in der Unit Contnrs deklariert ist.

D.h.: Die unit Contnrs ganz oben in die Uses eintragen ;)

EDIT: Mist! Zu spät :P

MFG

Simme 2. Mär 2010 23:05

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
Ja, bei meiner Hilfe stand's nicht drin. Aber ist jetzt nicht so wichtig. Das funktioniert jetzt. Das Problem ist jetzt noch: Wenn ich mehrere Bomben habe und die erste explodiert ist, kommt oft (nicht immer!) eine Fehlermeldung mit "zugriffsverletzung" usw.
Woher kommt die?

Gute Nacht,
Simon =)

wicht 2. Mär 2010 23:11

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
Herzlichen Glückwunsch zum Geburtstag :party:
Nimm dir den Debugger und finde es so raus. Ich vermute, du greifst irgendwo auf eine Bombe zu, obwohl die Bombe durch das BombenListe.Delete() schon zerstört wurde, also nicht mehr existiert. Benutze ausschließlich die Liste, um auf die Bomben zuzugreifen, dann sollte das nicht passieren, wenn es denn daran liegt.

Simme 3. Mär 2010 22:54

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
Hey,
danke. =)
also, das Problem mit dem Debugger: Im Moment ist von objektorientierter Programmierung bei mir noch nicht so viel zu sehen. Ich weiß sie jetzt aber anzuwenden, hab jetzt aber nicht die Zeit, das noch alles umzustellen. Deshalb hab ich das nur bei den Spielmännchen noch gemacht, weil es das total vereinfacht hat. Allerdings ist das beim Spielfeld nicht so. Somit gehe ich andauernd alle Spielfelder des 11x11 großen Spielfeldes durch. 11x11 sind 121 Spieldfelder. Und durch solche Schleifen muss ich dann immer wieder durch beim Debugger. 121 mal. Das nervt und ist sehr aufwendig.
Er hat halt immer ein Problem damit, wenn eine Bombe explodiert ist. Obwohl ich eigentlich versucht habe, es so einzurichten, dass er die Liste nur löscht, wenn sich keine Bombe mehr auf dem Spielfeld befindet...
ich schau mir das morgen in der Schule nochmal an, ich geh jetzt ins Bett. Bin sehr müde. Wenn du noch eine Idee hast, dann poste sie mir. ;) Ansonsten schreib ich dir morgen nochmal irgendwann und gebe Bericht über den Stand der Dinge.

Eine gute Nacht wünscht
Simon =)

wicht 3. Mär 2010 23:28

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
Nabend.
Ich werd erstmal warten, ob du so noch weiter kommst, aber ein Tipp noch :) ... Wenn du die Schleife über alle Spielfelder machst (du könntest sie auch über alle Mannchen/Bomben machen, dann läuft sie nicht 1xx mal durch :) ), setze deinen Brechpunkt vom Debugger doch in eine weitere Bedingung:

Delphi-Quellcode:
for i := 0 to 11 do
  for n := 0 to 11 do
    if Spielfeld[i][n] is TMaennchen then
    begin
      // tu was mit dem maennchen und hier rein den breakpoint setzen
      TMaennchen(Spielfeld[i][n]).TuWas;
    end;
Dafür muss Spielfeld natürlich so aussehen:

Delphi-Quellcode:
var
  Spielfeld: array[0..10, 0..10] of TObject;
Und man sollte evtl am Anfang jedes Feld mit nil initialisieren. Ist aber auch sehr nervig, wenn sich ein Maennchen bewegt, es immer im Spielfeld auf die neue Koordinate zu setzen. Führt ausserdem dazu, dass auf einem Feld immer nur ein Spieler/Bombe sein kann, nichts gleichzeitig (Nach dem Bombe legen bleibt man ja drauf stehen, deshalb ist das schon ein starkes Minus). Du solltest also eventuell überlegen, ob das Spielfeld nicht über mehrere Listen verwaltet werden soll, wie Bomben und Mannchen, in einer großen Liste. Jede TBombe hat X und Y als Eigenschaft der Klasse, so wie das TMaennchen auch. Dann gehst du einfach über diese Liste und weißst ja direkt, wo das Element, was du in dem Schleifendurchlauf gerade hast, platziert ist... War jetzt doch ein etwas längerer Post, aber egal...

HTH

Simme 4. Mär 2010 21:35

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
So, hallo nochmal!
Also, ich hab nach wie vor keine Ahnung, woran das liegt... Da kommt immer "Das Maximum(0) ist überschritten." Statt 0 steht da auch manchmal 1 oder 2. Ich hab schon einiges probiert. Ich habe echt keine Ahnung, woran es liegt. Es liegt irgendwie daran, dass ich die Bombenobjekte lösche. Aber warum das so ist, raff ich trotzdem noch nicht.
Mal eine kurze Expertenfrage: Wäre es auch akzeptabel, die Bomben einfach nicht zu löschen, sondern sie einfach invisible zu machen? Würde das sehr viel Speicher blockieren? Ist halt pro gelegte Bombe ein Image mehr.
Ich habe übrigens dadurch, dass ich jetzt weiß, wie ein Timer funktioniert, auch das Problem mit der Tastenverzögerung gelöst. =) Ich habe außerdem den Spieler als extra Klasse vereinbart, damit wurde ein Mehrspielermodus jetzt sehr viel einfacherer möglich. Das ist dann mein letzter Fortschritt. Der Mehrspielermodus. Das funktioniert eigentlich alles gut! ;) Ich freu mich! =) Das einzige zu lösende Problem wäre jetzt eben das mit der ObjectList.

Vielleicht hast du/habt ihr ja noch Ideen!?

Liebe Grüße,
Simon =)

Sir Rufo 4. Mär 2010 21:44

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
Ich verstehe gar nicht, warum du mit/zu jeder Bombe ein Image hast.

Eine Bombe hat 3 Zustände

0 - warten
1 - explodieren
2 - explodiert

Diese Zustände würde ich mir in einer Klasse TBombe merken.

Wenn du jetzt eine ImageList nimmst mit 3 Bildern jeweils eins für jeden Zustand,
dann nimmst du je nach Zustand aus der ImageList einfach das Bild raus.

Das macht die ganze Verwaltung wesentlich einfacher.

Einen Vorschlag für die Bomben-Klasse und die Verarbeitung in einer TObjectList habe ich ja schon gegeben.

So, it's on u

Simme 4. Mär 2010 21:56

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
Zitat:

Zitat von Sir Rufo
Ich verstehe gar nicht, warum du mit/zu jeder Bombe ein Image hast.

Wieso verstehst du das nicht? Ich hab ja nicht für jeden Bombenzustand ein Image. Sondern nur für jede Bombe. Dieses Image wird immer erzeugt, wenn man die entsprechende Taste zum Bombenlegen drückt. Und wenn die Bombe explodiert ist, soll dieses Image wieder gelöscht werden aus der Liste. So mein Gedankengang.

Zitat:

Zitat von Sir Rufo
Eine Bombe hat 3 Zustände

0 - warten
1 - explodieren
2 - explodiert

Diese Zustände würde ich mir in einer Klasse TBombe merken.

Wenn du jetzt eine ImageList nimmst mit 3 Bildern jeweils eins für jeden Zustand,
dann nimmst du je nach Zustand aus der ImageList einfach das Bild raus.

Das macht die ganze Verwaltung wesentlich einfacher.

Ich finde, es macht die Verwaltung nicht einfacherer. Das ist ja auch nicht mein Problem. Es geht halt um die Images. Aber du hast wahrscheinlich einen anderen Denkansatz als ich... :roll:

Liebe Grüße,
Simon =)

Sir Rufo 4. Mär 2010 22:05

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
Also hast du das gleiche Image in jeder Klasse einmal drin und auf dem Formular zeigst du das auch noch mit an.

Ja, dann würde ich mir auch Gedanken über den Speicher machen :mrgreen:

wicht 4. Mär 2010 22:08

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
Löscht du eventuell Bombenobjekte aus der Liste mit Hilfe einer Schleife?
Das könnte bei... unsachgemäßer Vorgehensweise nämlich das mit dem Listenindex erklären :mrgreen: .. Ein herrlicher Fehler den glaube ich fast jeder schonmal gemacht hat.

Sir Rufo 4. Mär 2010 22:11

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
Zitat:

Zitat von wicht
Löscht du eventuell Bombenobjekte aus der Liste mit Hilfe einer Schleife?
Das könnte bei... unsachgemäßer Vorgehensweise nämlich das mit dem Listenindex erklären :mrgreen: .. Ein herrlicher Fehler den glaube ich fast jeder schonmal gemacht hat.

Ist aber auch nur ein Blick in die :glaskugel:

Der SourceCode ist so geheim, dass wenn er den hier zeigen würde, er uns sofort alle erschießen müsste :mrgreen:

wicht 4. Mär 2010 22:15

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
Da hast du sowas von Recht. Aber ich würde fast drauf wetten, dass es so ist :stupid: ...
Ich wollte sogar die Erklärung samt Lösungsansatz posten aber... weil es eben :glaskugel: ist, erstmal abwarten ist wohl vernünftiger.

Simme 5. Mär 2010 14:24

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
Macht ihr mich grad dumm? :D

Das Problem ist, dass der Quelltext zum Bombezünden so komplex ist, dass ich das nicht alles mitposten will, vor allem auch, weil ich mich bestimmt dafür schämen müsste, weils sicher sehr viel einfacherer geht. Aber ich versuche, euch den ganzen Code verkürzt zu posten.

Delphi-Quellcode:
procedure TForm2.Timer1Timer(Sender: TObject);
var
  i, e: Integer;
  gesprengt, item : ARRAY[1..4] of Boolean;
  itemx, itemy : Array[1..4] of Integer;
  zeit, x_wert, y_wert, Start : Integer;
begin
  Label5.Caption := IntToStr(Bomben.Count);
  for i := 0 to Bomben.Count - 1 do //Alle Bomben die es gibt durchgehen
    begin
    {...}
    Spieler1.bombegelegt := Spieler1.bombegelegt - 1;
    If Spieler1.bombegelegt < 0 Then Spieler1.bombegelegt := 0;
    If Spieler1.bombegelegt < Spieler1.laufzahl_bombe Then Spieler1.zuendet := 0;
  end;
  Label1.Caption := IntToStr(Spieler1.bombegelegt);
  If (Spieler1.bombegelegt = 0) Then
    begin
      Bomben.Delete(i);
    end;
end;
Also, an sich lösche ich die Bomben erst aus der Liste, wenn sich keine Bombe mehr auf dem Spielfeld befindet. Denn die Variable bombegelegt sagt, wieviele Bomben sich auf dem Spielfeld noch befinden. Das Problem ist nur, dass das mit dem bombegelegt nicht mehr so funktioniert, wie ursprünglich geplant. Naja.

Zitat:

Zitat von wicht
Löscht du eventuell Bombenobjekte aus der Liste mit Hilfe einer Schleife?
Das könnte bei... unsachgemäßer Vorgehensweise nämlich das mit dem Listenindex erklären :mrgreen: .. Ein herrlicher Fehler den glaube ich fast jeder schonmal gemacht hat.

Ja, das mache ich, wie du siehst. Ich hab aber keine Ahnung, ob ich das unsachgemäß mache. Naja, sagt einfach mal bescheid. Wenn ihr noch mehr wollt, sagt bescheid.

Liebe Grüße,
Simon =)

wicht 5. Mär 2010 18:29

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
Keine Anhung was in {...} steht, aber da unten wird nichts in einer Schleife aus der Liste gelöscht.

Delphi-Quellcode:
procedure TForm2.Timer1Timer(Sender: TObject);
var
  i, e: Integer;
  gesprengt, item : ARRAY[1..4] of Boolean;
  itemx, itemy : Array[1..4] of Integer;
  zeit, x_wert, y_wert, Start : Integer;
begin
  Label5.Caption := IntToStr(Bomben.Count);
  for i := 0 to Bomben.Count - 1 do //Alle Bomben die es gibt durchgehen
  begin
    {...}
    Spieler1.bombegelegt := Spieler1.bombegelegt - 1;
    If Spieler1.bombegelegt < 0 Then Spieler1.bombegelegt := 0;
    If Spieler1.bombegelegt < Spieler1.laufzahl_bombe Then Spieler1.zuendet := 0;
  end;

  Label1.Caption := IntToStr(Spieler1.bombegelegt);
  If (Spieler1.bombegelegt = 0) Then
  begin
    Bomben.Delete(i);
  end;
end;
Du greifst einfach unten auf i zu. Ich habe mal gelesen, dass Schleifenvariablen nach der Schleife undefiniert sind oder sein können. Von daher wird dort vermutlich irgendetwas gelöscht, was es in der Liste gar nicht gibt, weil i so ziemlich alles sein kann.
Wenn du in der Schleife Objekte aus der Liste löschen würdest, solltest du die Schleife anders aufbauen. Weil sobald in der Schleife ein Objekt gelöscht wird, hat die Liste ein Element weniger. Die Schleife merkt davon allerdings nichts und geht bis zum alten Count - 1. Aber das Letzte Element in der Liste fehlt ja jetzt danke dem vorherigen Aufruf von Delete(), das führt auch zu einem Fehler. Lösung: Schleife umdrehen:

Delphi-Quellcode:
for i := Bomben.Count - 1 downto 0 do
begin
  Bomben.Delete(i);
end;
Gewöhn dich an den Debugger, damit wärst du da nämlich selbst drauf gekommen, dass du oben nicht in einer Schleife löscht. Ausserdem kann der Debugger Variablenwerte anzeigen - im Delete würdest du dann sehen, was i wirklich ist. Man kommt sehr oft in Situationen, wo das Ding mehr als nützlich ist.. :)

HTH

Simme 6. Mär 2010 23:43

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
Das ist auch nicht der Fehler. An sich ist es logisch, was du gesagt hast. Aber der Fehler besteht weiterhin. Vielleicht hat es noch etwas zu tun mit der allgemeinen Schleife. Muss man da vielleicht auch runterzählen?

Liebe Grüße,
Simon

DeddyH 6. Mär 2010 23:49

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
Wenn das da oben Dein Originalcode ist, sollte Delphi eigentlich eine Warnung ausgeben ("Variable ist nach Schleifendurchlauf undefiniert" oder so ähnlich). Was also heißt: die Schleife rückwärts durchlaufen wie gesagt und innerhalb prüfen, ob das Objekt gelöscht werden sol (und dies dann auch tun).

Sir Rufo 7. Mär 2010 00:01

Re: Allgemeines Problem in meinem Programm/ Threads!?
 
Wieso die schleife rückwärts durchgehen?

Ist eine Möglichkeit ... aber ... da war doch noch der Compiler, der aus Rückwärts auch mal Vorwärts macht oder umgekehrt.

M.E. ist es so besser (da hat man es in der Hand - hoffe ich doch :mrgreen: ):
Delphi-Quellcode:
var
  idx : integer;
begin
  idx := 0;
  while idx < Bomben.Count do
    begin
      if BombeMussGeloeschtWerden then
        Bomben.Delete( idx )
      else
        Inc( idx );
    end;
end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:59 Uhr.
Seite 1 von 2  1 2      

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