Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Geschriebenes Programm stürzt ab (https://www.delphipraxis.net/144518-geschriebenes-programm-stuerzt-ab.html)

Steve-0 9. Dez 2009 15:30


Geschriebenes Programm stürzt ab
 
Hallo liebe Forengemeinde,
Ich habe ein Problem, dass ich rein gar nicht verstehe, ich soll für die Schule eine Pyramide zeichnen, in der sich immer kleiner werdende andere Pyramiden schachteln mit Hilfe von Variablen zeichnen. Ich bin leider nicht weit gekommen, denn bei dem Eintrag
Delphi-Quellcode:
LineTo (PenPos.X+ Round((Breite-BZ)/2), PenPos.Y-(Breite-BZ));
In einer while Schleife stürzt das Programm ab, nachdem ich den Button zum Zeichnen gedrückt habe, d.h. es reagiert nicht mehr, zeichnet aber auch nicht. Ich kann es nur über Run-->Program Reset schließen, komischerweise läuft das Programm, wenn ich das geteilt durch 2 und den Round Befehl weg lasse, aber dann zeichnet es ja nicht richtig. ICh bin ziemlicher Anfänger, vlt. ist einfach irgendwo ein Fehler, den ich nicht sehe, ich hoffe mal ihr könnt mir das erklären :)

Hier der restliche Programm Text:
Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    ImZeichnen: TImage;
    Zeichnen: TButton;
    procedure ZeichnenClick(Sender: TObject);
  private
    { Private declarations }
    procedure DreieckZeichnen (Ebenen: Integer; Breite: Integer; X1,Y1: Integer);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.DreieckZeichnen(Ebenen: Integer; Breite: Integer; X1,Y1: Integer);
var BZ: Integer;
begin
BZ := Round (Breite/Ebenen);
with ImZeichnen.Canvas do begin
MoveTo (x1,y1);
LineTo (PenPos.X+Round (Breite/2), PenPos.Y-Breite);
LineTo (PenPos.X+Round (Breite/2), PenPos.Y+Breite);
LineTo (x1,y1);
while PenPos.X < Breite do begin
MoveTo (x1+BZ,y1);
LineTo (PenPos.X+ Round((Breite-BZ)/2), PenPos.Y-(Breite-BZ));
end;
end;
end;

procedure TForm1.ZeichnenClick(Sender: TObject);
begin
DreieckZeichnen (7,100,0,100);
end;

end.

Steve-0 9. Dez 2009 16:19

Re: Geschriebenes Programm stürzt ab
 
Damit ihr wisst, wie die Pyramide aussehen soll:
http://www2.pic-upload.de/09.12.09/1dafp6j6omv.jpg

Ich wollte so vorgehen, dass ich erst die Pyramide zeichne (was auch geklappt hat) und dann die Striche einzelnd zeichne. Die Variable Ebenen gibt dabei an, wieviele dieser Striche es gibt (auf dem Bild also 5, in meinem Programm sind es 7), die Variable Breite gibt an, wie breit die Grundpyramide ist, also von linker, unterer Ecke bis rechte, untere Ecke.
Die Variable BZ steht für BreiteZeichnen (hat sich unser Info-Lehrer ausgedacht und es ist unverständlich, ich weiß:D), es ist eine Variable, die den Abstand zwischen den Linien angibt, also immer Breite durch Ebenen, wie ich es geschrieben habe.

Ich hoffe das hilft euch, damit ihr mir helfen könnt, weil ich schreib morgen ne Klausur und das wäre echt wichtig :wink: :wink:

Wolfgang Mix 9. Dez 2009 16:33

Re: Geschriebenes Programm stürzt ab
 
Erstmal herzlich willkommen in der DP :dp:

Ich vermute mal, daß du aus der while-Schleife nicht herauskommst.
So kannst du es testen: Starte das Programm mit F7 (Einzelschrittmodus):
Dann siehst du evtl. wo der Compiler Schwierigkeiten hat.

Grüß

Wolfgang

p80286 9. Dez 2009 16:43

Re: Geschriebenes Programm stürzt ab
 
Dem ist so, da weder Breite noch PenPos.x sich in der Schleife ändern.

Gruß
K-H

Steve-0 9. Dez 2009 17:21

Re: Geschriebenes Programm stürzt ab
 
Danke :thumb: :thumb:

Steve-0 9. Dez 2009 18:28

Re: Geschriebenes Programm stürzt ab
 
Sorry, nochmal ich... Ich kriege partout keine Schleife, ob while oder for, hin, die automatisch mit den gegebenen Variablen die Linien zeichnet, ohne für jede Linie jedesmal einen neuen Befehl einzugeben (was ja die Schleifen unnütz machen würde...). Habt ihr da irgendeine Idee? Ich wäre echt dankbar...

p80286 10. Dez 2009 09:54

Re: Geschriebenes Programm stürzt ab
 
Als kleiner Denkanstoß:
Delphi-Quellcode:
  ...
  while PenPos.X < Breite do begin
    //MoveTo (x1+BZ,y1);
    inc(x1,bz);         {--- ohne Änderung der Koordinate keine Bewegung}
    moveto(x1,y1);
    LineTo (PenPos.X+ Round((Breite-BZ)/2), PenPos.Y-(Breite-BZ));
    form1.repaint;      {-- Denn sieht man was "gezeichnet" wurde}
  end;
Bevor Du Dich beschwerst, das ist immer noch eine Endlosschleife, aber es tut sich etwas und es entsteht nicht der Eindruck da wäre irgendetwas "abgeschmiert".

Mir erschließt sich allerdings immer noch nicht so ganz was Du eigentlich willst.
Die Aufgabenstellung war doch wohl

Zeichne Dreieck ABC
Zeichne weitere Dreiecke die "innerhalb ABC liegen".

Du benötigst also nur eine Dreieckszeichenroutine, die mehrmals mit den passenden Parametern aufgerufen wird.

Gruß
K-H

Phoenix 10. Dez 2009 11:06

Re: Geschriebenes Programm stürzt ab
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich würde es anders angehen.

Du weisst, wieviele Ebenen das Dreieck haben muss.
Diese Ebenen würde ich einzeln Zeichen - und zwar genau drei mal (für jede Seite der Pyramide).

Denn das sind interessanterweise auch genau die Linien, die einmal durch die Pyramide laufen ;-)

Ich nehme Dein Bild als Basis.
Pro Ebene zeichnest Du 5 mal drei Linien (Blau, Orange, Grün, Violett, Rot). In dem Bild sind das eben 5, bei Dir wären das dann eben 2 mehr.

A.
1.) Die Grundlinie (Blau)
2.) Die zweite schräge 'Grundlinie' rechts (Startpunkt = Endpunkt der Grundlinie) um beta (im Gegenuhrzeigersinn) gedreht.
3.) Die dritte schräge 'Grundlinie' links (Startpunkt = Endpunkt von 2.), um gamma (im Gegenuhrzeigersinn) gedreht.

B.
Dann im nächsten Durchlauf berechnest Du die nächst kürzere Linie eine Ebene über der Grundlinie (Orange).
Sie ist genau 1/5 kürzer (beginnt also (1/2)*(1/5) weiter rechts von der Grundlinie) und liegt genau das h einer der kleinen Pyramiden (nach Höhensatz von Euklid) darüber.

Auch diese Linie drehst Du nun um beta und positionierst sie um die entsprechenden Werte ausgehend von der zweiten Grundlinie. Das gleiche wieder für die dritte Seite.

C.
Das Spiel beginn von Vorne. Du verkürzt die Linie um 1/5 und setzt sie um h nach oben und 1/2 * 1/5 nach rechts.
Das gleiche wieder für die zwei anderen gedrehten Linien.

Und so weiter. Bis Du alle 5 Ebenen hast - damit bist Du komplett fertig.

Delphi-Laie 10. Dez 2009 12:14

Re: Geschriebenes Programm stürzt ab
 
Vielleicht etwas zum grundsätzlichen Verständnis:

1. Bedingte Schleifen (also while und repeat/until) sollten in Folge der (Schleifen-)Bedingung (i.d.R.) mehr als einen Durchlauf ausführen - ansonsten ist die Schleifenkonstruktion überflüssig.

2. Die am Schleifenanfang bzw. -ende abgefragte (einfache oder zusammgesetzte) Bedingungsvariable muß sich in Folge der Aktionen innerhalb der Schleife irgendwann ändern, ansonsten wird es tatsächlich eine Endlosschleife (die nur in sehr speziellen Fällen beabsichtigt ist).

Edit: Die Diskussionsüberschrift halte ich für irreführend. Abstürze sind n.m.W. daran gekennzeichnet, daß ein Programm sich beendet (z.B. einfach aus dem Speicher verschwindet oder mit Fehler abbricht). Was Sie meinen, ist eher ein „Aufhängen“ (genau das gleiche blumig-metaphorische Umschreiben wie das Abstürzen), was man auch z.B. mit „verfängt sich in nicht abbrechenbarer Endlosschleife“ oder kürzer „Nicht abbrechenbare, endlose While-Schleife“ besser beschreiben kann.

Daß es ein Programm ist, ist zwar nicht zwingend, denn es könnte auch eine DLL sein, jedoch schon aus Häufigkeitsgründen naheliegend (also ziemlich überflüssig), und daß dieses geschrieben wurde.....wer hätte das gedacht. Vielleicht könnten Sie bitte die Suche anderer erleichtern und den Titel etwas aussagekräftiger (um-)formulieren.

thepaine91 11. Dez 2009 09:58

Re: Geschriebenes Programm stürzt ab
 
Da hier keiner mehr Antwortet und mir langweilig war:
Delphi-Quellcode:
private
  procedure Pyramide_paint(grundflaeche, anzahl_ebenen: Integer);

procedure TForm1.Pyramide_paint(grundflaeche, anzahl_ebenen: Integer);
var i, i2, hoehe, grundflaeche_halb: integer;
begin
//Bug entfernt.
  if frac(grundflaeche / 2) <> 0 then
    grundflaeche := grundflaeche -1;
  hoehe := trunc((grundflaeche * sqrt(3)) /2);
  grundflaeche_halb := grundflaeche / 2;
  with Form1 do
  begin
    Canvas.Pen.Color := clBlack;
    for i := 0 to anzahl_ebenen -1 do
    begin
      Canvas.MoveTo(0 +  grundflaeche_halb * i, hoehe * (anzahl_ebenen - i));
      for i2 := 0 to (anzahl_ebenen -1) - i do
      begin
        Canvas.MoveTo(Canvas.PenPos.X + grundflaeche, Canvas.PenPos.Y);
        Canvas.LineTo(Canvas.PenPos.X - grundflaeche_halb, Canvas.PenPos.Y - hoehe);
        Canvas.LineTo(Canvas.PenPos.X - grundflaeche_halb, Canvas.PenPos.Y + hoehe);
        Canvas.LineTo(Canvas.PenPos.X + grundflaeche, Canvas.PenPos.Y);
      end;
    end;
  end;
end;

// Aufruf könnte so aussehen:
  Pyramide_paint(100, 3);
Form1 kann durch beliebige Komponenete ersetzt werden solange diese .Canvas beherscht.
Ich würde empfehlen mich mal über die richtige Methode zum Konvertieren von Double in int zu informieren und es entsprechend zu ändern.
Unter umständen wird es dir auch ein erfahrenes Mitglied verraten. ;)

mfg nic


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:12 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