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

Особливості використання функцій бібліотеки "Windows.h". Довільне заповнення поля клітинами з певною ймовірністю і його відображення на екрані. Зображення основних конфігурацій класичної гри "Життя". Тестування програми та інструкція користувача.

Рубрика Программирование, компьютеры и кибернетика
Вид курсовая работа
Язык украинский
Дата добавления 28.09.2018
Размер файла 634,7 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

Размещено на http://www.allbest.ru/

Харківський національний університет радіоелектроніки

КУРСОВА РОБОТА

м. Харків - 2018 рік

РЕФЕРАТ

Пояснювальна записка до курсової роботи містить 37 с., 5 розділів, 9 рис., 1 додаток, список із 7 літературних джерел.

Об'єкт дослідження - розробка симулятора клітинного автомату.

Мета роботи - розробка програми для моделювання поведінки двовимірного клітинного автомату.

Метод дослідження - вивчення літератури, складання і налагодження тестової програми на комп'ютері.

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

Програма складена мовою C++ та за допомогою засобів Win32Api в середовищі Visual C++.

КЛІТИННЕ ПОЛЕ, КРАЙОВИЙ ЕФЕКТ, ТОР, ОКОЛИЦЯ МУРА, СТАН КЛІТИНИ, ПОКОЛІННЯ, ПРАВИЛО ЕВОЛЮЦІЇ, КОНФІГУРАЦІЇ, УМОВИ НАРОДЖЕННЯ І ВИЖИВАННЯ, WINAPI

ЗМІСТ

ВСТУП

1. ПОСТАНОВКА ЗАДАЧІ ТА СФЕРА ЇЇ ВИКОРИСТАННЯ

2. АНАЛІЗ ДОСТУПНИХ ЗАСОБІВ ПРОЕКТУВАННЯ ПРОГРАМИ

2.1 Структура Windows-додатка

2.2 Особливості використання функцій бібліотеки «Windows.h»

3. АРХІТЕКТУРА РОЗРОБЛЕНОЇ ПРОГРАМИ

4. ОСОБЛИВОСТІ ПРОГРАМНОЇ РЕАЛІЗАЦІЇ

4.1 Реалізований функціонал

4.2 Довільне заповнення поля клітинами з певною ймовірністю і його відображення на екрані

4.3 Відображення основних конфігурацій класичної гри «Життя»

4.4 Заміна обмеженого поля нескінченним і навпаки

4.5 Реалізація варіацій гри «Життя»

5. ТЕСТУВАННЯ ПРОГРАМИ ТА ІНСТРУКЦІЯ КОРИСТУВАЧА

5.1 Тестування програми

5.2 Інструкція користувача

ВИСНОВКИ

СПИСОК ВИКОРИСТАНИХ ДЖЕРЕЛ

ДОДАТОК

ВСТУП

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

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

В даний час більшість обчислювальних задач вимагає для свого розв'язання ресурсів, що виходять за рамки можливостей однопроцесорних комп'ютерів. З'являється все більше алгоритмів, що використовують паралельні або розподілені обчислення для вирішення завдань. Крім того, виникають нові завдання, які вимагають паралельної або розподіленої архітектури для свого рішення. Беручи до уваги ту обставину, що зараз при розробці складних програмно-апаратних комплексів значна частка витрат йде на розробку програмного забезпечення і ця частка неухильно зростає, завдання створення інструмента для автоматизації проектування програмного забезпечення систем з паралельною і розподіленою обчислювальними архітектурами стає актуальною.

Клітинні автомати застосовуються для проведення різних обчислювальних експериментів, оскільки вони зручні, наприклад, для чисельного рішення диференційних рівнянь і рівнянь в частинних похідних. Вони також широко використовуються для моделювання поведінки складних систем. За класифікацією С.Вольфрама [1] одновимірні і двовимірні правильні сумуючі автомати діляться за своєю поведінкою на чотири класи.

Клас 1. За кінцеве число кроків автомати досягають просторово-однорідного стану. Кінцевий стан не залежить від часу і від початкових умов.

Клас 2. Автомат генерує локалізовані структури, стаціонарні або періодичні за часом. Клас 3. Автомат цього класу породжує неперіодичні конфігурації клітин, «забуваючи» при цьому про початкові умови, - володіє так званим «турбулентним» перемішуванням. Приклади автоматів такого класу наведені нижче, в таблиці 1, присвяченій модифікації клітинного автомата «гра "Життя "». Клас 4. Динаміка клітинного автомата істотно залежить від початкових даних. Підбираючи початкові умови, можна групувати найрізноманітніші послідовності станів, що змінюють один одного. Відомо кілька «кандидатів» на роль автомата класу 4, чітко встановлено, що таким автоматом є гра Дж.Конуея «Життя».

Перші описи гри «Життя» містяться в книгах Мартіна Гарднера [2],[3]. У 1980-2010 роках в різних країнах різними авторами створені «життєподібні» клітинні автомати. Математичні теорії і чисельний експеримент в області таких автоматів призвели до виникнення не тільки численних спеціалізованих Інтернет-ресурсів, а й спеціалізованих наукових журналів.

Динаміка автомата «Життя» не є хаотичною, а скоріше «регулярна». У ньому можливі локалізовані цикли (конфігурації «млин» або «семафор»), рухомі конфігурації - «планери». Існують також і різні динамічні структури (наприклад, в разі «зіткнення» «планера» з «млином») і «неелементарні» початкові конфігурації типу «паровоза» і «рушниці», «стріляє» «планерами».

Для реалізації графічного відображення поколінь клітинного автомату були застосовані інструменти Windows API.

Windows API - загальне найменування цілого набору базових функцій інтерфейсів програмування додатків операційних систем сімейств Microsoft Windows корпорації «Microsoft». Являється найбільш прямим способом взаємодії додатків з Windows. Для створення програм, що використовують Windows API, «Майкрософт» випускає комплект розробника програмного забезпечення, який називається Platform SDK, і містить документацію, набір бібліотек, утиліт і інших інструментальних засобів для розробки.

Windows API був спочатку спроектований для використання в програмах, написаних мовою Сі або C++. Робота через Windows API - це найбільш близький до системи спосіб взаємодії з нею з прикладних програм.

WinAPI представляє уніфікований інтерфейс для доступу програміста до функціоналу операційної системи, що значно прискорює розробку системного програмного забезпечення. Будь-яка програма для Windows має так зване «вікно». У кожного вікна є назва, тобто заголовок. Більшість функцій запускається за допомогою меню.

В цій курсовій роботі буде реалізована гра «Життя», яка, втім, не є грою в прямому значенні цього слова. Користувачеві буде запропоновано спостерігати за розвитком колонії клітин за визначеними правилами. Реалізація гри «Життя» у середовищі Microsoft Visual Studio 2017 дозволить отримати практичні навички з використання Windows API та GDI.

1. ПОСТАНОВКА ЗАДАЧІ ТА СФЕРА ЇЇ ВИКОРИСТАННЯ

Джон фон Нейман, геніальний математик (один з головних майстрів реалізації комп'ютерів), поставив сорок років тому питання про саморепродукцію машин. Він створив на папері клітинний автомат. Він складається з поля, розділеного на клітини, які живуть і вмирають відповідно до логічних правил залежно від їхньго сусідства. Теорія клітинних автоматів тоді швидко розвивалася і викликала значний ентузіазм.

Тоді ж американський математик Джон Конуей заклав в 1970-х роках основні принципи гри «Життя», що полягають в еволюції клітин, які можуть відтворюватися, зникати або виживати, підкоряючись правилам, які іноді називають «генетичними». Ці клітини тут представлені квадратами на полі.

Основна мета даного курсового проекту полягає в отриманні практичних навичок з використання функцій WinAPI, а основним засобом досягнення поставленої мети є саме реалізація клітинного автомату «Життя».

Так, в двовимірному просторі всі автомати типу «Життя» визначені лише на шаблоні типу «околиця Мура». Правила переходу на наступний шар можуть бути записані в канонічній формі B3/S23. У першій частині запису правила пошарового переходу («B» від слова «born» - «народження») вказується те число сусідів в околиці Мура, при якому відбувається народження нової клітини. «S» (save) - число сусідів, при якому клітина залишається живою. У всіх інших випадках клітина переходить в стан 0 - «смерть», і ці правила не записуються стандартною нотацією.

Всі автомати типу «Життя» розглядають клітини, що знаходяться в двох станах, правила переходу залежать тільки від числа сусідів в околиці Мура.

Нижче буде наведена зведена таблиця правил таких автоматів. За основу опису взята аналогічна таблиця з англомовного варіанту Вікіпедії [Conway's Game of Life] (див. таблицю 1.1).

Таблиця 1.1 - Опис клітинних автоматів типу «Життя»

Правила переходу

Назва

Опис

B018/S018

Автомат Вольфрама-Пакарда, клас 2

B0578/S045

Автомат Вольфрама-Пакарда

B0578/S12456

Автомат Вольфрама-Пакарда

B1/S012345678

Автомат Вольфрама-Пакарда

B1/S1

Gnarl

Автомат досліджений Келі Еванс. Формуються цікаві структури. На прямій є одновимірним аналогом «Життя»

B123567/S0238

Автомат Вольфрама-Пакарда; клас 3

B13456/S01356

Автомат Вольфрама-Пакарда

B135/S135

Автомат Вольфрама-Пакарда; класс 3

B1357/S1357

Реплікатор

Автомат Едварда Фредкіна, кожна структура відтворює множинні копії себе

B137/S45678

Автомат Вольфрама-Пакарда

B236/S0468

Автомат Вольфрама-Пакарда; клас 3

B257/S27

Автомат Вольфрама-Пакарда; наявні планери

B3/S012345678

Безсмертне

Життя

Візерунки, що схожі на сходи, можуть бути використані для симуляції логічних систем

B3/S12345

Лабіринт

Формує схожі на лабіринт форми

B3/S23

Життя

B3/S234

Автомат Вольфрама-Пакарда; клас 2. В цьому автоматі існують планери

B3/S45678

Корал

Ростуть «коралоподібні» структури

Правила переходу

Назва

Опис

B34/S03456

Автомат Вольфрама-Пакарда

B34/S34

34 Життя

Спочатку вважався більш стійким варіантом «Життя». Потім за допомогою комп'ютерного моделювання знайдені нескінченно зростаючі структури. Має багато планерів та циклів різного періоду.

B345/S4567

Асиміляція

Формує «діамантоподібні» структури з заповненою внутрішньою частиною

B345/S5

Довге життя

Досліджений Andrew Trevorrow. В ньому зустрічаються осцилятори з дуже дов-гими періодами

B35678/S5678

«Діамеба»

Формуються крупні «діаманти» з хаотично осцилюючими межами.

B357/S1358

Амеба

Модель гарно збалансована між «життям» і «смертю». Формуються структури із «стінками» та хаотичною поведінкою всередині областей. Наявні планери

B357/S238

Псевдожиття

Структури, що формуються призводять до формування із структур «Життя» більш простих через нестійкість «глайдеру» (під глайдером часто розуміють один із найпоширеніших планерів у грі «Життя»). Наявні планери

Правила переходу

Назва

Опис

B36/S125

2x2

Якщо структура утворена з блоків клітин розмірами 2х2, то вона й надалі розвиватиметься подібним чином. Наявні різноманітні види осциляторів і планерів

B36/S23

Піднесене життя

Схожий на «Життя», має невеликі структури, що самовідтворюються

B367/S2346

Автомат Вольфрама-Пакарда. Наявні планери

B3678/S235678

Плями

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

B3678/S34678

День і Ніч

Має сконструйовані структури зі склад- ною поведінкою

B368/S245

Рух

Довільні структури прагнуть стабілізу- ватися, але виявлені різноманітні види планерів

B378/S012345678

Автомат Вольфрама-Пакарда

B378/S235678

Коагуляція

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

B45678/S2345

Міста за стінами

Формує райони активності, розділені «стінками»

Гра «Життя» була запропонована в 1970 р. Дж. Конвеєм як математична розвага. В даний час досить великий інтерес математиків до цієї гри: доведено, що вона є клітинним автоматом класу 4. Згідно з існуючими гіпотезами, автомати даного класу можуть здійснювати універсальні обчислення, подібно машині Тьюринга [4], і застосовуватися при моделюванні розвитку турбулентності і виникнення дисипативних систем в екології, біології, економіці тощо.

Крім того, завдяки «універсальній поведінці», подібний клітинний автомат може бути хорошим тестом при створенні спеціалізованих трансляторів (компіляторів) для систем, що здійснюють паралельні обчислення на трансп'ютерних архітектурах [5].

Розглядається двовимірна система клітин на площині. Кожен елемент позначатимемо двома індексами (знизу). Шаблон, що враховує кількість найближчих сусідів, включає вісім клітин, що мають з даною загальні межі або вершини. Правила переходу для кожного елемента вкрай прості: елемент aij може перебувати в стані спокою (0) або активності (1). Зі стану спокою в активний в наступному поколінні елемент переходить, якщо поруч з ним в поточному поколінні виявилося рівно три активних елементи. Стан активності зберігається, якщо серед найближчих сусідів знаходяться два або три активних елементи. Правила переходу на наступний шар можуть бути записані в канонічній формі B3/S23.

Основною ключовою відмінністю даної реалізації від більш популярних загальноприйнятих реалізацій гри, окрім використання фактично не призначеного для розробки ігор API, є широкий вибір правил еволюції, що запропоновані користувачеві, а також можливість вибору типу поля: нескінченне чи обмежене. Таким чином, послідовно застосовуючи різні правила, можна побачити цікаві форми і конфігурації, що формуються в результаті дії тих чи інших «генетичних» правил.

Програма реалізації клітинного автомату «Життя» спрямована на спостереження еволюції колонії клітин у часі. Початкова конфігурація може бути довільною або заздалегідь визначеною. При довільній конфігурації спостерігачеві пропонується слідкувати за розвитком клітин, які можуть формуватися в стабільні структури, періодичні та структури, що переміщуються полем, при цьому маючи певний період, через який можна побачити ту саму конфігурацію, але зміщену в просторі. Окрім класичної гри «Життя» користувачеві запропоновано ще три десятки її варіацій. Послідовно їх застосовуючи, можна отримати цікаві конфігурації та візерунки. Також можна прослідкувати, як поводитимуться базові конфігурації класичної гри «Життя», при дії інших правил еволюції.

2. АНАЛІЗ ДОСТУПНИХ ЗАСОБІВ ПРОЕКТУВАННЯ ПРОГРАМИ

2.1 Структура Windows-додатка

Віконні додатки будуються за принципами подійно-керованого програмування (event-driven programming) - стилю програмування, при якому поведінка компонента системи визначається набором можливих зовнішніх подій і відповідних реакцій компонента на них. Такими компонентами в Windows є вікна.

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

Завдання будь-якої віконної програми - створити головне вікно і повідомити Windows функцію обробки подій для цього вікна. Всі основні дії для додатка відбуватимуться саме в функції обробки подій головного вікна.

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

Класичний віконний додаток, як правило, складається принаймні з двох функцій:

- стартова функція, що створює головне вікно WinMain();

- функція обробки повідомлень вікна (віконна процедура).

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

Більш точно, вікно завжди створюється на основі «класу вікна». Клас вікна визначає віконну процедуру, що обробляє повідомлення, які надходять до вікна. Використання класу вікна дозволяє створювати безліч вікон на основі одного і того ж класу вікна і, отже, використовувати одну і ту саму віконну процедуру. Цей клас пов'язаний з віконної процедурою (розташованою в бібліотеці динамічної компоновки Windows), яка керує процесом передачі повідомлень всіх кнопок всіх вікон [6].

В об'єктно-орієнтованому програмуванні будь-який «об'єкт» несе в собі поєднання коду і даних. Вікно - це об'єкт. Код - це віконна процедура. Дані - це інформація, що зберігається віконною процедурою, і інформація, що зберігається системою Windows для кожного вікна і кожного класу вікна, які є в системі.

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

Коли програма для Windows починає виконуватися, Windows будує для програми чергу повідомлень (message queue). У цій черзі зберігаються повідомлення для будь-яких типів вікон, які могли б бути створені програмою.

Невелика частина програми, яка називається циклом обробки повідомлень (message loop), вибирає ці повідомлення з черги і переправляє їх відповідній віконній процедурі. Інші повідомлення відправляються безпосередньо віконної процедури, минаючи чергу повідомлень.

Існують три повідомлення, які обов'язково треба обробити для коректної роботи програми, а саме:

- WM_CREATE - повідомлення, що приходить при створенні вікна, зазвичай тут ініціалізують деякі необхідні для роботи програми дані та викликають функції для створення дочірніх вікон керування;

- WM_PAINT - повідомлення, що надходить за умови, що необхідно оновити або перемалювати якусь область вікна;

- WM_DESTROY - повідомлення, що приходить при закінченні роботи програми.

- Більш детально ознайомитися з текстами цих блоків можна у прикладеному тексті програми.

2.2 Особливості використання функцій бібліотеки «Windows.h»

Переважний об'єм програми становить використання існуючих у бібліотеці «Windows.h» функцій. Функцією, що найбільш часто виконується, є функція «CreateWindow» для створення елементів керування.

Розглянемо детальніше цю функцію:

Прототип функції наведено у прикладі 2.1.

HWND CreateWindow

(

LPCTSTR lpClassName

, LPCTSTR lpWindowName

, DWORD dwStyle

, int x

, int y

, int nWidth

, int nHeight

, HWND hWndParent

, HMENU hMenu

, HANDLE hInstance

, LPVOID lpParam

Приклад 2.1 - Прототип функції створення вікна

Розглянемо аргументи функції «CreateWindow».

lpClassName - покажчик на зареєстроване ім'я класу

lpWindowName - покажчик на ім'я вікна

dwStyle - стиль вікна, стилі, що стосуються вікна, в цілому мають префікс «WS_», стилі, що стосуються вікна, як статичного малюнку - «SS_». Ключовим стилем для дочірнього вікна керування є «WS_CHILD».

x - горизонтальна позиція вікна.

y - вертикальна позиція вікна.

nWidth - ширина вікна.

nHeight - висота вікна.

hWndParent - дескриптор вікна власника.

hMenu - дескриптор меню, у випадку дочірнього елемента керування - ідентифікатор вікна.

hInstance - дескриптор екземпляру програми.

lpParam - покажчик на дані створення вікна, для вікон керування зазвичай має значення «NULL».

3. АРХІТЕКТУРА РОЗРОБЛЕНОЇ ПРОГРАМИ

Архітектура програмного забезпечення (англ. software architecture) -- це структура програми або обчислювальної системи, яка включає програмні компоненти, видимі зовні властивості цих компонентів, а також відношення між ними. Цей термін стосується також документування архітектури програмного забезпечення. Документування архітектури ПЗ спрощує процес комунікації між зацікавленими особами, дозволяє зафіксувати прийняті на ранніх етапах проектування рішення про високорівневі дизайни системи і дозволяє використовувати компоненти цього дизайну і шаблони повторно в інших проектах.

Рисунок 3.1 - Блок-схема розробленої програми

Програма починає свою роботу з ініціалізації фізичних координат клітин і початкового заповнення поля функціями «initCoord» та «fillField». Далі викликається функція «drawField» для відображення поля в клієнтській області вікна. Потім викликається функція «nextGeneration» з визначеними користувачем параметрами.

4. ОСОБЛИВОСТІ ПРОГРАМНОЇ РЕАЛІЗАЦІЇ

4.1 Реалізований функціонал

Програма була розроблена на основі процедурної парадигми програмування. В програмі були реалізовані функції довільного заповнення поля з вказаною ймовірністю; розміщення на полі стандартних конфігурацій класичної гри «Життя» Дж. Конуея, також надана можливість прослідкувати еволюцію лінії з одного ряду клітин за обраним правилом; була реалізована функція заміни нескінченного поля полем з межами і навпаки, а також були запропоновані три десятки правил на вибір.

4.2 Довільне заповнення поля клітинами з певною ймовірністю і його відображення на екрані

Була застосована стандартна функція rand() з певним удосконаленням: вона повертає значення істини лише тоді, коли довільне число в діапазоні від 0 до 100 менше за певне значення ймовірності, що передається в якості аргументу (див. приклад 4.1). На її основі, була реалізована функція довільного заповнення поля активними клітинами (див. приклад 4.2).

bool probabilityRandTrue(int a)

{

return (rand() % 100) < a;

}

Приклад 4.1 - Функція генерації одиниці з певною ймовірністю

void fillField(t_generation & generation, int a = 25)

{

clearField(generation);

srand(time(NULL));

for (size_t i{ 0 }; i < LIFE_SIZE; i++)

{

for (size_t j{ 0 }; j < LIFE_SIZE; j++)

generation[i][j] = probabilityRandTrue(a);

}

}

Приклад 4.2 - Функція довільного заповнення поля клітинами

Для подальшого заповнення поля і його відображення на екрані були введені тип данних t_cells, що представляє масив координат верхніх лівих точок квадраті, якими зображені клітини, а також тип даних t_generation, що представляє масив, який зберігає стан клітин (див. приклад 4.3)

typedef std::array <std::array <POINT, LIFE_SIZE>, LIFE_SIZE> t_cells;

typedef std::array <std::array <bool, LIFE_SIZE>, LIFE_SIZE> t_generation;

Приклад 4.3 - Декларація масивів координат і станів клітин

Для відображення масиву клітин на екрані (див. приклад 4.5), необхідно коректно заповнити масив координат, з використанням яких, на екрані з'являтимуться квадрати (див. приклад 4.4) як візуалізація клітин, у випадку, якщо відповідний елемент масиву generation має значення істини, що відповідає активному стану клітини.

void drawCell(HDC & hdc, t_cells & cells, int i, int j)

{

Rectangle(hdc, cells[i][j].x - 1, cells[i][j].y - 1,

cells[i][j].x + CELL_RADIUS, cells[i][j].y + CELL_RADIUS);

}

Приклад 4.4 - Функція відображення клітини

void drawField(t_cells & cells, t_generation & generation, HDC & hdc)

{

for (unsigned int i{ 0 }; i < LIFE_SIZE; i++)

{

for (unsigned int j{ 0 }; j < LIFE_SIZE; j++)

{

if (generation[i][j])

drawCell(hdc, cells, i, j);

}

}

}

Приклад 4.5 - Функція відображення клітинного поля

4.3 Відображення основних конфігурацій класичної гри «Життя»

Для реалізації цієї частини функціоналу програми були проаналізовані і обрані певні конфігурації, які представляють інтерес з точки зору їхньої еволюції (див. рисунок 4.1). Потім відповідні клітини були переведені в активний стан (див. приклад 4.6) і були відображені на екрані (див. приклад 4.5).

void largeShip(t_generation & generation)

{

clearField(generation);

generation[LIFE_SIZE/2-10 + 4][LIFE_SIZE/2-10 + 2] = 1;

generation[LIFE_SIZE/2-10 + 3][LIFE_SIZE/2-10 + 6] = 1;

generation[LIFE_SIZE/2-10 + 5][LIFE_SIZE/2-10 + 2] = 1;

generation[LIFE_SIZE/2-10 + 4][LIFE_SIZE/2-10 + 6] = 1;

generation[LIFE_SIZE/2-10 + 2][LIFE_SIZE/2-10 + 3] = 1;

generation[LIFE_SIZE/2-10 + 5][LIFE_SIZE/2-10 + 6] = 1;

generation[LIFE_SIZE/2-10 + 7][LIFE_SIZE/2-10 + 3] = 1;

generation[LIFE_SIZE/2-10 + 6][LIFE_SIZE/2-10 + 6] = 1;

generation[LIFE_SIZE/2-10 + 8][LIFE_SIZE/2-10 + 4] = 1;

generation[LIFE_SIZE/2-10 + 7][LIFE_SIZE/2-10 + 6] = 1;

generation[LIFE_SIZE/2-10 + 2][LIFE_SIZE/2-10 + 5] = 1;

generation[LIFE_SIZE/2-10 + 8][LIFE_SIZE/2-10 + 6] = 1;

generation[LIFE_SIZE/2-10 + 8][LIFE_SIZE/2-10 + 5] = 1;

}

Приклад 4.6 - Функція ініціалізації конфігурації «важкий космічний човен»

Рисунок 4.1 - Конфігурація «важкий космічний човен»

В основному файлі виконується відображення цієї конфігурації на полі в такий спосіб (див. приклад 4.7). В якості параметру функції, що реалізується, передається масив life_Generation, який зберігає поточний стан поля клітин типу t_generation.

case ID_MAINPROTOTYPES_LARGESHIP:

InvalidateRect(hWnd, RECT, TRUE);

largeShip(life_Generation);

break;

Приклад 4.7 - Обробка вибору пункту меню «Large ship»

4.4 Заміна обмеженого поля нескінченним і навпаки

Для того, щоб замінити обмежене поле нескінченним необхідно реалізувати відповідну функцію, яка модифікуватиме алгоритм обчислення кількості сусідів клітини в крайніх точках. Спочатку було реалізовано функцію, яка модифікує індекс елемента масиву клітин в «крайніх точках» (див. приклад 4.8). Крайніми точками тут називаються уявні точки як елементи масиву, індекси яких відрізняються на один від крайніх індексів елементів масиву. Такими індексами є -1 і LIFE_SIZE. Кінцевою метою реалізованої функції є загортання масиву клітин в тор таким чином, що клітина з індексом -1, що виходить за межі масиву, перетвориться на клітину з індексом LIFE_SIZE - 1 та стане сусідньою з клітиною з індексом LIFE_SIZE - 2. Так само і навпаки: клітина з індексом LIFE_SIZE перетвориться на клітину з індексом 0 та стане сусідньою з клітиною з індексом 1.

inline int checkBorders(int index)

{

int result;

if (index == -1) {

result = LIFE_SIZE - 1;

return result;

}

if (index == LIFE_SIZE) {

result = 0;

return result;

}

return index;

}

Приклад 4.8 - Функція перевірки меж поля

Були реалізовані дві функції підрахунку кількості сусідів для обмеженого поля (див. приклад 4.9) і для нескінченного (загорнутого в тор) (див. приклад 4.10). Функція обчислення кількості сусідів для обмеженого поля перевіряє по черзі вісім сусідів клітини на поточний стан і, якщо стан виявляється активним, збільшує лічильник кількості сусідів на один. Також тут було реалізовано перевірку на вихід за межі масиву, оскільки прохід масиву починається з нульового елемента, а звернення до елементу масуву з індексом вигляду i - 1 у випадку i = 0 й індексом вигляду i + 1 у випадку i = LIFE_SIZE - 1 призведе до помилки виконання, оскільки обраним контейнером зберігання масиву станів є std::array.

int neighbors(t_generation & generation, int i, int j)

{

int neighbors{ 0 };

if (j - 1 >= 0)

{

if (generation[i][j - 1])

neighbors++;

if (i + 1 < LIFE_SIZE && generation[i + 1][j - 1])

neighbors++;

}

if (i + 1 < LIFE_SIZE)

{

if (generation[i + 1][j])

neighbors++;

if (j + 1 < LIFE_SIZE && generation[i + 1][j + 1])

neighbors++;

}

if (j + 1 < LIFE_SIZE)

{

if (generation[i][j + 1])

neighbors++;

if (i - 1 >= 0 && generation[i - 1][j + 1])

neighbors++;

}

if (i - 1 >= 0)

{

if (generation[i - 1][j])

neighbors++;

if (j - 1 >= 0 && generation[i - 1][j - 1])

neighbors++;

}

return neighbors;

}

Приклад 4.9 - Функція обчислення кількості сусідів клітини для обмеженого поля

Для функції обчислення кількості сусідів клітини для нескінченого поля теж існує проблема звернення до елементів масиву, які є «крайніми точками». Але в цьому випадку вона розв'язується підміною індексів таких елементів з використанням реалізованої функції «checkBorders» (див. приклад 4.8).

int adj_neighbors(t_generation & generation, int i, int j)

{

int neighbors{ 0 };

if (generation[checkBorders(i - 1)][checkBorders(j - 1)])

neighbors++;

if (generation[checkBorders(i - 1)][j])

neighbors++;

if (generation[checkBorders(i - 1)][checkBorders(j + 1)])

neighbors++;

if (generation[i][checkBorders(j - 1)])

neighbors++;

if (generation[i][checkBorders(j + 1)])

neighbors++;

if (generation[checkBorders(i + 1)][checkBorders(j - 1)])

neighbors++;

if (generation[checkBorders(i + 1)][j])

neighbors++;

if (generation[checkBorders(i + 1)][checkBorders(j + 1)])

neighbors++;

return neighbors;

}

Приклад 4.10 - Функція підрахунку кількості сусідів клітини у випадку нескінченного поля

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

case ID_TYPEDECHAMP_INFINIE:

isInfinite = TRUE;

break;

case ID_TYPEDECHAMP_WITHBORDERS:

isInfinite = FALSE;

break;

Приклад 4.11 - Обробка вибору пунктів меню, що змінюють тип поля

4.5 Реалізація варіацій гри «Життя»

Як було зазначено вище, будь-яке правило для варіації гри «Життя» записується стандартним чином, вказуючи кількість сусідів клітини для її переходу з пасивного стану в активний і кількість сусідів для збереження активності клітини. Для цього було реалізовано декілька допоміжних функцій і перелік правил у вигляді enum сlass (див. приклад 4.12) (див. таблицю 1.1).

enum class Rules

{

CurrentRule, B018_S018, B0578_S045, B0578_S12456, B1_S012345678, B1_S1_Gnarl, B123567_0238, B13456_S01356, B135_S135, B1357_S1357_Replicator, B137_S45678, B236_S0468, B257_S27, B3_S012345678_ImmortalLife, B3_S12345_Maze, B3_S23_CONWAY_LIFE, B3_S234, B3_S45678_Coral, B34_S03456, B34_S34_34LIFE, B345_S4567_Assimilation, B345_S5_LongLife, B35678_S5678_Diamoeba, B357_S1358_Amoeba, B357_S238_PseudoLife, B36_S125_2x2, B36_S23_HighLife, B367_S2346, B3678_S235678_Stains, B3678_S34678_Day_Night, B368_S245_Motion, B378_S012345678, B378_S235678_Concretion, B45678_S2345_Towns_Walls, B23_S01234_TASK_OF_COURSE_PROJ

};

Приклад 4.12 - Перелік реалізованих варіацій гри «Життя»

Для реалізації перевірки виконання умови рівності для народження або виживання клітини була реалізована відповідна функція (див. приклад 4.13). Вона перевіряє елементи списку ініціалізаторів, які є допустимою кількістю сусідів для народження або виживання клітини, на рівність кількості сусідів поточної клітини. У випадку знаходження хоча б одної рівності, функція повертає значення істини, реалізуючи таким чином аналог операції АБО для багатьох аргументів. Пізніше ця функція буде використана для спрощення декларації і реалізації нових правил, для запису яких використовується стандартна нотація вигляду B3/S23.

bool condition(int neighbors, std::initializer_list <int> neighbor_numb) {

const int * pTemp = neighbor_numb.begin();

while (pTemp != neighbor_numb.end()){

if (*pTemp == neighbors)

return true;

++pTemp;

}

return false;

}

Приклад 4.13 - Функція перевірки відповідності кількості сусдів клітини умові, що вказана в правилі

Для застосування обраного правила була реалізована функція, яка враховує поточний тип поля (див. приклад 4.14). Ця функція є основною для всієї програми, оскільки вона реалізує логіку формування наступного покоління, враховуючи стани клітин поточного покоління, а також умови народження нових клітин і умови виживання існуючих. В якості списку параметрів цієї функції передаються масив станів поточного покоління клітин, масив станів наступного покоління клітин, які необхідні для обчислення кількості сусідів поточної клітини, а також індекси клітини як елемента масиву generation, умови народження і збереження клітини і змінна, що визначає тип поля. Виходячи зі значення цієї змінної, застосовується той чи інший алгоритм обчислення кількості сусідів клітини (див. приклади 4.9, 4.10).

void applyRule(t_generation & generation, t_generation & next_generation, int i, int j, std::initializer_list <int> born_cond, std::initializer_list <int> save_cond, bool areBorders)

{

if (areBorders)

{

if (!generation[i][j] && (condition(adj_neighbors(generation, i, j), born_cond)))

next_generation[i][j] = true;

if (generation[i][j] && (condition(adj_neighbors(generation, i, j), save_cond)))

next_generation[i][j] = true;

}

else

{

if (!generation[i][j] && (condition(neighbors(generation, i, j), born_cond)))

next_generation[i][j] = true;

if (generation[i][j] && (condition(neighbors(generation, i, j), save_cond)))

next_generation[i][j] = true;

}

}

Приклад 4.14 - Функція застосування будь-якого правила

Врешті була реалізована функція для переходу на наступне покоління. В її тілі правило, що застосовується, обирається за допомогою умовного оператора switch. Для того, щоб при наступному переході не було необхідно знову вказувати «генетичне» правило, була введена статична змінна, яка зберігатиме поточне правило (див. приклад 4.15). В кожному case викликається функція «applyRule», в якій для кожного правила передаються відповідні умови народження та зберження клітини у вигляді списку ініціалізаторів.

void nextGeneration(t_generation & generation, t_generation & next_generation, enum class Rules rule, bool areBorders) {

clearField(next_generation);

static Rules tmp{ Rules::B23_S01234_TASK_OF_COURSE_PROJ };

for (int i{ 0 }; i < LIFE_SIZE; i++){

for (int j{ 0 }; j < LIFE_SIZE; j++){

//Apply rules to the cell:

switch (rule) {

case Rules::B018_S018:

applyRule(generation, next_generation, i, j, { 0,1,8 }, { 0,1,8 }, areBorders);

tmp = Rules::B018_S018;

break;

Приклад 4.15 - Фрамент реалізації генерації нового покоління відповідно до обраного правила B018/S018

В основному файлі програми перехід до наступного покоління за відповідним правилом реалізовано через пункт меню, кнопку і акселератор (див. приклад 4.16).

case ID_R32842:

nextGeneration(life_Generation, next_Generation, Rules::B23_S01234_TASK_OF_COURSE_PROJ, isInfinite);

copyField(next_Generation, life_Generation);

InvalidateRect(hWnd, RECT, TRUE);

break;

case ID_STEP:

nextGeneration(life_Generation, next_Generation, Rules::CurrentRule, isInfinite);

copyField(next_Generation, life_Generation);

InvalidateRect(hWnd, RECT, TRUE);

break;

Приклад 4.16 - Обробка вибору пукту меню і натискання клавіші «Return»

5. ТЕСТУВАННЯ ПРОГРАМИ ТА ІНСТРУКЦІЯ КОРИСТУВАЧА

5.1 Тестування програми

Тестування програмного забезпечення це процес, що використовується для виміру якості розроблюваного програмного забезпечення. Зазвичай, поняття якості обмежується такими поняттями, як коректність, повнота, безпечність, але може містити більше технічних вимог, які описані в стандарті ISO 9126. Тестування це процес технічного дослідження, який виконується на вимогу замовників, і призначений для вияву інформації про якість продукту відносно контексту, в якому він має використовуватись. До цього процесу входить виконання програми з метою знаходження помилок.

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

Програма була протестована на таких машинах:

- Intel Pentium lV 2.20 GHz, 2Gb RAM, 1Gb відеопам'яті, Windows 7;

- Intel Core i3- 3005U 2.40 GHz, 4 Gb RAM, 2Gb відеопам'яті, Windows 10.

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

5.2 Інструкція користувача

При запуску програми виводиться довільно заповнене поле клітин. За замовчуванням активне правило B23/S01234, що відповідає завданню курсової роботи (див. рисунок 5.1).

Рисунок 5.1 - Вигляд програми після запуску

За бажанням, користувач може власноруч обрати ймовірність заповнення поля клітинами (див. рисунок 5.2) або обрати одну з запропонованих конфігурації за допомогою відповідних пунктів меню (див. рисунок 5.3).

Рисунок 5.2 - Вибір ймовірності появи клітини на полі

Рисунок 5.3 - Вибір початкової конфігурації

Користувачу запропоновано на вибір тридцять чотири правила, що обираються через пункт меню. Цифри після «B» означають кількість сусідів навколо «мертвої» клітини, при якій вона «оживе», а цифри після «S» означають кількість сусідів клітини, за якої вона «виживе» (див. рисунок 4.4).

Рисунок 5.4 - Вибір «генетичного» правила

Оскільки наявність меж в поля спричиняє «крайові ефекти» в програмі є можливість зробити поле нескінченним (див. рисунок 5.5). В такому разі крайній верхній ряд клітин стане сусіднім з крайнім нижнім, а крайній лівий - з крайнім правим.

Рисунок 5.5 - Вибір типу поля для подальшої еволюції за діючим правилом

Крайовий ефект полягає в тому, що одна й та сама початкова конфігурація за дії того ж правила може мати різну еволюцію в залежності від наявності границь (див рис. 5.6 і рис. 5.7)

Рисунок 5.6 - Еволюція горизонтальної лінії за дії правила «Реплікатор» через 62 кроки при обмеженому полі

Рисунок 5.7 - Еволюція горизонтальної лінії за дії правила «Реплікатор» через 62 кроки при нескінченному полі

ВИСНОВКИ

В ході виконання даної роботи у середі Visual C++ за допомогою мови програмування C++ та засобів WinAPI була розроблена програма, що дозволяє простежити еволюцію клітинного автомату «Життя».

Детальніше, використання даної програми моделювання клітинного автомата «Життя» дозволяє:

- Обирати спосіб ініціалізації початкової конфігурації;

- Спостерігати за еволюцією поля клітин за вибраних умов

- Змінювати умови еволюції без ануляції попереднього прогресу

Програма легка в користуванні, оскільки в ній інтуїтивно зрозумілий графічний інтерфейс користувача, що виводить цю програму в клас віконних додатків.

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

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

На даному етапі розвитку функціонал програми логічно завершений. У разі продовження роботи над даним додатком у сторону розширення функціоналу можливо додати функцію зберігання у пам'яті та подальше відтворення поточної конфігурації клітин. Також додати можливість персоналізованого заповнення поля з використанням миші шляхом активізації певних клітин або малюванням на полі певних фігур, лінії контурів яких відповідатимуть активним клітинам, а також зміну швидкості виведення поколінь та надати користувачеві можливість самому створювати правила з використанням реалізованого функціоналу. Нарешті можна додати можливість присвоювати окремим колоніям клітин їхні власні кольори з метою простеження їхнього розвитку і «дифузії».

СПИСОК ВИКОРИСТАНИХ ДЖЕРЕЛ

1. Wolfram S. A New Kind of Science / Stephen Wolfram. - United States: Wolfram Media, 2002. - 1197 с.

2. Гарднер М. Математические досуги. М.: Мир. 1972.

3. Гарднер М. Крестики-нолики. М.: Мир. 1988.

4. Тоффоли Т. Машины клеточных автоматов / Т. Тоффоли, Н. Марголоус. - Москва: Мир, 1991. - 280 с.

5. Джоунз Г. Программирование на языке ОККАМ. -- Москва: Мир, 1989. -- 284 с.

6. Петзольд Ч. Програмування під Windows 95. У двох книгах. - BHV St.-Petersburg изд. - Санкт-Петербург: 1997. - 654 с.

ДОДАТОК

Текст програми

Заголовковий файл №1: Course_Proj_31_Game_LIFE_PS.h

#pragma once

#include <array>

#include <vector>

#include <Windows.h>

#include "resource.h"

#include <ctime>

#define LIFE_SIZE 135

#define CELL_RADIUS 7

typedef std::array <std::array <POINT, LIFE_SIZE>, LIFE_SIZE> t_cells;

typedef std::array <std::array <bool, LIFE_SIZE>, LIFE_SIZE> t_generation;

inline int checkBorders(int index)

{

int result;

if (index == -1)

{

result = LIFE_SIZE - 1;

return result;

}

if (index == LIFE_SIZE)

{

result = 0;

return result;

}

return index;

}

void initCoord(t_cells & cells);

bool condition(int neighbours, std::initializer_list<int> l);

bool probabilityRandTrue(int a);

void fillField(t_generation & generation, int a);

void P46_glider_gun(t_generation & generation);

void Glider_gun(t_generation & generation);

void Beacon(t_generation & generation);

void Blinker(t_generation & generation);

void largeShip(t_generation & generation);

void smallShip(t_generation & generation);

void Pentadecathlon(t_generation & generation);

void Line(t_generation & generation);

void drawCell(HDC & hdc, t_cells & cells, int i, int j);

void drawField(t_cells & cells, t_generation & generation, HDC & hdc);

int adj_neighbors(t_generation & generation, int i, int j);

int neighbors(t_generation & generation, int i, int j);

void nextGeneration(t_generation & generation, t_generation & next_generation, enum class Rules rule, bool areBorders);

void applyRule(t_generation & generation, t_generation & next_generation, int i, int j, std::initializer_list <int> born_cond, std::initializer_list <int> save_cond, bool areBorders);

void copyField(t_generation & src, t_generation & dest);

bool cmpField(t_generation & w1, t_generation & w2);

void clearField(t_generation & generation);

Заголовковий файл №2: Resource.h

//{{NO_DEPENDENCIES}}

// fichier Include Microsoft Visual C++.

// Utilisй par Course_Proj_31_Game_LIFE_PS.rc

//

#define IDC_MYICON 2

#define IDD_COURSEPROJ31GAMELIFEPS_DIALOG 102

#define IDS_APP_TITLE 103

#define IDD_ABOUTBOX 103

#define IDM_ABOUT 104

#define IDM_EXIT 105

#define IDI_SMALL 108

#define IDC_COURSEPROJ31GAMELIFEPS 109

#define IDR_MAINFRAME 128

#define IDI_ICON1 130

#define ID_MAINPROTOTYPES_GLIDERGUN 32771

#define ID_MAINPROTOTYPES_LARGESHIP 32772

#define ID_ACTIONS_START 32773

#define ID_ACTIONS_STOP 32774

#define ID_MAINPROTOTYPES_LONGBARGE 32775

#define ID_MAINPROTOTYPES_LOAF 32776

#define ID_MAINPROTOTYPES_PENTADECATHLON 32777

#define ID_MAINPROTOTYPES_BLINKER 32778

#define ID_MAINPROTOTYPES_BEACON 32779

#define ID_MAINPROTOTYPES_GLIDER 32780

#define ID_Menu 32781

#define ID_MAINPROTOTYPES_SMALLSHIP 32782

#define ID_MAINPROTOTYPES_P46_GLIDERGUN 32783

#define ID_MAINPROTOTYPES_HERZOSCILLATOR 32784

#define ID_MAINPROTOTYPES_LINE 32785

#define ID_FICHIER_FILL 32786

#define ID_FILL_1 32787

#define ID_FILL_5 32788

#define ID_FILL_10 32789

#define ID_FILL_15 32790

#define ID_FILL_20 32791

#define ID_FILL_25 32792

#define ID_FILL_30 32793

#define ID_FILL_40 32795

#define ID_FILL_50 32797

#define ID_FILL_60 32799

#define ID_FILL_70 32801

#define ID_FILL_80 32803

#define ID_R32807 32807

#define ID_R32808 32808

#define ID_WOLFRAM_B018 32809

#define ID_WOLFRAM_B0578 32810

#define ID_WOLFRAM_B579 32811

#define ID_WOLFRAM_B1 32812

#define ID_WOLFRAM_B123567 32813

#define ID_WOLFRAM_B13456 32814

#define ID_WOLFRAM_B135 32815

#define ID_WOLFRAM_B137 32816

#define ID_WOLFRAM_B236 32817

#define ID_WOLFRAM_B257 32818

#define ID_WOLFRAM_B3 32819

#define ID_WOLFRAM_B34 32820

#define ID_WOLFRAM_B367 32821

#define ID_WOLFRAM_B378 32822

#define ID_R32823 32823

#define ID_R32824 32824

#define ID_R32825 32825

#define ID_R32826 32826

#define ID_R32827 32827

#define ID_R32828 32828

#define ID_R32829 32829

#define ID_R32830 32830

#define ID_R32831 32831

#define ID_R32832 32832

#define ID_R32833 32833

#define ID_R32834 32834

#define ID_R32835 32835

#define ID_R32836 32836

#define ID_R32837 32837

#define ID_R32838 32838

#define ID_R32839 32839

#define ID_R32840 32840

#define ID_R32841 32841

#define ID_R32842 32842

#define ID_STEP 32843

#define ID_RAND_FILL 32844

#define ID_CLEAR 32845

#define ID_R32849 32849

#define ID_TYPEDECHAMP_INFINIE 32850

#define ID_TYPEDECHAMP_WITHBORDERS 32851

#ifndef IDC_STATIC

#define IDC_STATIC-1

#endif

// Next default values for new objects

//

#ifdef APSTUDIO_INVOKED

#ifndef APSTUDIO_READONLY_SYMBOLS

#define _APS_NEXT_RESOURCE_VALUE 135

#define _APS_NEXT_COMMAND_VALUE 32852

#define _APS_NEXT_CONTROL_VALUE 1004

#define _APS_NEXT_SYMED_VALUE 110

#endif

#endif

Вихідний файл №3: Course_Proj_31_Game_LIFE_PS.cpp

// Course_Proj_31_Game_LIFE_PS.cpp : dйfinit le point d'entrйe pour l'application.

//

/*

Разработать программу клеточного автомата «жизнь». Экран разбивается на клеточное поле. Каждая клетка может быть в 2-х состояниях: пустая и содержащая «организм» (Х). Колония «организмов» развивается во времени следующим образом: если пустая клетка имеет по соседству 2 или 3 «организма», то в следующий момент времени в ней появляется новый «организм»; если занятая клетка имеет более 4 соседей, то в следующий момент времени она «умирает» (становиться пустой). Организовать начальное заполнение поля и просмотр развития колонии клеток во времени.

*/

#include "stdafx.h"

#include "Course_Proj_31_Game_LIFE_PS.h"

#include <process.h>

HWND hWnd;

PAINTSTRUCT ps;

static HDC hdc;

CRITICAL_SECTION cs;

BOOL flag{ false };

extern unsigned int counter;

enum class Rules

{

CurrentRule, B018_S018, B0578_S045, B0578_S12456, B1_S012345678, B1_S1_Gnarl, B123567_0238, B13456_S01356, B135_S135, B1357_S1357_Replicator, B137_S45678, B236_S0468, B257_S27, B3_S012345678_ImmortalLife, B3_S12345_Maze, B3_S23_CONWAY_LIFE, B3_S234, B3_S45678_Coral, B34_S03456, B34_S34_34LIFE, B345_S4567_Assimilation, B345_S5_LongLife, B35678_S5678_Diamoeba, B357_S1358_Amoeba, B357_S238_PseudoLife, B36_S125_2x2, B36_S23_HighLife, B367_S2346, B3678_S235678_Stains, B3678_S34678_Day_Night, B368_S245_Motion, B378_S012345678, B378_S235678_Concretion, B45678_S2345_Towns_Walls, B23_S01234_TASK_OF_COURSE_PROJ

};

char buffer[5];

#define MAX_LOADSTRING 100

#define IDT_TIMER1 66692

// Variables globales :

HINSTANCE hInst; // instance actuelle

WCHAR szTitle[MAX_LOADSTRING]; // Le texte de la barre de titre

WCHAR szWindowClass[MAX_LOADSTRING]; // le nom de la classe de fenкtre principale

HWND bStep, bRand, bReset;

HBRUSH hb{ CreateSolidBrush(RGB(0, 0, 0)) };

static t_cells cells_coord;

static t_generation life_Generation, next_Generation;

// Prй-dйclarations des fonctions incluses dans ce module de code :

ATOM MyRegisterClass(HINSTANCE hInstance);

BOOL InitInstance(HINSTANCE, int);

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,

_In_opt_ HINSTANCE hPrevInstance,

_In_ LPWSTR lpCmdLine,

_In_ int nCmdShow)

{

UNREFERENCED_PARAMETER(hPrevInstance);

UNREFERENCED_PARAMETER(lpCmdLine);

srand(time(NULL));

initCoord(cells_coord);

fillField(life_Generation, rand() % 100);

// Initialise les chaоnes globales

LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);

LoadStringW(hInstance, IDC_COURSEPROJ31GAMELIFEPS, szWindowClass, MAX_LOADSTRING);

MyRegisterClass(hInstance);

// Effectue l'initialisation de l'application :

if (!InitInstance(hInstance, nCmdShow))

{

return FALSE;

}

HACCEL hAccelTable{ LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_COURSEPROJ31GAMELIFEPS)) };

MSG msg;

// Boucle de messages principale :

while (GetMessage(&msg, nullptr, 0, 0))

{

if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))

{

TranslateMessage(&msg);

DispatchMessage(&msg);

}

}

return (int)msg.wParam;

}

//

// FONCTION : MyRegisterClass()

//

// BUT : inscrit la classe de fenкtre.

//

ATOM MyRegisterClass(HINSTANCE hInstance)

{

WNDCLASSEXW wcex;

wcex.cbSize = sizeof(WNDCLASSEX);

wcex.style = CS_HREDRAW | CS_VREDRAW;

wcex.lpfnWndProc = WndProc;

wcex.cbClsExtra = 0;

wcex.cbWndExtra = 0;

wcex.hInstance = hInstance;

wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));

wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);

wcex.hbrBackground = (HBRUSH)hb;

wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_COURSEPROJ31GAMELIFEPS);

wcex.lpszClassName = szWindowClass;

wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_ICON1));

return RegisterClassExW(&wcex);

}

//

// FONCTION : InitInstance(HINSTANCE, int)

//

// BUT : enregistre le handle de l'instance et crйe une fenкtre principale

//

// COMMENTAIRES :

//

// Dans cette fonction, nous enregistrons le handle de l'instance dans une variable globale, puis

// crйons et affichons la fenкtre principale du programme.

//

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)

{

hInst = hInstance; // Stocke le handle d'instance dans la variable globale

hWnd = CreateWindow(szWindowClass,

szTitle,

WS_DLGFRAME | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,

20, 20, LIFE_SIZE*CELL_RADIUS + 17, 1050, NULL, NULL, hInstance, NULL); бібліотека екран гра тестування

if (!hWnd)

return FALSE;

ShowWindow(hWnd, nCmdShow);

UpdateWindow(hWnd);

return TRUE;

}

//

// FONCTION : WndProc(HWND, UINT, WPARAM, LPARAM)

//

// BUT : traite les messages pour la fenкtre principale.

//

// WM_COMMAND - traite le menu de l'application

// WM_PAINT - dessine la fenкtre principale

// WM_DESTROY - gйnиre un message d'arrкt et retourne

//

//

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{

UINT idCtl;

PAINTSTRUCT ps;

const RECT rt = { 0, 0, LIFE_SIZE*CELL_RADIUS, LIFE_SIZE*CELL_RADIUS };

const RECT* RECT{ &rt };

static bool isInfinite{ FALSE };

switch (message)

{

case WM_CREATE:

bStep = CreateWindow(L"BUTTON", L"Step", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 350, 960, 80, 20, hWnd, (HMENU)1, hInst, NULL);

bRand = CreateWindow(L"BUTTON", L"Random fill", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 465, 960, 80, 20, hWnd, (HMENU)2, hInst, NULL);

bReset = CreateWindow(L"BUTTON", L"Reset", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 570, 960, 80, 20, hWnd, (HMENU)3, hInst, NULL);

break;

case WM_COMMAND:

{

int wmId{ LOWORD(wParam) };

// Analyse les sйlections de menu :

switch (wmId)

{

case IDM_ABOUT:

DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);

break;

case IDM_EXIT:

DestroyWindow(hWnd);

break;

case ID_MAINPROTOTYPES_P46_GLIDERGUN:

InvalidateRect(hWnd, RECT, TRUE);

P46_glider_gun(life_Generation);

break;

case ID_MAINPROTOTYPES_BLINKER:

InvalidateRect(hWnd, RECT, TRUE);

Blinker(life_Generation);

break;

...

Подобные документы

  • Аналіз теоретичної бази методів інтерполювання функцій. Розробка алгоритмів та вибір оптимального. Приклад програми інтерполювання функції за допомогою інтерполяційного многочлена Лагранжа: інструкція користувача, опис, тестування та лістинг програми.

    курсовая работа [1,0 M], добавлен 19.09.2013

  • Інструменти середовища C++Builder, які були використані в програмі. Робота з файлами, їх відкриття, відображення та закриття. Розробка основних функцій для реалізації програми. Тестування програмного забезпечення. Блок-схема та алгоритм програми.

    курсовая работа [924,3 K], добавлен 14.01.2014

  • Опис методів і алгоритмів вирішення задачі в середовищі розробки Myeclipse. Основні функції програмного продукту, його структура. Розробка алгоритму та програми, інструкція користувачу. Результати тестування, лістинг основних блоків. Вікно головного меню.

    курсовая работа [1,8 M], добавлен 24.02.2014

  • Програми, які виводять на екран характеристики комп'ютера. Розробка програми "Монітор використання ресурсів комп’ютера" на мові програмування ASM-86. Алгоритм програми та її реалізація. Системні вимоги, інструкція для користувача, лістинг програми.

    курсовая работа [22,2 K], добавлен 08.08.2009

  • Аналіз технічного забезпечення, вибір інструментального програмного забезпечення та середовища розробки програм. Створення класів для реалізації необхідних функцій для роботи програмного засобу. Розробка інтерфейсу для користувача та лістинг програми.

    курсовая работа [343,9 K], добавлен 24.08.2012

  • Створення комп'ютерної програми на мові програмування С++ для ведення обліку мобільних телефонів на складі-магазині. Вимоги до апаратного та програмного забезпечення. Схема зв'язку між складовими частинами програми. Інструкція користувача, тестування.

    дипломная работа [4,2 M], добавлен 06.06.2012

  • Характеристика предметної області: FTP-server для ОС Windows. Шляхи встановлення FTP-серверу в ОС Windows. Опис мови та середовища програмування, компонентів та функцій програми. Аналіз реалізованої програми FTP-клієнта. Тестовий запуск та опис програми.

    курсовая работа [1,7 M], добавлен 22.06.2017

  • Призначення менеджеру пристроїв. Обґрунтування вибору мови програмування. Розробка структурної схеми і опис діалогового інтерфейсу програми. Блок-схема програмного додатку, основні функції і алгоритм його роботи. Методики і інструкція його тестування.

    курсовая работа [3,4 M], добавлен 17.11.2014

  • Розробка та використання програми для пришвидшення процесу перетворення двомірного зображення у об'ємне. Методика та процес випробовування для виявлення та усунення недоліків в роботі програми. Інтерфейс програми, встановлення параметрів зображення.

    курсовая работа [3,2 M], добавлен 09.06.2010

  • Розробка програми для моделювання роботи алгоритму Дейкстри мовою C# з використанням об’єктно-орієнтованих принципів програмування. Алгоритм побудови робочого поля. Програмування графічного інтерфейсу користувача. Тестування програмного забезпечення.

    курсовая работа [991,4 K], добавлен 06.08.2013

  • Розробка алгоритму по виявленню і локалізації особи на зображенні у візуальному середовищі Delphi. Розробка програми по виділенню областей кольору шкіри особи, крапок, ліній і яскравості зображення. Опис структури програми і інтерфейсу користувача.

    курсовая работа [3,9 M], добавлен 07.01.2014

  • Призначення ігрової програми "Змійка" для розвитку уваги та логічного мислення гравців. Розробка програми в середовищі C++ Builder 6, її функціонування в ОС Windows. Опис алгоритму та основних функцій програми. Основні переваги та недоліки мови С++.

    реферат [1,7 M], добавлен 17.12.2014

  • Побудова інформаційно-математичної моделі та алгоритм задачі. Визначення структури даних. Розробка інтерфейсу програми з користувачем. Складання коду програми. Реалізація проекту у візуальному середовищі. Тестування та інструкція з експлуатації програми.

    курсовая работа [1,3 M], добавлен 14.04.2009

  • Основи розробки додатків Windows. Параметри функції WinMain. Запуск процесу, використання для цього вибраних на диску файлів. Відслідковування кожного з процесів (його статус, назву, час життя), діяльності користувача. Опис алгоритму роботи програми.

    курсовая работа [202,6 K], добавлен 14.05.2015

  • Загальна характеристика алгоритму та опис програми. Керівництво системного програміста. Особливості запуску програми в Linux, FreeBSD, Windows. Аналіз результатів тестування програми, що проектується, вивчення та оцінка її практичної ефективності.

    курсовая работа [91,4 K], добавлен 13.06.2014

  • Аналіз предметної області і постановка задачі на розробку програми для автоматизації роботи автопідприємства. Перелік та опис використаних компонентів та основних процедур програми. Опис структур та методів обробки даних. Інструкція для користувача.

    курсовая работа [2,3 M], добавлен 15.02.2012

  • Програмування під DOS мовою низького рівня Асемблер (ASM-86). Функції програми: виведення в довільне місце екрану тексту заданого стилю та кольору, змінення шрифту, розміру літер та напрямку їх виводу. Алгоритм програми, системні вимоги до комп'ютера.

    курсовая работа [47,4 K], добавлен 03.06.2009

  • Розробка структури програмного забезпечення, загальної схеми функціонування програми. Реалізація виведення графічних зображень, роботи з шлагбаумом, загальних елементів керування та музики. Інструкція з технічного обслуговування, системного програміста.

    курсовая работа [3,1 M], добавлен 10.03.2009

  • Розробка програми GameBox, яка включає в себе дві гри, судоку та пятнашки. Опис структури даних та вимоги до них, процедур і функцій користувача, стандартних процедур і функцій, які використовувались в програмі, та файлів. Результати роботи програми.

    курсовая работа [5,3 M], добавлен 12.11.2011

  • Розробка і обґрунтування технічного завдання, вимоги до програмної реалізації та користувача. Можливі варіанти зміни та вдосконалення програми. Початок загального алгоритму вирішення задачі. Структурні зв’язки між функціями програми, її тестування.

    курсовая работа [1,8 M], добавлен 14.03.2013

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.