Розробка уроку — практичної роботи

Тема: створення моделей рівномірного прямолінійного руху об’єкта, руху об’єкта на площині з перешкодами та з вибором шляху мовою С++.

Мета: надати учням приклад створення моделі руху об’єкта на площині з перешкодами мовою С++.

Обладнання: комп'ютери зі встановленими ОС, браузером, середовищем CodeBlocks для програмування мовою С++ з використанням бібліотеки wxWidgets, (дана) інструкція.

Структура уроку

  1. Організаційний момент.
  2. Актуалізація опорних знань.
  3. Вивчення нового матеріалу.
  4. Інструктаж з ТБ.
  5. Вироблення практичних навичок.
  6. Підбиття підсумків уроку.
  7. Домашнє завдання.

Хід уроку
1. Організаційний момент
Вітання з класом. Перевірка присутності і готовності учнів до уроку. Перевірка виконання домашнього завдання.

2. Актуалізація опорних знань

Галуження

if (умова) вказівка1 else вказівка2 — повна форма умовного оператора;
if (умова) вказівка — неповна форма умовного оператора;


switch (вираз)
{ case значення1 : вказівка1; break;
  case значення2 : вказівка2; break;
  …
  case значенняn : вказівкаn; break;
  default: вказівкаn + 1
};

Цикли

for (дія до почату циклу;
     умова продовження циклу;
     дія в кінці кожної ітерації циклу;)
{ вказівка1;
  вказівка2;
  …
  вказівкаn;
}

Контейнер vector (вектор) у мові С++ призначено для зберігання послідовності значень одного типу:

make_pair(x,y) — пара елементів x, y.

3. Вивчення нового матеріалу
Створення комп'ютерної моделі рівномірного прямолінійного руху об’єкта на площині з оминанням перешкод

передбачає:

Таймер-планувальниквбудований засіб бібліотеки wxWidgets зі вкладення Tools, що задає виклик функції OnTimer*Trigger через проміжок часу, вказаний розробником з точністю до мілісекунди.

У назві функції OnTimer*Trigger — обробника події звернення до таймера — замість зірочки буде записано номер таймера у порядку його встановлення на форму. Таймер, на відміну від циклу, дозволяє виконувати певні дії декілька разів, дозволяючи виконувати інші дії у проміжках між зверненнями таймера.

Перед створенням зображення з використанням бібліотеки wxWidgets потрібно створити об'єкт визначення пристрою (device context, DC). Такий об'єкт у wxWidgets називають wxDC. Його не призначено для безпосереднього використання, замість нього потрібно вибрати один з похідних класів:

Кожен похідний клас призначено для використання у певних умовах:

Методи (функції) одного класу можуть виявитися непридатними до методів іншого. Тому при створенні одного видимого зображення, яке потрібно опрацювати, насправді потрібно створити 4 об'єкти таких класів:

Описане вище можна подати такою схемою.

*.bmp, *.gif,
*.ico, *.jpeg,
*.pcx, *.png,
*.tiff


wxBitmap

~wxMemoryDCwxImage
wxPaintDC

На схемі символом ~ позначено можливість задання еквівалентності вмісту, стрілками — напрям можливого перенесення даних, зеленим кольором — можливість малювання, червоним кольором — можливість аналізу інтенсивності кольорів моделі RGB окремих пікселів.

Рекомендований порядок роботи із зображеннями

  1. Створити (описати) 4 об'єкти таких класів:
    wxBitmap, wxMemoryDC, wxImage, wxPaintDC.
  2. Узгодити растрове зображенням wxBitmap і об'єкт пам'яті wxMemoryDC.
  3. Або намалювати в оперативній пам'яті об'єкт wxMemoryDC,
    або завантажити наявний графічний файл у растрову карту wxBitmap.
  4. Отримати зображення для аналізу wxImage з растрової карти wxBitmap.
  5. Проаналізувати невидиме зображення wxImage.
  6. Відобразити растрову карту wxBitmap у об'єкт видимого зображення wxPaintDC.
  7. Домалювати видиме зображення wxPaintDC згідно з проведеним аналізом.

Примітка. Пункт 6 можна перенести на місце пункту 4.

Опис класу wxDC на сторінці офіційного сайту проекту wxWidgets не дає простих і зрозумілих для початківця вказівок, як імпортувати, створювати, подавати й опрацьовувати зображення. У публікації подано короткі прокоментовані приклади кодів роботи з контуром, прямокутником, многокутником, сплайном, дугою, текстом, градієнтами, плоскими геометричними фігурами, графічними файлами та опрацюванням зображень.

Розглянемо прокоментований приклад коду з втіленням імпортування, створення, редагування й подання зображення. Для успішної роботи коду при завантаженні зображення поля тека проекту повинна містити файл field.png. Наприклад, такого вигляду.

При виконанні завдання 2 (див. далі) потрібно вставити в обробник події звернення до таймера розглянутий код повністю. Але доповнити його безпосередньо після коментаря:

  /* Визначення значень глобальних змінних x, y
     - координат центра рухомого круга       */

відповідним програмним втіленням алгоритму руху площиною з оминанням перешкод. Таке доповнення обов'язково міститиме визначення інтенсивностей кольорів у точці з координатами j (по горизонталі) і k (по вертикалі) як значень функцій зображення img класу wxImage:
img.GetRed(j,k), img.GetGreen(j,k), img.GetBlue(j,k).

4. Інструктаж з ТБ
5. Вироблення практичних навичок


Завдання 1. Скласти алгоритм руху об’єкта прямокутним полем з оминанням перешкод (наприклад, відрізків прямих ліній) при таких обмеженнях:

Вхідні дані (розташування перешкод і співвідношення між розмірами поля, об'єкта й величиною стрибка) ґарантують істування розв'язку — відповідної траєкторії руху.

Створений за допомогою конкурсу ідей алгоритм проходження лабіринту у темноті без його схеми порівняти з очікуваним.

Алгоритм (діяти до досягнення правої сторони поля)

  1. Вважати:
    • напрям руху → (зліва направо);
    • номер стану гри 0 — об'єкт не дотикається до перешкоди.
  2. Рухатися вперед до досягнення перешкоди.
  3. Змінити номер стану гри на 1 — об'єкт обходить перешкоду.
  4. Запам'ятати розташування об'єкта.
  5. Змінити поточний напрям руху на перший з можливих у послідовності ↑, ←.
  6. Обійти перешкоду, полишаючи її праворуч, і знайти на шляху точку, з якої можна почати рух праворуч або почати обхід іншої перешкоди, розташованої (хоча б частково) правіше від поточної перешкоди. Інакше кажучи, поки не досягнуто правого краю поля або останнього розташування кроку, запам'ятованого на кроці 4, робити таке у кожному розташуванні об'єкта:

    • запам'ятати розташування у порядку обходу перешкоди;

    • якщо розташування — правіше від усіх пройдених, тобто абсциса (центра) об'єкта найбільша з усіх досягнутих, запам'ятати його місце у траекторії;

    • наступне переміщення здійснити у першому з можливих напрямків, заданих такою послідовністю різниць кутових аргументів нового напрямку і попереднього (напрям вимірювання традиційний — проти напрямку руху годинникової стрілки):

      • −90° — повернути праворуч;
      • 0° — зберегти напрям руху, бо праворуч перешкода;
      • +90° — повернути ліворуч, якщо перешкода і праворуч, і прямо;
      • +180° — рушити назад, якщо перешкоди немає лише позаду.
  7. Змінити номер стану гри на 2 — об'єкт рухається у «точку відриву» від перешкоди, тобто у розташування з найбільшою абсцисою при обході останньої перешкоди.

  8. Повернутися у «точку відриву».

  9. Очистити пам'ять, відведену на запам'ятовування траєкторії обходу перешкоди.

  10. Перейти до виконання пункту 1.

Примітка. Горизонтальну межу поля потрібно тлумачити як перешкоду при русі полем. Якщо кілька перешкод дотикаються до горизонтальної межі, то вони разом з цією межею утворюють одну перешкоду з точки зору виконавця алгоритму.

Поради щодо програмного втілення:

Завдання 2. Програмно втілити складений алгоритм руху білого круга прямо­кутним полем темно зеленого кольору з оминанням перешкод (наприклад, відрізків прямих ліній) жовтого кольору.

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

Вказівки до виконання завдання:

  1. У середовищі CodeBlocks у вказаній учителем теці створити проєкт obstacles з використанням бібліотеки wxWidgets з такими параметрами:

    • Prefered GUI — Builders;
    • Application Type — Frame Based.
  2. Видалити об'єкти: MenuBar1 і StatusBar1, виділивши їхні зображення (клацнувши на них лівою кнопкою миші) над зображенням форми і натиснувши клавішу Delete.

  3. Надати властивостям форми значення (тут і нижче у тексті вказано лише ті властивості, значення яких потрібно змінити):

    • Title — obstacles
    • Width — 800;
    • Height — 450.
  4. Розташувати на формі об'єкти з вкладення Standard (Стандартне):

    • wxPanel — панель з такими значеннями властивостей:

      X0
      Y0
      Width 800
      Height450
    • Custom — користувацький віджет (покласти на панель) з такими значеннями властивостей:

    Creating code$(THIS) = new $(CLASS)($(PARENT));
    Include filewx/dcclient.h
    Var namez
    Class namewxPaintDC
    X0
    Y0
    Width 800
    Height450

    Щоб змінити значення Creating code (коду породження), потрібно клацнути лівою кнопкою миші праворуч від відповідного значення

    і у вікні діалогу Creating code вилучити зайві символи, після чого натиснути на кнопку Гаразд.

  5. Виставити на панель таймер з вкладення Tools і виставити проміжок між вмиканнями 50 мілісекунд, що відповідає частоті 20 кадрів на секунду.

  6. Створити обробник події вмикання таймера:

    • виділити таймер, клацнувши на ній лівою кнопкою миші, і перейти до розгляду подій, натиснувши кнопку із зображенням фігурних дужок {};

    • навести вказівник миші на рядок з написом None (Жодного) праворуч від напису EVT_BUTTON, клацнути лівою кнопкою миші і з випадного меню вибрати Add new handler (Додати новий обробник);

    • підтвердити створення події OnTimer1Trigger вмикання таймера, натиснувши кнопку з написом Гаразд у вікні діалогу New hadler (Новий обробник);



  7. Замовити бібліотеки і простір назв

    #include <wx/dcmemory.h>
    #include <vector>
    using namespace std;

    на початку програми obstaclesMain.cpp.

  8. Описати глобальні змінні перед кодом обробника події вмикання таймера — функції OnTimer1Trigger програми obstaclesMain.cpp.

    int igame=0, // стан гри
        idir =0, // напрям руху
    x=8,  y=225, // поточні координати центра круга
    xb,          // найбільше досягнуте значення абсциси
    jb,          // номер точки траєкторії з найбільшим
                 // досягнутим значенням абсциси
    jt;          // поточний номер точки траєкторії при поверненні
                 // у точку "відриву" за найменшу кількість кроків
    bool incjt;  // зростання поточного номера точки траєкторії
                 // при поверненні у "точку відриву від перешкоди"
                 // за найменшу кількість кроків
    vector < pair <int, int> > t; // траєкторія центрів круга
  9. Вставити розглянуту при вивченні нового матеріалу частину програми у код обробника події вмикання таймера — функції OnTimer1Trigger програми obstaclesMain.cpp.

  10. Програмно втілити алгоритм зміни координат центра круга у коді обробника події вмикання таймера — функції OnTimer1Trigger програми obstaclesMain.cpp. Порівняти з очікуваним.

  11. Перевірити правильність виконання проекту. Для цього на панелі інструментів середовища CodeBlocks натиснути (у вказаному порядку) такі кнопки:

    Save all files (Зберегти всі файли);
    Build (Побудувати);
    Run (Запустити).

    Замість натискання двох останніх кнопок можна натиснути одну:

    Build and run (Побудувати і запустити).

    У разі потреби внести зміни у код програми.

  12. Повідомити вчителя про завершення роботи над проектом.

6. Підбиття підсумків уроку
Обговорення проблем виконання завдання. Виставлення оцінок.

7. Домашнє завдання

У разі потреби доробити завдання.

Для охочих: удосконалити програму — дозволити переміщення центра білого круга у точки з цілими координатами, віддаленими від початкового положення на відстань, що не перевищує s за умови, що при зміні однієї з координат кінцевого розташування на 1 можна отримати точку, віддалену від початкового розташування на відстань, що не перевищує s — див. малюнок, на якому:

При одночасному зростанні s і розмірів подання перешкод така дискретна модель (зі скінченою кількістю розташувань круга) є гарним наближенням неперервної моделі, у якій можливим є довільне розташування круга без перетину з перешкодами з довільним напрямком переміщення на певну відстань. Файл для опрацювання (із зображенням перешкод) може місти істотно більше пікселів, ніж його зображення на екрані монітора.

Іншим наближенням такої моделі є модель з довільним розташуванням круга без перетину з перешкодами, але векторами переміщення з такими координатами:

(s · cos(πj/2n), s · sin(πj/2n)) при j = 0, 1, …, n.

Якщо сумістити початки векторів, то їхні кінці будуть вершинами правильного 4n-кутника. Кратність 4 кількості вершин вибрано для того, щоб мати можливість рухатися по горозонталі праворуч і ліворуч та по вертикалі вгору й униз. У цьому випадку:

Для обох моделей алгоритм перевірки можливості руху у певному напрямку вимагає істотного доопрацювання з використанням рівняння прямої на площині.


Текст упорядкував Олександр Рудик.