2015-03-02 2 views
1

Мне нужно написать программу в Delphi, используя формы VCL. Три фигуры, квадратные, шестиугольные и восьмиугольные, должны перемещаться до границы, затем к нижней границе и т. Д. Проблема в том, что моя программа зависает, когда я пытаюсь поместить значения в операторы условий, чтобы остановить перемещение, если координата Y = 0. Хотя она работает (странно), если я положил значение = 180, например.Borland Delphi: Как отладить эту программу?

unit Main; 

interface 

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

type 
TMainForm = class(TForm) 
Image: TImage; 
BeginButton: TButton; 
EndButton: TButton; 
Timer1: TTimer; 
Edit1: TEdit; 
procedure FormActivate(Sender: TObject); 
procedure BeginButtonClick(Sender: TObject); 
procedure EndButtonClick(Sender: TObject); 
procedure Timer1Timer(Sender: TObject); 
private 
{ Private declarations } 
public 
{ Public declarations } 
end; 

var 
MainForm: TMainForm; 

implementation 

uses Figure; 

{$R *.dfm} 
Var 
t:single=0.0; 
L:TSquare; 
S:THexagon; 
C:TOctagon; 
Moving:Boolean=true; 

procedure TMainForm.FormActivate(Sender: TObject); 
begin 
Image.Canvas.Brush.Color:=clWhite; 
end; 

procedure TMainForm.Timer1Timer(Sender: TObject); 
begin 
    L.Move(t); 
    S.Move(-0.2*t); 
    C.Move(0.5*t); 
    t:=t+0.5; 
end; 

procedure TMainForm.BeginButtonClick(Sender: TObject); 
begin 
    L:=TSquare.Create(60,35,Image); 
    S:=THexagon.Create(180,100,Image); 
    C:=TOctagon.Create(300,100,Image); 
    Timer1.Enabled:=true; 
end; 

procedure TMainForm.EndButtonClick(Sender: TObject); 
begin 
    Close; 
end; 

initialization 

finalization 
L.Free; 
S.Free; 
C.Free; 

end. 

И вторая часть:

Unit Figure; 
Interface 
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,   Forms, 
Dialogs, StdCtrls, ExtCtrls; 
Type 
TFigure=Class 
    private x,y, b, 
    dx:integer; 
    Image:TImage; 
    procedure Draw;virtual;abstract; 
    procedure Rel(t:real);virtual; 
    public 
    constructor Create(ax,ay:integer;aImage:TImage); 
    procedure Move(t:single); 
end; 

THexagon=Class(TFigure) 
    private procedure Draw;override; 
end; 

TSquare=Class(TFigure) 
    private procedure Draw;override; 
end; 

TOctagon=Class(TFigure) 
    private procedure Draw;override; 
end; 


Implementation 

Constructor TFigure.Create; 
Begin 
    inherited Create; 
    x:=ax; y:=ay; Image:=aImage; 
End; 

Procedure TFigure.Rel; 
Begin 
    dx:=5*round(t); 
End; 

Procedure TFigure.Move; 
Begin 
    Image.Canvas.Pen.Color:=clWhite; 
    Draw; 
    Image.Canvas.Pen.Color:=clBlack; 
    Rel(t); 
    Draw; 
End; 

Procedure TSquare.Draw; 
Begin 
    b:=70; 
    Image.Canvas.MoveTo(x+round(0.5*b),y-round(0.5*b)); 
    Image.Canvas.LineTo(x-round(0.5*b),y-round(0.5*b)); 
    Image.Canvas.LineTo(x-round(0.5*b),y+round(0.5*b)); 
    Image.Canvas.LineTo(x+round(0.5*b),y+round(0.5*b)); 
    Image.Canvas.LineTo(x+round(0.5*b),y-round(0.5*b)); 
End; 

Procedure THexagon.Draw; 
Begin 
    b:=70; 
    repeat 
    begin 
    Image.Canvas.MoveTo(x+round(0.5*b),y+dx); 
    Image.Canvas.LineTo(x+round(0.25*b),y+round(0.5*b)+dx); 
    Image.Canvas.LineTo(x-round(0.25*b),y+round(0.5*b)+dx); 
    Image.Canvas.LineTo(x-round(0.5*b),y+dx); 
    Image.Canvas.LineTo(x-round(0.25*b),y-round(0.5*b)+dx); 
    Image.Canvas.LineTo(x+round(0.25*b),y-round(0.5*b)+dx); 
    Image.Canvas.LineTo(x+round(0.5*b),y+dx); 
    end; 
    until ((y+round(0.5*b)+dx)<180); 
End; 




Procedure TOctagon.Draw; 
var 
I: Integer; 
p: array[1..9] of tpoint; 
u:extended; 
Begin 
    x:=300; 
    y:=100; 
    u:=0; 
    for I := 1 to 8 do 
    begin 
    p[i].X:=x+round(40*cos(u)); 
    p[i].Y:=y-round(40*sin(u)); 
    u:=u+pi/4; 
    end; 
    repeat 
    begin 
    Image.Canvas.MoveTo(p[8].x,p[8].y-dx); 
    for I := 1 to 8 do 
    Image.Canvas.LineTo(p[i].X,p[i].y-dx); 
    end; 
    until (p[3].y>50); 

End; 
end. 
+0

Ваша процедура рисования шестнадцатеричного цикла - это повторение до тех пор, пока цикл не изменится, чтобы остановить цикл. –

+0

@LURD да, потому что программа не запустится, если я ставлю, например, ((y + round (0.5 * b) + dx) = 0) как условие остановки. – Taxidermic

+0

Процедура рисования должна нарисовать форму только один раз, это была моя точка. –

ответ

10

Delphi поставляется с интегрированным отладчиком. Вы должны использовать его. Вот как начать расследование случая, когда программа, кажется, висит.

  1. Запустите свою программу под управлением отладчика кнопкой «играть».
  2. Воспроизведите ситуацию, которую вы пытаетесь исследовать.
  3. Когда программа зависает, переключитесь на отладчик и нажмите кнопку «пауза». Отладчик прервет выполнение вашей программы, чтобы вы могли исследовать текущее состояние.
  4. Посмотрите на стек вызовов. (Если окно окна вызова еще не видно, вы можете показать его, используя опцию меню «Отладочные окна» в IDE.)

    В стеке вызовов будет отображаться список функций, которые вызвала ваша программа. В верхней части стека будет работать ваша программа в момент паузы. Функция под ним будет функцией, называемой текущей функцией, и так далее, пока вы не достигнете нижней части стека, которая представляет собой основную функцию вашей программы.

    Функция, в которой вы остановились, вероятно, не будет тем, что вы написали. Вместо этого это обычно функция, предоставляемая операционной системой или библиотекой времени Delphi. Вы не хотите их отлаживать. Как правило, вы можете предположить, что они уже работают правильно. Вы ищете ошибку в вместо кода.

  5. Используйте команду «запустить до возвращения», чтобы продолжить работу самой верхней функции. Повторите это, пока вы не достигнете одной из своих функций в стеке вызовов. Вероятно, это преступник.

Теперь, когда вы определили проблемную функцию, пришло время исследовать ее дальше.

  1. Используйте команду отладки «step over» для запуска каждой строки вашей функции по очереди. (Существует также команда «шаг за шагом», но это приведет к выполнению функций, которые не являются вашими, и теперь вас это не интересует.)
  2. Соблюдайте текущие значения переменных в коде. Вы можете навести указатель мыши на переменную, чтобы отладчик отображал ее значение в подсказке инструмента, или вы можете использовать окно отладки часов, чтобы отображать сразу несколько переменных. Они будут обновляться после каждого шага в вашей программе.

    Обратите внимание на значения переменных. У вас уже должно быть некоторое ожидание того, как их ценности должны прогрессировать в ходе вашей программы. Вероятно, вы думали об этой прогрессии, когда писали код. Вспомните это время и сравните результаты, которые вы наблюдаете в отладчике, с вашими предыдущими ожиданиями. Они совпадают? Если да, то продолжайте проходить код. Если они не совпадают, вы обнаружите ошибку. Почини это.

    Другим источником неожиданного поведения является достижение точки в вашей программе, которую вы не ожидали достичь. Может быть, программа называется функцией, которой она не должна быть, или, может быть, вы выполнили цикл больше, чем захотите. Если вы можете решить причину, исправьте ошибку. В противном случае вам может потребоваться резервное копирование.

  3. Определите точку в вашей программе раньше, чем там, где вы наблюдали неожиданное поведение. Найдите синие точки в левом поле редактора кода. Эти точки представляют собой места, где вы можете установить контрольную точку . Нажмите одну из точек, и вы заметите, что линия будет выделена (возможно, красной).

  4. Завершите свою программу и запустите ее снова.

    На этот раз вы должны увидеть остановку отладчика до, программа, похоже, виснет, потому что выполнение сначала достигло точки останова. Отладчик прерывает вашу программу там.

  5. Пройдите по строкам своего кода, как вы это делали раньше, и следите за тем условием, которое заставляет вашу программу отклоняться от ожидаемого пути выполнения. Когда вы определили ошибку, исправьте ее.

+0

Это блестящий ответ, Роб. –

0

Это зависает, потому что цикл повторения до конца никогда не кончится.

repeat 
    begin 
    Image.Canvas.MoveTo(x+round(0.5*b),y+dx); 
    Image.Canvas.LineTo(x+round(0.25*b),y+round(0.5*b)+dx); 
    Image.Canvas.LineTo(x-round(0.25*b),y+round(0.5*b)+dx); 
    Image.Canvas.LineTo(x-round(0.5*b),y+dx); 
    Image.Canvas.LineTo(x-round(0.25*b),y-round(0.5*b)+dx); 
    Image.Canvas.LineTo(x+round(0.25*b),y-round(0.5*b)+dx); 
    Image.Canvas.LineTo(x+round(0.5*b),y+dx); 
    end; 
    until ((y+round(0.5*b)+dx)<180); 

Его состояние основано на у, б и дх значения, но они никогда не меняются в цикле.

Чтобы подтвердить, где он висит, используйте команду «Пауза» в Delphi, затем нажмите F7/F8, чтобы запустить ее шаг за шагом.

Смежные вопросы