- •Теоретические сведения.
- •Ход работы
- •Самостоятельная работа.
- •5.9 Открываем клавишей f12 окно кода программы Unit3.Cpp. И в конструкторе формы запишем ниже приведенный текст функции.
- •Int X, y;// : Integer;
- •Int VX, Vy ;//: Integer;
- •5.12 Измените код программы так , чтобы холодный и горячий газы были разного цвета.
- •5.13. Проверить работу программы . Убедится, что все кнопки главной формы работают. Оформить самостоятельную работу в отчет.
5.9 Открываем клавишей f12 окно кода программы Unit3.Cpp. И в конструкторе формы запишем ниже приведенный текст функции.
// Это дописываем в код программы
TForm1 *Form1;
struct Molecule
{
Int X, y;// : Integer;
Int VX, Vy ;//: Integer;
};
bool IsRunning = false;
_fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
TLeft->Caption = "0";
TRight->Caption= "0";
StartStopBtn->Caption="Пуск";
}
Запустили проект на выполнение, проверили как изменились надписи на метках и кнопке.
5.10 Помимо разных скоростей, неплохо бы задать для горячих и холодных молекул разные радиусы, чтобы их можно было легко различать. Самый простой способ, это разделить содержимое массива на две одинаковые части. Левую половину в массиве Mol холодными, а вторую – горячими.
Открываем двумя щелчками мыши заготовку для кода программы на кнопке Пуск.
void __fastcall TForm3::StartStopBtnClick(TObject *Sender)
{
сonst int RCold = 7; // радиус холодных молекул
const int RHot = 3; //радиус горячих молекул
const int VHot = 10; //скорость горячих молекул
const int VCold = 5; // скорость холодных молекул
const int RHole = 10; // расстояние отверстия в перегородке
const int N = 20; // количество молекул в одной половине аквариума
float angle ; // угол отклонения
int i ;
Molecule Mol [2*N]; // массив молекул удвоенный, то есть всего 40 молекул
int Lb, Rb; // расстояние в пикселях для левой и правой границ
int V , R ; // скорость и радиус молекул
int N1, N2 ; // количество горячих и холодных молекул
if (IsRunning)
{
IsRunning = false;
StartStopBtn->Caption = "Пуск";
return;
}
StartStopBtn->Caption = "Стоп";
TLeft->Caption = "0";
TRight->Caption= "0";
IsRunning = true;
randomize();
Screen->Refresh();
N1 = N * VCold;
N2 = N * VHot;
Тогда цикл определения исходных молекул на псевдокоде будет выглядеть так:
for( i=0; i<2*N;i++)
{
if ( i<N)
{
Выбрать случайную точку в левой части аквариума
Нарисовать молекулу, задав для неё маленькую скорость и большой радиус
}
else
{
Выбрать случайную точку в правой части аквариума
Нарисовать молекулу, задав для неё большую скорость и маленький радиус
}
Выбрать для молекулы случайное направление
Записать данные молекулы в Mol[i]
}
На языке С++ это выглядит так:
for(i = 0;i<2*N; i++)
{
if (i < N)
{ Lb = RCold; Rb = Screen->Width / 2 - RCold;
V = VCold; R= RCold; }
else
{ Lb = Screen->Width / 2 + RHot; Rb = Screen->Width - RHot;
V = VHot; R = RHot; }
Mol[i].X = RandomRange(Lb, Rb);
Mol[i].Y = RandomRange(R, Screen->Height - R);
angle = random(360)* M_PI /180;
Mol[i].Vx = floor(V * sin(angle));
Mol[i].Vy = floor(V * cos(angle));
}
while(IsRunning)
{ // код «Идеальный газ»
……………….// код 5.10.1—5.10.6
// код «Идеальный газ»
Sleep(10);
Application->ProcessMessages();
}
5.10.1 Тот же прием используется дальше – во время операций стирания/рисования молекул. Если текущее значение переменной цикла меньше или равно N, то нам известно, что радиус молекулы большой, иначе маленький.
5.10.2 Вывести значения температур проще всего в двух элементах TLabel. В нашем случае в качестве температуры вполне сгодится сумма скоростей молекул, находящихся в интересующей нас половине. Изначально температура холодного газа равна N*V_холодного_молекулы, а горячего –N*V_горячей_молекулы. Если какая-нибудь молекула перелетает в другую половину аквариума, то температура первой уменьшается на скорость молекулы, температура второй же увеличивается на то же число.
5.10.3 Не забудем, что при выводе числа в метку( строку) необходимо преобразовать его, используя функцию преобразования из ЦелогочислаВСтроку : IntToStr(число).
5.10.4 Теперь проясним ситуацию с перегородкой. Линия прорисовывается методами:
где параметры а-координаты X, b- координаты Y
Pen->Color= clBlack; // устанавливается цвет линии, черный, можно поменять на любой другой.
MoveTo(a,b); // координаты начала линии
LineTo(a,b); // координаты окончания линии
Линии в середине аквариума надо перерисовывать в каждой итерации цикла while(IsRunning), так как пролетающие молекулы стирают её.
5.10.5 Когда молекула подлетает к перегородке, необходимо как-то определить, что с ней произойдет дальше: перелетит ли она в другую половину аквариума или отразится от перегородки назад . Напоминаем, что в процессе работы с молекулой мы сначала её стираем, потом вычисляем новые координаты, рисуем на новом месте, но прежде теперь надо проверить не произошло ли столкновение с перегородкой. Если такое случилось, то его надо обработать, т.е. молекула должна отлететь от перегородки в обратную сторону, аналогично того как это происходило при встрече со стенками всего аквариума.
ЕСЛИ молекула находится в правой части аквариума, но при этом на предыдущей итерации моделирования молекула была в его левой части
ЕСЛИ молекула находится на уровне отверстия в перегородке
То молекула перелетает из левой части аквариума в правую
ИНАЧЕ
Молекула отлетает от перегородки назад в левую часть
ИНАЧЕ
ЕСЛИ молекула находится в левой части аквариума, но при этом на предыдущей итерации моделирования молекула была в его правой части
ЕСЛИ молекула находится на уровне отверстия в перегородке
То молекула перелетает из правой части аквариума в левую
ИНАЧЕ
Молекула отлетает от перегородки назад в правую часть
На языке С++ это выглядит так
if (Mol[i].X > Screen->Width / 2 - R && Mol[i].X - Mol[i].Vx <= Screen->Width / 2 - R)
{
if (Mol[i].Y >= Screen->Height / 2 - RHole && Mol[i].Y <= Screen->Height / 2 + RHole)
{ N1 = N1 - V; // молекула перелетает, температура изменяется
N2 = N2 + V;
}
else
{ Mol[i].X = Screen->Width / 2 - R; // молекула отражается
Mol[i].Vx = -Mol[i].Vx;
}
}
else
if (Mol[i].X < Screen->Width / 2 + R && Mol[i].X - Mol[i].Vx >= Screen->Width / 2 + R)
{
if (Mol[i].Y >= Screen->Height / 2 - RHole && Mol[i].Y <= Screen->Height / 2 + RHole)
{ N2 = N2 - V; N1 = N1 + V; }
else
{ Mol[i].X = Screen->Width / 2 + R; Mol[i].Vx = -Mol[i].Vx; }
}
5.10.6 Следующие строки дописываем в конце цикла while(IsRunning)
Screen->Canvas->Pen->Color= clBlack;
Screen->Canvas->MoveTo(Screen->Width / 2, 0);
Screen->Canvas->LineTo(Screen->Width / 2, Screen->Height / 2 - RHole);
Screen->Canvas->MoveTo(Screen->Width / 2, Screen->Height / 2 + RHole);
Screen->Canvas->LineTo(Screen->Width / 2, Screen->Height);
TLeft->Caption = IntToStr(N1);
TRight->Caption= IntToStr(N2);
5.11 Объедините код тела цикла из программы «Идеальный газ», добавьте в него фрагменты 5.10.1 - 5.10.6
while(IsRunning)
{
}
Откомпилируйте и запустите программу, работа программы соответствует рисунку приведенному ниже.