AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi Allgemeines Problem in meinem Programm/ Threads!?
Thema durchsuchen
Ansicht
Themen-Optionen

Allgemeines Problem in meinem Programm/ Threads!?

Ein Thema von Simme · begonnen am 1. Mär 2010 · letzter Beitrag vom 25. Mär 2010
Antwort Antwort
Seite 1 von 5  1 23     Letzte »    
Simme

Registriert seit: 8. Jan 2010
31 Beiträge
 
Delphi 7 Personal
 
#1

Allgemeines Problem in meinem Programm/ Threads!?

  Alt 1. Mär 2010, 23:04
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 =)
  Mit Zitat antworten Zitat
Klaus01

Registriert seit: 30. Nov 2005
Ort: München
5.771 Beiträge
 
Delphi 10.4 Sydney
 
#2

Re: Allgemeines Problem in meinem Programm/ Threads!?

  Alt 1. Mär 2010, 23:17
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
Klaus
  Mit Zitat antworten Zitat
Simme

Registriert seit: 8. Jan 2010
31 Beiträge
 
Delphi 7 Personal
 
#3

Re: Allgemeines Problem in meinem Programm/ Threads!?

  Alt 1. Mär 2010, 23:22
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 =)
  Mit Zitat antworten Zitat
Benutzerbild von wicht
wicht

Registriert seit: 15. Jan 2006
Ort: Das schöne Enger nahe Bielefeld
809 Beiträge
 
Delphi XE Professional
 
#4

Re: Allgemeines Problem in meinem Programm/ Threads!?

  Alt 1. Mär 2010, 23:27
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 - falls das mit den globalen Vars zutrifft.
http://streamwriter.org

"I make hits. Not the public. I tell the DJ’s what to play. Understand?"
  Mit Zitat antworten Zitat
Simme

Registriert seit: 8. Jan 2010
31 Beiträge
 
Delphi 7 Personal
 
#5

Re: Allgemeines Problem in meinem Programm/ Threads!?

  Alt 1. Mär 2010, 23:40
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 =)
  Mit Zitat antworten Zitat
Benutzerbild von wicht
wicht

Registriert seit: 15. Jan 2006
Ort: Das schöne Enger nahe Bielefeld
809 Beiträge
 
Delphi XE Professional
 
#6

Re: Allgemeines Problem in meinem Programm/ Threads!?

  Alt 2. Mär 2010, 00:17
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.

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:

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
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.
http://streamwriter.org

"I make hits. Not the public. I tell the DJ’s what to play. Understand?"
  Mit Zitat antworten Zitat
Simme

Registriert seit: 8. Jan 2010
31 Beiträge
 
Delphi 7 Personal
 
#7

Re: Allgemeines Problem in meinem Programm/ Threads!?

  Alt 2. Mär 2010, 16:11
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.
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 =)
  Mit Zitat antworten Zitat
Benutzerbild von wicht
wicht

Registriert seit: 15. Jan 2006
Ort: Das schöne Enger nahe Bielefeld
809 Beiträge
 
Delphi XE Professional
 
#8

Re: Allgemeines Problem in meinem Programm/ Threads!?

  Alt 2. Mär 2010, 16:41
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 ..

HTH
http://streamwriter.org

"I make hits. Not the public. I tell the DJ’s what to play. Understand?"
  Mit Zitat antworten Zitat
Simme

Registriert seit: 8. Jan 2010
31 Beiträge
 
Delphi 7 Personal
 
#9

Re: Allgemeines Problem in meinem Programm/ Threads!?

  Alt 2. Mär 2010, 16:53
Ja, ich bin echt ein Brot. Es ist klar, dass da immer 1 steht, wenn ich sie als lokale Variable vereinbare! Naja, Denkblokade.
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?
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#10

Re: Allgemeines Problem in meinem Programm/ Threads!?

  Alt 2. Mär 2010, 17:14
Ich habe Dir im Anhang mal eine kleine Bomber-App geschrieben, die dir das mit dem Timer nochmals verdeutlicht.

Quelltext ist dokumentiert
Angehängte Dateien
Dateityp: zip bomber_154.zip (375,2 KB, 18x aufgerufen)
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 5  1 23     Letzte »    


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:35 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