Лидеры рейтинга

ID: 226425

Konstantin Shvetski

Мастер-Эксперт

953

Россия, Северодвинск


ID: 259041

Алексеев Владимир Николаевич

Мастер-Эксперт

537

Россия, пос. Теплоозёрск, ЕАО


ID: 401284

Михаил Александров

Академик

351

Россия, Санкт-Петербург


ID: 137394

Megaloman

Мастер-Эксперт

310

Беларусь, Гомель


ID: 400669

epimkin

Профессионал

265


ID: 400484

solowey

Профессор

72


ID: 401888

puporev

Профессор

52

Россия, Пермский край


8.1.6

02.01.2021

JS: 2.2.2
CSS: 4.2.0
jQuery: 3.5.1


 

Создание программ на языках Pascal, Delphi и Lazarus.

Администратор раздела: Зенченко Константин Николаевич (Старший модератор)


Зенченко Константин Николаевич
Статус: Старший модератор
Рейтинг: 267
Gluck
Статус: 6-й класс
Рейтинг: 239
puporev
Статус: Профессор
Рейтинг: 52
 

Перейти к консультации №:
 

Консультация онлайн # 199785
Раздел: • Pascal / Delphi / Lazarus
Автор вопроса: Nedix (Посетитель)
Дата: 06.12.2020, 01:13
Поступило ответов: 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.


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

-----
Прикрепленное изображение (кликните по картинке для увеличения):

Состояние: Консультация закрыта

Здравствуйте, 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;


Удачи!


Консультировал: Зенченко Константин Николаевич (Старший модератор)
Дата отправки: 09.12.2020, 17:09

5
Спасибо
-----
Дата оценки: 09.12.2020, 18:27

Рейтинг ответа:

0

[подробно]

Сообщение
модераторам

Отправлять сообщения
модераторам могут
только участники портала.
ВОЙТИ НА ПОРТАЛ »
регистрация »

Мини-форум консультации № 199785

Nedix

Посетитель

ID: 404025

1

= общий = |  06.12.2020, 01:18 |  цитировать |  профиль |  личное сообщение

Скриншот меню программы

-----
Прикрепленное изображение (кликните по картинке для увеличения):

Nedix

Посетитель

ID: 404025

2

= общий = |  06.12.2020, 13:57 |  цитировать |  профиль |  личное сообщение
Зенченко Константин Николаевич:

Сможете подсказать?

Зенченко Константин Николаевич

Старший модератор

ID: 31795

3

= общий = |  07.12.2020, 10:41 |  цитировать |  профиль |  личное сообщение
Nedix:

Цитата: Nedix
Сможете подсказать?

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

=====
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.
smile

Nedix

Посетитель

ID: 404025

4

= общий = |  07.12.2020, 11:59 |  цитировать |  профиль |  личное сообщение
Зенченко Константин Николаевич:

Формулу не подскажите?

Зенченко Константин Николаевич

Старший модератор

ID: 31795

5

= общий = |  07.12.2020, 12:29 |  цитировать |  профиль |  личное сообщение
Nedix:

Цитата: Nedix
Формулу не подскажите?

smile
Среднее арифметическое

=====
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.
smile

Nedix

Посетитель

ID: 404025

6

= общий = |  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]);

-----
Прикрепленное изображение (кликните по картинке для увеличения):

Зенченко Константин Николаевич

Старший модератор

ID: 31795

7

= общий = |  08.12.2020, 10:18 |  цитировать |  профиль |  личное сообщение
Nedix:

Вы не так поняли:

Цитата: Зенченко Константин Николаевич
суммируйте абсолютные величины скорости по осям


Avg.X := Avg.X + Mol.FVx;
 Avg.Y := Avg.Y + Mol.FVy;


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

=====
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.
smile

Nedix

Посетитель

ID: 404025

8

= общий = |  08.12.2020, 17:35 |  цитировать |  профиль |  личное сообщение
Зенченко Константин Николаевич:

Не понял вашей мысли. Можете с кодом подсказать?

Зенченко Константин Николаевич

Старший модератор

ID: 31795

9

= общий = |  09.12.2020, 12:22 |  цитировать |  профиль |  личное сообщение
Nedix:

Цитата: Nedix
Не понял вашей мысли.

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

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

=====
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.
smile

Nedix

Посетитель

ID: 404025

10

= общий = |  09.12.2020, 12:35 |  цитировать |  профиль |  личное сообщение
Зенченко Константин Николаевич:

Это понятно, но что мне необходимо поменять в коде?

Зенченко Константин Николаевич

Старший модератор

ID: 31795

11

= общий = |  09.12.2020, 13:04 |  цитировать |  профиль |  личное сообщение
Nedix:

Avg.X := Avg.X + ABS(Mol.FVx);
 Avg.Y := Avg.Y + ABS(Mol.FVy);

=====
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.
smile

Nedix

Посетитель

ID: 404025

12

= общий = |  09.12.2020, 13:20 |  цитировать |  профиль |  личное сообщение
Зенченко Константин Николаевич:

Спасибо. А подскажите возможно ли сделать так, что средняя скорость сама по себе изменялась на панеле, когда двигаются молекулы?

Зенченко Константин Николаевич

Старший модератор

ID: 31795

13

= общий = |  09.12.2020, 14:51 |  цитировать |  профиль |  личное сообщение
Nedix:

У Вас скорость создается один раз, поэтому скорость будет постоянной.

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

Либо в TForm1.ButtonStopClick обнулять её и при пуске снова генерировать новую, тогда после каждого пуска будет новая скорость.

=====
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.
smile

Зенченко Константин Николаевич

Старший модератор

ID: 31795

14

= общий = |  09.12.2020, 15:15 |  цитировать |  профиль |  личное сообщение
Nedix:

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);

=====
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.
smile

Nedix

Посетитель

ID: 404025

15

= общий = |  09.12.2020, 16:34 |  цитировать |  профиль |  личное сообщение
Зенченко Константин Николаевич:

Спасибо за помощь!

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