Консультация № 199785
06.12.2020, 01:13
0.00 руб.
1 16 1
Здравствуйте, уважаемые эксперты! Прошу вас ответить на следующий вопрос:
Есть программа, прикладываю код:
Код:
unit Unit1;

interface

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

type
TForm1 = class(TForm)
GroupBox1: TGroupBox;
GroupBox2: TGroupBox;
PaintBox1: TPaintBox;
EditL: TEdit;
EditH: TEdit;
EditNum: TEdit;
EditRad: TEdit;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Label4: TLabel;
UpDownNum: TUpDown;
ButtonGo: TButton;
ButtonStop: TButton;
ButtonColor: TButton;
ButtonFon: TButton;
ColorDialog1: TColorDialog;
Timer1: TTimer;
procedure FormCreate(Sender: TObject);
procedure ButtonFonClick(Sender: TObject);
procedure ButtonColorClick(Sender: TObject);
procedure ButtonGoClick(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure ButtonStopClick(Sender: TObject);
procedure UpDownNumClick(Sender: TObject; Button: TUDBtnType);
procedure EditNumKeyPress(Sender: TObject; var Key: Char);
procedure ButtonGoKeyPress(Sender: TObject; var Key: Char);
procedure GroupBox1Click(Sender: TObject);
private
{ Private declarations }
procedure Painting;
public
{ Public declarations }
end;

type
TMolekula = class
Fx, Fy, FVx, FVy, FR : Integer;
public
constructor Create(x, y, Vx, Vy : integer);
procedure Wall(i : integer; width, height : integer);
procedure Strike(i : integer);
end;

type
TMolekulaList = Class(TList)
public
procedure Add(Mol : TMolekula);
procedure Clear;
procedure Delete(n : integer);
end;

const MaxSpeed=10;

var
Form1: TForm1;
Molcolor: TColor;
FonColor: TColor;
Mollist: TMolekulaList;
pbWidth, pbHeight: integer;
Rad: integer;

implementation

{$R *.dfm}

Constructor TMolekula.Create(x, y, Vx, Vy : integer);
begin
Fx := x;
Fy := y;
FVx := Vx;
FVy := Vy;
FR := Rad;
end;

function CreateMol: TMolekula;
var x, y, vx, vy : integer;
begin
x := RandomRange(Rad, pbWidth - Rad);
y := RandomRange(Rad, pbHeight - Rad);
Vx:= RandomRange(1, MaxSpeed);
Vy:= RandomRange(1, MaxSpeed);
if RandomRange(1, 100) > 50 then Vx := -Vx;
if RandomRange(1, 100) > 50 then Vy := -Vy;
Result := TMolekula.Create(x, y, Vx, Vy);
end;

Function DistanceBetween(Mol1, Mol2 : TMolekula) : real;
begin
Result:= sqrt(sqr(Mol1.Fx - Mol2.Fx) + sqr(Mol1.Fy - Mol2.Fy));
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
MolColor := clBlack;
FonColor := clSilver;
MolList := TMolekulaList.Create;
Randomize;
end;

procedure TForm1.GroupBox1Click(Sender: TObject);
begin

end;

procedure TForm1.ButtonFonClick(Sender: TObject);
begin
if ColorDialog1.Execute then
FonColor := ColorDialog1.Color;
end;

procedure TForm1.ButtonColorClick(Sender: TObject);
begin
if ColorDialog1.Execute then
MolColor := ColorDialog1.Color;
end;

procedure TForm1.ButtonGoClick(Sender: TObject);
var i, n : integer;
Mol : TMolekula;
begin
PaintBox1.Width := pbWidth;
PaintBox1.Height := pbHeight;
pbWidth := StrToInt(editL.Text);
pbHeight:= StrToInt(editH.Text);
n := strToInt(editNum.Text);
Rad := strToInt(editRad.Text);

if (Rad=0) or (n=0) then
begin
ShowMessage ('Количество молекул и/или радиус молекул не могут быть равны 0');
exit;
end;

if (pbWidth*pbHeight)<Trunc (n*pi*Rad*Rad) then
begin
ShowMessage ('Сосуд маленький для таких молекул');
exit;
end;

MolList.Clear;

MolList.Clear;
for i := 1 to n do
begin
Mol := CreateMol;
MolList.Add(Mol);
end;
timer1.Enabled:=true;
ButtonStop.Caption:= 'Стоп';
end;

procedure TForm1.ButtonGoKeyPress(Sender: TObject; var Key: Char);
begin
if key =#13 then ButtonGo.Click;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var x, y : integer;
i : integer;
Mol : TMolekula;
begin
for i:=0 To MolList.Count-1 do
begin
Mol := TMolekula(MolList.Items[i]);
Mol.Fx := Mol.Fx + Mol.FVx;
Mol.Fy := Mol.Fy + Mol.FVy;
Mol.Wall(i, pbwidth, pbheight);
Mol.Strike(i);
Painting;
end;
end;

procedure TForm1.ButtonStopClick(Sender: TObject);
begin
Timer1.Enabled:= not Timer1.Enabled;
if Timer1.Enabled then
ButtonStop.Caption:= 'Стоп'
else
ButtonStop.Caption:= 'Продолжить'
end;

procedure TForm1.EditNumKeyPress(Sender: TObject; var Key: Char);
begin
if key =#13 then
begin
ButtonGo.Click;
end;
end;
procedure TForm1.UpDownNumClick(Sender: TObject; Button: TUDBtnType);
var Mol: TMolekula;
begin
if ButtonStop.Caption = 'Стоп' then
if Button = btNext then
begin
Mol := CreateMol;
MolList.Add(Mol);
end
else
if MolList.Count > 1 then
MolList.Delete(0);
end;

procedure TMolekula.Wall(i:integer; width, height:integer);
var
Mol : TMolekula;
begin
Mol := TMolekula(MolList.Items[i]);
if Mol.Fx + Rad >= width then
begin
Mol.FVx := -Mol.FVx;
Mol.Fx := width - Rad;
end
else
if Mol.Fy + Rad >= height then
begin
Mol.FVy := -Mol.FVy;
Mol.Fy := height - Rad;
end
else
if Rad >= width then
begin
Mol.FVx := -Mol.FVx;
Mol.Fx := width;
end
else
if Rad >= height then
begin
Mol.FVy := -Mol.FVy;
Mol.Fy := height;
end;
if Mol.Fx - Rad <= 0 then
begin
Mol.FVx := -Mol.FVx;
Mol.Fx := Rad;
end
else
if Mol.Fy - Rad <= 0 then
begin
Mol.FVy := -Mol.FVy;
Mol.Fy := Rad;
end;
end;
procedure TMolekula.Strike(i : integer);
var j : byte;
Mol1, Mol2 : TMolekula;
temp : integer;
begin
Mol1:=TMolekula(MolList.Items[i]);
for j := 0 to MolList.Count - 1 do
begin
if j <> i then
begin
Mol2 := TMolekula(MolList.Items[j]);
if DistanceBetween(Mol1, Mol2) <= 2 * Rad then
begin
temp := Mol1.FVx;
Mol1.FVx := Mol2.FVx;
Mol2.FVx := temp;
temp := Mol1.FVy;
Mol1.FVy := Mol2.FVy;
Mol2.FVy := temp;
break;
end;
end;
end;
end;

procedure TMolekulaList.Add(Mol: TMolekula);
begin
inherited Add(Mol);
end;

procedure TMolekulaList.Clear;
var i: integer;
begin
for i := 0 to Count - 1 do TMolekula(Items[i]).Free;
Inherited Clear;
end;

procedure TMolekulaList.Delete(n: integer);
begin
if (n >=0) and (n <= Count - 1) then
begin
TMolekula(Items[n]).Free;
Inherited Delete(n);
end;
end;

procedure TForm1.Painting;
var
i : Integer;
Mol : TMolekula;
begin
paintBox1.Canvas.Brush.Color := FonColor;
PaintBox1.Canvas.Rectangle(0, 0, pbWidth, pbHeight);
PaintBox1.Canvas.Brush.Color := MolColor;
for i := 0 to MolList.Count - 1 do
begin
Mol := TMolekula(MolList.Items[i]);
PaintBox1.Canvas.Ellipse(Mol.Fx - Rad, Mol.Fy - Rad,
Mol.Fx + Rad, Mol.Fy + Rad);
end;
end;

end.


Вопрос: Каким образом написать функцию, вычисляющую среднюю скорость движения молекул по осям, и выводить эти значения на панель параметров.
Прикрепленные файлы:
008e891f3581b34fc546e8fedf0a7ccad6131ffd.JPG

Обсуждение

давно
Посетитель
404025
131
06.12.2020, 01:18
общий
Скриншот меню программы
Прикрепленные файлы:
fbb2d5d7200c3f62cd3da38d261db709.JPG
давно
Посетитель
404025
131
06.12.2020, 13:57
общий
Адресаты:
Сможете подсказать?
давно
Старший Модератор
31795
6196
07.12.2020, 10:41
общий
Адресаты:
Цитата: Nedix
Сможете подсказать?

В TForm1.Timer1Timer Вы изменяете положение молекул, суммируйте абсолютные величины скорости по осям и делите их на количество молекул
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Посетитель
404025
131
07.12.2020, 11:59
общий
Адресаты:
Формулу не подскажите?
давно
Старший Модератор
31795
6196
07.12.2020, 12:29
общий
Адресаты:
Цитата: Nedix
Формулу не подскажите?


Среднее арифметическое
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Посетитель
404025
131
07.12.2020, 17:40
общий
Адресаты:
Сделал следующим образом:
1. Ввел переменную:
Код:
Avg: record
X,Y: single
end;

2. Прописал в ButtonGo.Click:
Код:
Mol := CreateMol;
Avg.X := Avg.X + Mol.FVx;
Avg.Y := Avg.Y + Mol.FVy;
end;
Avg.X := Abs(Avg.X / n);
Avg.Y := Abs(Avg.Y / n);
Label5.Caption := Format('Средняя скорость по X=%f Y=%f', [Avg.X,Avg.Y]);
Прикрепленные файлы:
23047f72b985b1a4c1063ed6b54ea47a.JPG
давно
Старший Модератор
31795
6196
08.12.2020, 10:18
общий
Адресаты:
Вы не так поняли:
Цитата: Зенченко Константин Николаевич
суммируйте абсолютные величины скорости по осям


Код:
Avg.X := Avg.X + Mol.FVx;
Avg.Y := Avg.Y + Mol.FVy;


ABS -должен быть в этих строках, так как молекула летящая к примеру влево, имеет скорость -3, а две молекулы летящие вправо со скоростями +2 и +1. У Вас суммарная скорость получится 0, а их общая скорость 6
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Посетитель
404025
131
08.12.2020, 17:35
общий
Адресаты:
Не понял вашей мысли. Можете с кодом подсказать?
давно
Старший Модератор
31795
6196
09.12.2020, 12:22
общий
Адресаты:
Цитата: Nedix
Не понял вашей мысли.

  • Скорость не может быть отрицательной - априори, она либо есть, либо её нет.
  • На экране при движении объекта используется смещение dX, dY(у Вас это Mol.FVx и Mol.FVy) взависимости от направления могут быть отрицательными, и их нужно суммировать по абсолютному эначению

    А то получается две молекулы летят в разные стороны, с одинаковым значением, а при суммировании, к примеру по горизонтали друг друга компенсируют.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Посетитель
404025
131
09.12.2020, 12:35
общий
Адресаты:
Это понятно, но что мне необходимо поменять в коде?
давно
Старший Модератор
31795
6196
09.12.2020, 13:04
общий
Адресаты:
Код:
 Avg.X := Avg.X + ABS(Mol.FVx);
Avg.Y := Avg.Y + ABS(Mol.FVy);
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Посетитель
404025
131
09.12.2020, 13:20
общий
Адресаты:
Спасибо. А подскажите возможно ли сделать так, что средняя скорость сама по себе изменялась на панеле, когда двигаются молекулы?
давно
Старший Модератор
31795
6196
09.12.2020, 14:51
общий
Адресаты:
У Вас скорость создается один раз, поэтому скорость будет постоянной.

Можно в TForm1.Timer1Timer при суммировании скоростей рамдомно для каждой молекулы генерировать поправку dX:=RandomRange(0, 2)-1, dY:=RandomRange(0, 2)-1 и добавлять её к Mol.FVx и Mol.FVy, тогда скорость будет меняться каждый вызов таймера и контролировать само изменение, чтобы оно было в диапазоне -MaxSpeed . . +MaxSpeed

Либо в TForm1.ButtonStopClick обнулять её и при пуске снова генерировать новую, тогда после каждого пуска будет новая скорость.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Старший Модератор
31795
6196
09.12.2020, 15:15
общий
Адресаты:
Код:
Vx:= RandomRange(1, MaxSpeed);
Vy:= RandomRange(1, MaxSpeed);
if RandomRange(1, 100) > 50 then Vx := -Vx;
if RandomRange(1, 100) > 50 then Vy := -Vy;

Вместо этих 4-х строк можно оставить 2-е
Код:
Vx:= RandomRange(-MaxSpeed, MaxSpeed);
Vy:= RandomRange(-MaxSpeed, MaxSpeed);
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Посетитель
404025
131
09.12.2020, 16:34
общий
Адресаты:
Спасибо за помощь!
давно
Старший Модератор
31795
6196
09.12.2020, 17:09
общий
это ответ
Здравствуйте, Nedix!

Измените процедуру TForm1.Timer1Timer:
Код:
procedure TForm1.Timer1Timer(Sender: TObject);
var
i,x, y : integer;
Mol : TMolekula;
begin
x:=0;
y:=0;
for i:=0 To MolList.Count-1 do
begin
Mol := TMolekula(MolList.Items[i]);
Mol.FVx:=Mol.FVx+RandomRange(-1, 1);
Mol.FVy:=Mol.FVx+RandomRange(-1, 1);
x:=x+abs(Mol.FVx);
y:=y+abs(Mol.FVy);
Mol.Fx := Mol.Fx + Mol.FVx;
Mol.Fy := Mol.Fy + Mol.FVy;
Mol.Wall(i, pbwidth, pbheight);
Mol.Strike(i);
Painting;
end;
Label5.Caption := Format('Средняя скорость по X=%f Y=%f', [X/MoList.Count,Y/MolList.Count]);
end;


Удачи!
5
Спасибо
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Форма ответа