161 Востаннє редагувалося ReAl (25.06.2019 09:34:16)

Re: Програма розв'язування задач з фізики! Для учнів 7-го класу.

koala написав:

А від мене - фокус на кілька сотень рядків.
У вас там є повторюваний (з точністю до змінних) фрагмент

і тепер робимо

14..20: begin
           for idx0 := 4 to 8 do
             ComboBox16.Items.Add(UNITS_M_U[idx0]);
           for idx1 := 15 to 21 do
             ComboBox16.Items.Add(UNITS_P_С2[idx1]);
           BitBtn1.Top := 642;
           BitBtn2.Top := 642;
           CheckBox3.Visible := True;
           Options[2] := True;
           CheckBox3.Caption := NumberedString('s%s - Від''ємне переміщення',ComboBox10.ItemIndex-14);
          end;

Було 80 рядків, стало 11. І таких місць кілька.

Дивлюся я на ці ComboBox10 та itemindex = 14 і думаю…
Якщо індекс зробити конкатенацією полів, які означають тип величини (переміщення, час, швидкість, ...), номер змінної такого типу і ще там щось, то таких ручних дій (чому для case 4 потрібно t1? хто про це пам'ятатиме через 5 років?)

          4: RichEdit1.Lines.Add('t = t1');
          5: RichEdit1.Lines.Add('t = t2');
          6: RichEdit1.Lines.Add('t = t3');

і різних

ComboBox10.ItemIndex-14

просто не буде.
NumberedString прийматиме лише індекс, виколупуватиме з нього частини і по типу величини вийматиме рядок, а номер змінної теж просто виколупуватиметься, а не отримуватиметься відніманням магічного числа.

Об'єднання полів і виймання окремого можна робити або бітовими shl, shr, and, or, або цілочисловими div, mod, *, +.
Краще запхати у функції.

type
  PhysicalValue = (Time = 0, Displacement = 1, Speed = 2);

const
  MaxVars = 100; { 0 to 99 }

function ComposeIndex(value : PhysicalValue, n : integer) : integer;
begin
  { перевірити діапазон n ! }
  ComposeIndex := Ord(value) * MaxVars + n;
end;

function GetVarIndex(itemIndex : integer) : integer;
begin
  GetVarIndex := itemIndex mod MaxVars;
end;

function GetVarType(itemIndex : integer) : PhysicalValue;
t : integer;
begin
  t := itemIndex div MaxVars;
  { перевірити діапазон t ! }
  GetVarType := PhysicalValue(t);
end;

Думаю, це дасть змогу уніфікувати (а тому винести в окремі процедури і зробити код коротшим, меншим і зрозумілішим) багато операцій. Різні 't = t1' полетять у const array of string, ...
Може навіть елементи інтерфейсу можна буде формувати динамічно і довільно так само типів/індексів змінних і масивів рядків.

Подякували: ProgramBandera1

162

Re: Програма розв'язування задач з фізики! Для учнів 7-го класу.

ReAl, загалом ви праві, але там настільки все закручене, що я не певен, що так просто вийде. Воно ще більше заплутається.
Ще одна порада:

procedure TForm1.Edit3KeyPress(Sender: TObject; var Key: Char);
begin
 case Key of
  '0'..'9',#8: ;
  ',':
  if Pos(',',Edit3.Text) <> 0  then
   Key := #0;
  '=':
  if Pos('=',Edit3.Text) <> 0  then
   Key := #0;
  '-':
  if Pos('-',Edit3.Text) <> 0  then
   Key := #0;
  else
   Key := #0;
 end;
end;

procedure TForm1.Edit4KeyPress(Sender: TObject; var Key: Char);
begin
 case Key of
  '0'..'9',#8: ;
  ',':
  if Pos(',',Edit4.Text) <> 0  then
   Key := #0;
  '=':
  if Pos('=',Edit4.Text) <> 0  then
   Key := #0;
  '-':
  if Pos('-',Edit4.Text) <> 0  then
   Key := #0;
  else
   Key := #0;
 end;
end;

procedure TForm1.Edit10KeyPress(Sender: TObject; var Key: Char);
begin
 case Key of
  '0'..'9',#8: ;
  '-':  begin
         if Pos('-',Edit10.Text) <> 0  then
         Key := #0;
         Edit10.MaxLength :=3;
        end
  else
   Key := #0;
 end;
end;

procedure TForm1.Edit11KeyPress(Sender: TObject; var Key: Char);
begin
 case Key of
  '0'..'9',#8: ;
  '-':  begin
         if Pos('-',Edit11.Text) <> 0  then
         Key := #0;
         Edit11.MaxLength :=3;
        end
  else
   Key := #0;
 end;
end;

і ще по півдесятка копій таких однакових обробників подій. Їх можна легко об'єднати, якщо обробляти параметр Sender (який вказує на той об'єкт, який створив подію):

procedure TForm1.Edit3KeyPress(Sender: TObject; var Key: Char);
var EditSender: TEdit;
begin
  EditSender := Sender as TEdit; //якщо ви випадково направите сюди не TEdit, матимете виключну ситуацію EInvalidCast
 case Key of
  '0'..'9',#8: ;
  ',':
  if Pos(',',EditSender.Text) <> 0  then
   Key := #0;
  '=':
  if Pos('=',EditSender.Text) <> 0  then
   Key := #0;
  '-':
  if Pos('-',EditSender.Text) <> 0  then
   Key := #0;
  else
   Key := #0;
 end;
end;

{у властивостях Edit4 вказуєте Edit3KeyPress як обробника події KeyPress}

procedure TForm1.Edit10KeyPress(Sender: TObject; var Key: Char);
var EditSender: TEdit;
begin
  EditSender := Sender as TEdit;
 case Key of
  '0'..'9',#8: ;
  '-':  begin
         if Pos('-',EditSender.Text) <> 0  then
         Key := #0;
         EditSender.MaxLength :=3;
        end
  else
   Key := #0;
 end;
end;

{у властивостях Edit11 вказуєте Edit10KeyPress як обробника події KeyPress}

Ну і, звісно, бажано перейменувати такі обробники - на, скажімо, EditKeyPressFloat та EditKeyPress3Symbols (я не певен, що зрозумів, що саме ви хотіли досягти такими обробниками, тому назви умовні).

Подякували: ReAl, ProgramBandera, Torbins3

163

Re: Програма розв'язування задач з фізики! Для учнів 7-го класу.

У FormCreate

ComboBox_.Style := csDropDown;

треба виставляти на самій формі, а не в програмі.

Подякували: ProgramBandera1

164

Re: Програма розв'язування задач з фізики! Для учнів 7-го класу.

І так, порада з обробниками працює трохи гірше, якщо там є посилання на інші елементи. Наприклад,
ComboBox10Change посилається на ComboBox10 та ComboBox16, а
ComboBox11Change - на ComboBox11 та ComboBox17.
Простим перетворенням Sender на ComboBox при об'єднанні ми отримаємо лише ComboBox10 (та ComboBox11). Доведеться дописати некрасивий шматок на кшталт

if Sender = ComboBox10 then begin
  ComboSender := ComboBox10;
  ComboTarget := ComboBox16;
end
else if Sender = ComboBox11 then begin
  ComboSender := ComboBox11;
  ComboTarget := ComboBox17;
end;

Загалом і це можна виправити, але то вже серйозніше.

Подякували: ProgramBandera1

165

Re: Програма розв'язування задач з фізики! Для учнів 7-го класу.

koala написав:

ReAl, загалом ви праві, але там настільки все закручене, що я не певен, що так просто вийде. Воно ще більше заплутається.

Тоді саме час думати — чи не час подумати над аналізом всього цього згори не зважаючи на вже написаний код.
Бо інакше ще за рік код стане зовсім некерованим.

Подякували: ProgramBandera, leofun012

166

Re: Програма розв'язування задач з фізики! Для учнів 7-го класу.

ReAl написав:

Бо інакше ще за рік код стане зовсім некерованим.

Так воно уже давно некероване.

Подякували: ProgramBandera, leofun012

167 Востаннє редагувалося ProgramBandera (25.06.2019 19:49:17)

Re: Програма розв'язування задач з фізики! Для учнів 7-го класу.

koala написав:

Так воно уже давно некероване.

Ні ні він поки що, керований! *OK* Алгоритм там дуже простий!
Ліва частина ComboBox 9-14 - це змінні, Які беруть значення з Edit 1-6 відповідно.
Права частина ComboBox 15-20 вказує на те чи потрібно значення конвертувати в міжнародну систему одиниць (CI).
І в залежності який вибраний (у верху)  ItemIndex (Фізичне значення) в ComboBox 1-4, програма перевіряє чи в ComboBox 9-14 є такі величини, якщо є то програма перераховує їх за однією з формул та формує відповідь, якщо ні виводить повідомлення "Недостатньо даних".
ComboBox 5-8 робить зворотнє конвертування з міжнародної системи одиниць (CI) в метричну.
І це все обов'язково крок за кроком виводиться в RichEdit1: TJvRichEdit;

Пригадайте як розв'язували задачі з фізики в школі!
Змінні з індексами 1, 2, 3, 4, 5, 6 призначені для розв'язування задачі по діях.
Наприклад:
Нам потрібно знайти переміщення якогось (першого) тіла s яке визначається формулою s=v*t. Але нам не дано ні v ні t.
А за умовою задачі нам дано що швидкість другого тіла така сама як швидкість першого тіла і дано s2, t2.
Отже v2 := s2/t2; v := v2;
А час третього тіла такий самий як час першого тіла і дано s3, v3.
Отже t3 := s3/v3; t :=t3;
І тоді вже робимо s := v*t.
Ось для чого індекси 1, 2, 3, 4, 5, 6 для змінних

А в програмі воно буде виглядати як

 14  : begin
        Time3;
        Speed2;
        Moving;
       end;

А код виходить довгий через те (відповім чесно) бо я не вмію його писати, я тільки минулого року взяв в руки книгу Інформатика 11-й клас і по ній розпочав вчитися. тому й пишу по сім локальних процедур для кожного значення Time, Time1, Time2, Time3, Time4, Time5, Time6, Moving, Moving1 ... і так далі

168

Re: Програма розв'язування задач з фізики! Для учнів 7-го класу.

Одразу звертаю вашу увагу на те, що у наведеному прикладі 3 та 2 - залежні (певним чином) від 14 числа, а Time5 навряд буде сильно відрізнятися від Time3, окрім якогось значення, пов'язаного із числом чи то 3, чи то 5, залежно від функції. Тобто має сенс розкласти це на

1..27: time_num := отримати_номер_time(те_що_стоїть_в_case);
speed_num := отримати_номер_speed(те_що_стоїть_в_case);
Time(time_num);
Speed(speed_num);
Moving;

Звісно, можна без проміжних змінних, одразу підставити параметрами:

1..27: Time(отримати_номер_time(те_що_стоїть_в_case));
Speed(отримати_номер_speed(те_що_стоїть_в_case));
Moving;

1..27 - це наприклад, я не знаю, які саме мають бути числа.
Тим більше підозрюю, що, якщо Moving розв'язує саме такі рівняння, то йому і слід передавати ці параметри:

1..27: Moving(отримати_номер_time(те_що_стоїть_в_case), отримати_номер_speed(те_що_стоїть_в_case));

Але це стосується конкретно вашого прикладу. У цілому ж, боюся, ви взялися за заздалегідь заважке для себе завдання. Наведу простий приклад:

Автомобіль їхав зі швидкістю 60 км/год 30 хвилин, а потім ще 15 хвилин. Скільки він проїхав?

Задача - так само елементарна. Але ваш код, швидше за все, нічого із нею не зробить, бо не розрахований на таку формулу (s=v*(t+t1)). А якщо ви почнете додавати окремими випадками всі можливі подібні ситуації, код вимушено збільшиться в рази, бо знадобляться розв'язки відносно s,v,t і t1. Але при цьому залишаться нерозглянутими ситуації s=v*(t+t1+t2)... Звісно, можна зробити програму, що розкладатиме подібні вирази і знаходитиме рішення, ще й коментуватиме кожен крок ("Переносимо t1 в ліву частину", "Обчислюємо значення в дужках" і т.д.). Але який сенс від того для користувача?

Зайдемо з іншого боку. Яка мета вашої програми? Навчити користувача правильно розв'язувати задачі з конкретного фіксованого набору?

Подякували: ReAl, ProgramBandera, Torbins, leofun014

169 Востаннє редагувалося ProgramBandera (27.06.2019 20:13:41)

Re: Програма розв'язування задач з фізики! Для учнів 7-го класу.

koala написав:

Але це стосується конкретно вашого прикладу. У цілому ж, боюся, ви взялися за заздалегідь заважке для себе завдання. Наведу простий приклад:
Автомобіль їхав зі швидкістю 60 км/год 30 хвилин, а потім ще 15 хвилин. Скільки він проїхав?


Зайдемо з іншого боку. Яка мета вашої програми? Навчити користувача правильно розв'язувати задачі з конкретного фіксованого набору?

Дякую пане koala! Я в знаю що я взявся за заважке для себе завдання. І я знаю що ця програма не буде розв'язувати 100% задач (це не комерційний проект і я ж не штучний інтелект розроблюю  :) ). Я прагну її довести до 50-75% відсотків розв'язків і це буде дуже добре.
Ну а з вашої задачі можна визначити t1 та t2 і на калькуляторі додати t1 + t2 так взнаємо загальний час t. Але це поки що, в майбутньому  я планую за допомогою CheckBox додавати якісь опції на форму (створювати їх динамічно), та це буде в майбутньому. Наразі задача стоїть дописати основні функції до першого вересня і розпочати роздачу програми в якомусь торенті. Нехай діти тестують її та на пошту відправляють листи що їх не влаштовує в програмі.

170

Re: Програма розв'язування задач з фізики! Для учнів 7-го класу.

ReAl написав:
ProgramBandera написав:

Поставте собі Community Edition: https://www.embarcadero.com/products/delphi/starter Вона на рік безкоштовна, а через рік можна буде скачати нову версію.

Воно, звичайно, мені звідси дуже легко щось сказати, але я думаю, що це Вам переповзти на Lazarus було б краще — у довготривалій перспективі. Кросплатформовість і підтримка спільноти. Ніякиих «а через рік», просто вільне ПЗ.
Взагалі починати треба було з нього.
Я ще зрозумів би, якби це був проект, якому років 20+. Знаю один, який з 1996 тягнеться і в якому, мабуть, за півтораста тисяч рядків, за 95% яких сам автор забув, як вони працюють, бо років 10 не чіпав і не зазирав у ті файли.

Це погана порада, бо для Делфі в десятки разів більше різних корисних компонент та бібліотек. З різною довідковою інформацією та уроками те саме. Власне, ви у цьому уже переконалися самі.

ProgramBandera написав:

Ні ні він поки що, керований! *OK* Алгоритм там дуже простий!
Ліва частина ComboBox 9-14 - це змінні, Які беруть значення з Edit 1-6 відповідно.
Права частина ComboBox 15-20 вказує на те чи потрібно значення конвертувати в міжнародну систему одиниць (CI).
І в залежності який вибраний (у верху)  ItemIndex (Фізичне значення) в ComboBox 1-4, програма перевіряє чи в ComboBox 9-14 є такі величини, якщо є то програма перераховує їх за однією з формул та формує відповідь, якщо ні виводить повідомлення "Недостатньо даних".
ComboBox 5-8 робить зворотнє конвертування з міжнародної системи одиниць (CI) в метричну.

Якщо в програмі є елементи інтерфейсу, що повторюються і працюють групами, то пора застосовувати так звані фрейми. Приблизно як у цьому відео: https://youtu.be/emPh3_UBg-I?t=1814 Документація: http://docwiki.embarcadero.com/RADStudi … ith_Frames Взагалі, фрейми знаходяться дуже близько до об'єктно-орієнтованого програмування, з яким вам варто познайомитися. Призначення цього підходу - розбити складні програми на менші, відносно незалежні, шматочки, з якими буде легко працювати. Наприклад у вас могли б бути окремі типи Швидкість, Час, Відстань. Та об'єкти Швидкість1, Швидкість2, Час1 і так далі.

Подякували: ProgramBandera1

171

Re: Програма розв'язування задач з фізики! Для учнів 7-го класу.

Torbins написав:

Наприклад у вас могли б бути окремі типи Швидкість, Час, Відстань. Та об'єкти Швидкість1, Швидкість2, Час1 і так далі.

Пане Torbins якщо ви заглянете ось по цьому посиланню https://github.com/ProgramBandera/-7-0 де я на github виклав проект то ви побачите що в процедурі procedure TForm1.ToCalculate; в мене є локальні процедури час, шлях переміщення і так далі, а як їх перетворити на окремі типи та об'єкти наразі я навіть приблизно не знаю, буду переглядати уроки з ваших посилань можливо щось і придумаю.

172

Re: Програма розв'язування задач з фізики! Для учнів 7-го класу.

ProgramBandera написав:

Пане Torbins якщо ви заглянете ось по цьому посиланню https://github.com/ProgramBandera/-7-0 де я на github виклав проект то ви побачите що в процедурі procedure TForm1.ToCalculate; в мене є локальні процедури час, шлях переміщення і так далі, а як їх перетворити на окремі типи та об'єкти наразі я навіть приблизно не знаю, буду переглядати уроки з ваших посилань можливо щось і придумаю.

Об'єктно-орієнтоване програмування (ООП) - це наступний крок після процедурного. Якщо у вас уже є купа процедур, значить ви, мабуть, уже почали помічати, що часто вам доводиться передавати одні й ті ж параметри по черзі в декілька різних процедур, а також, що у вас є процедури які працюють лише з одним конкретним типом параметрів. Звідси до ООП зовсім недалеко.

Подякували: leofun01, ProgramBandera2

173

Re: Програма розв'язування задач з фізики! Для учнів 7-го класу.

ProgramBandera написав:

Нехай діти тестують її та на пошту відправляють листи що їх не влаштовує в програмі.

Можна і на пошту, звичайно, але вам, як розробнику вільного ПЗ, буде зручніше так :
Нехай діти тестують її та на GitHub відправляють issue що їх не влаштовує в програмі.


Torbins написав:
ReAl написав:

переповзти на Lazarus було б краще — у довготривалій перспективі.

Це погана порада, бо для Делфі в десятки разів більше різних корисних компонент та бібліотек.

Не знаю скільки там для Делфі бібліотек, може і більше, але автор програми отримав би більшу підтримку від спільноти, якби проект був на Lazarus.

Подякували: ProgramBandera, ReAl2

174 Востаннє редагувалося ProgramBandera (29.07.2019 21:46:10)

Re: Програма розв'язування задач з фізики! Для учнів 7-го класу.

Добрий вечір добрим людям!
Підкажіть будь ласка як вписати Рі в функцію формат?
Переписую в коді ось такі рядки:

RichEdit1.Lines.Add (FloatToStr(Variables[2,0]) + 'м. / ' + FloatToStr(Variables[1,0]) + 'с. = ' + FloatToStr(Variables[4,0]) + 'м.с.');

на рядки

RichEdit1.Lines.Add (Format('%.25gм. / %.25gс. = %.25gм.с.',
                       [Variables[3,0], Variables[1,0], Variables[4,0]]));

А як правильно записати ось такий рядок, якщо там є Рі FloatToStr(Pi)

RichEdit1.Lines.Add ('(2 * ' + FloatToStr(Pi) + ' * ' + FloatToStr(Variables[43,0]) + 'м.)' + ' / ' + FloatToStr(Variables[7,0]) + 'с. = ' + FloatToStr(Variables[4,0]) + 'м.с.');

175 Востаннє редагувалося leofun01 (29.07.2019 21:49:34)

Re: Програма розв'язування задач з фізики! Для учнів 7-го класу.

ProgramBandera написав:

А як правильно записати ось такий рядок, якщо там є Рі FloatToStr(Pi)

RichEdit1.Lines.Add ('(2' + FloatToStr(Pi) + FloatToStr(Variables[43,0]) + 'м.)' + ' / ' + FloatToStr(Variables[7,0]) + 'с. = ' + FloatToStr(Variables[4,0]) + 'м.с.');
RichEdit1.Lines.Add('(2*pi*' + FloatToStr(Variables[43,0]) + 'м.)' + ' / ' + FloatToStr(Variables[7,0]) + 'с. = ' + FloatToStr(Variables[4,0]) + 'м.с.');

Але "RichEdit1" - це не добре. І "Variables[43,0]" теж. Це я про імена контролів і розміри масивів.

Подякували: ProgramBandera1

176 Востаннє редагувалося ProgramBandera (29.07.2019 22:10:53)

Re: Програма розв'язування задач з фізики! Для учнів 7-го класу.

Питання знято! Вже сам додумався. Код буде ось такий

RichEdit1.Lines.Add (Format('(2 * %.25g * %.25gм.) / %.25gс. = %.25gм.с.',
                       [Pi, Variables[43,0], Variables[7,0], Variables[4,0]]));

На кінець-то я починаю розуміти функцію Format!


Вивело так як треба!

Знайти:
v - Швидкість  км/год. - Кілометрів за годину
 
 
 
------------
Дано:
T - Період обертання  37  год. - Годин
R - Радіус  40  км. - Кілометрів
   
   
   
   
------------
CI:
T = 37*3600
T - Період обертання  =  133200  Секунд
R = 40*1000
R - Радіус  =  40000  Метра(ів)
------------
Розв'язання:
ФIЗИКА — НАУКА ПРО ПРИРОДУ

Швидкiсть руху тiла  — це фiзична величина, яка показує, яку вiдстань проходить тiло за одиницю часу в напрямi руху. Позначають швидкiсть руху тiла малою латинською лiтерою v.

Визначаємо швидкість рівномірного руху по колу

(2 * 3,14159265358979 * 40000м.) / 133200с. = 1,88684243458846м.с.

177

Re: Програма розв'язування задач з фізики! Для учнів 7-го класу.

ProgramBandera написав:

Питання знято! Вже сам додумався. Код буде ось такий

RichEdit1.Lines.Add (Format('(2 * %.25g * %.25gм.) / %.25gс. = %.25gм.с.',
                       [Pi, Variables[43,0], Variables[7,0], Variables[4,0]]));

(2 * 3,14159265358979 * 40000м.) / 133200с. = 1,88684243458846м.с.

Ну тоді хоча б так :

RichEdit1.Lines.Add(Format('(2 * pi * %.25g м.) / %.25g с. = %.25g м/с.',
                       [Variables[43,0], Variables[7,0], Variables[4,0]]));

або так :

RichEdit1.Lines.Add(Format('(%.25g * pi м.) / %.25g с. = %.25g м/с.',
                       [Variables[43,0] * 2, Variables[7,0], Variables[4,0]]));
Подякували: ProgramBandera1

178

Re: Програма розв'язування задач з фізики! Для учнів 7-го класу.

topprogrammer написав:
ProgramBandera написав:

Напевно що if тут не причому, я переніс

var ComboboxIndexes: set of integer;

в локальну процедуру Time в який 7 чи 8 вкладених if результат той самий видало ту ж помилку.
Я думаю що це ItemIndex перевищує 256 значень. А от їх в мене поки що 378, але буде іще більше.
Тут потрібно set якось замінити щоб визначало множину більшу ніж 255 різних значень.

Set може містити не більше 256 значень(простими словами це масив з 256 елементів). Ви можете замінити його масивом і самостійно реалізувати необхідний ф-ціонал(перетин множин).

Пане topprogrammer, а як правильно замінити set масив на масив з більшою кількістю елементів.
Мені просто створити новий масив з більшою кількістю елементів, і якого типу його робити? Він же не extended буде, вірно?

179

Re: Програма розв'язування задач з фізики! Для учнів 7-го класу.

ProgramBandera написав:
topprogrammer написав:
ProgramBandera написав:

Напевно що if тут не причому, я переніс

var ComboboxIndexes: set of integer;

в локальну процедуру Time в який 7 чи 8 вкладених if результат той самий видало ту ж помилку.
Я думаю що це ItemIndex перевищує 256 значень. А от їх в мене поки що 378, але буде іще більше.
Тут потрібно set якось замінити щоб визначало множину більшу ніж 255 різних значень.

Set може містити не більше 256 значень(простими словами це масив з 256 елементів). Ви можете замінити його масивом і самостійно реалізувати необхідний ф-ціонал(перетин множин).

Пане topprogrammer, а як правильно замінити set масив на масив з більшою кількістю елементів.
Мені просто створити новий масив з більшою кількістю елементів, і якого типу його робити? Він же не extended буде, вірно?

Можна використати список http://docwiki.embarcadero.com/CodeExam … t_(Delphi)
Для перевірки наявності елемента в списку використовуйте метод Contains(внизу приведеної сторінки є лінки на детальний опис методів).

180

Re: Програма розв'язування задач з фізики! Для учнів 7-го класу.

ProgramBandera
Нагадайте, будь ласка, яка у вас зараз версія Делфі?

Подякували: ProgramBandera1