unit Unit1; {$mode objfpc}{$H+} interface uses Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, ExtCtrls, Math; type Molecule = record X, Y: Integer; Vx, Vy: Integer; end; { TForm1 } TForm1 = class(TForm) Cold: TLabel; Warm: TLabel; StartStopBtn: TButton; Screen: TPaintBox; procedure ScreenPaint(Sender: TObject); procedure StartStopBtnClick(Sender: TObject); private public end; var Form1: TForm1; IsRunning: Boolean = false; implementation {$R *.lfm} procedure TForm1.ScreenPaint(Sender: TObject); begin end; procedure TForm1.StartStopBtnClick(Sender: TObject); const RMolecule: Integer = 10; { Радиус молекулы } const RHole: Integer = 15; const V: Integer = 7; { Скорость молекулы } const N = 20; { Количество молекул } var angle: Real; { Угол, задающий начальное направление полета } i: Integer; { Счетчик цикла } Mol: array[1..N * 2] of Molecule; { Массив молекул } CurV: Integer; { Выбранаая случайная скорость молекулы } halfScreen: Integer; T1, T2: Integer; { Температуры и количество, статистика } begin if IsRunning then begin IsRunning := false; StartStopBtn.Caption := 'Пуск'; Exit; end; StartStopBtn.Caption := 'Стоп'; IsRunning := true; Randomize; Screen.Refresh; halfScreen := Screen.Width div 2; T1 := V * N; T2 := V * N; for i := 1 to N * 2 do { Цикл по все молекулам } begin { Выбор начального положения молекулы } if i <= N then begin Mol[i].X := RandomRange(RMolecule, halfScreen - RMolecule); end else begin Mol[i].X := RandomRange(halfScreen + RMolecule, Screen.Width - RMolecule); end; Mol[i].Y := RandomRange(RMolecule, Screen.Height - RMolecule); { Выбор нправления и скорости молекулы (1 - V) } angle := Random(360) * Pi / 180; CurV := RandomRange(1, V); Mol[i].Vx := Round(CurV * Sin(angle)); { Получение составляющих } Mol[i].Vy := Round(CurV * Cos(angle)); { скорости молекулы } end; while IsRunning do { Основной цикл } begin { Черчение перегородки } Screen.Canvas.Line(halfScreen, 0, halfScreen, Screen.Height div 2 - RHole - RMolecule); Screen.Canvas.Line(halfScreen, Screen.Height div 2 + RHole + RMolecule, halfScreen, Screen.Height); for i := 1 to N * 2 do { Цикл по всем молекулам } begin Screen.Canvas.Pen.Color := clBtnFace; Screen.Canvas.Ellipse(Mol[i].X - RMolecule, Mol[i].Y - RMolecule, Mol[i].X + RMolecule, Mol[i].Y + RMolecule); { Сдвигаем на новую позицию } Mol[i].X := Mol[i].X + Mol[i].Vx; Mol[i].Y := Mol[i].Y + Mol[i].Vy; if (Mol[i].X > halfScreen - RMolecule) and (Mol[i].X - Mol[i].Vx <= halfScreen - RMolecule) then begin if (Mol[i].Y >= Screen.Height div 2 - RHole) and (Mol[i].Y <= Screen.Height div 2 + RHole) then begin T1 := T1 - V; T2 := T2 + V; end else begin Mol[i].X := halfScreen - RMolecule; Mol[i].Vx := -Mol[i].Vx; end; end else if (Mol[i].X < halfScreen + RMolecule) and (Mol[i].X - Mol[i].Vx >= halfScreen + RMolecule) then begin if (Mol[i].Y >= Screen.Height div 2 - RHole) and (Mol[i].Y <= Screen.Height div 2 + RHole) then begin T2 := T2 - V; T1 := T1 + V; end else begin Mol[i].X := halfScreen + RMolecule; Mol[i].Vx := -Mol[i].Vx; end; end; { Определяем, не вышла ли молекула за границы аквариума } if Mol[i].X > Screen.Width - RMolecule then begin Mol[i].X := Screen.Width - RMolecule; Mol[i].Vx := -Mol[i].Vx; end; if Mol[i].X < RMolecule then begin Mol[i].X := RMolecule; Mol[i].Vx := -Mol[i].Vx; end; if Mol[i].Y > Screen.Height - RMolecule then begin Mol[i].Y := Screen.Height - RMolecule; Mol[i].Vy := -Mol[i].Vy; end; if Mol[i].Y < RMolecule then begin Mol[i].Y := RMolecule; Mol[i].Vy := -Mol[i].Vy; end; Cold.Caption := IntToStr(T1); Warm.Caption := IntToStr(T2); Screen.Canvas.Pen.Color := clBlue; { Рисуем молекулу на новой } Screen.Canvas.Ellipse(Mol[i].X - RMolecule, Mol[i].Y - RMolecule, { позиции } Mol[i].X + RMolecule, Mol[i].Y + RMolecule); end; Sleep(10); { Пауза на 10 миллисекунд } Application.ProcessMessages; end; end; end.