Если когда-нибудь пытались написать свой Тетрис, сделать электронную свечку или собрать светомузыку — точно использовали случайные числа. Пара строк кода и программа уже выдаёт новую фигурку или яркость светодиода. Всё просто?
На самом деле нет. Компьютер штука умная, но предельно логичная. Выполнить сложную программу, обработать тысячи чисел за долю секунды — никаких проблем, но придумать действительно случайное число компьютер не может. Все «случайные» числа это результат выполнения заранее написанной программы. Поэтому правильнее называть их псевдослучайными.
В проектах на Arduino для получения псевдослучайного числа предусмотрена функция random(). В параметрах функции можно задать диапазон получаемых значений, от минимального до максимального.
long randNumber; void setup(){ Serial.begin(9600); } void loop() { randNumber = random(1000); // выбираем случайное число от 0 до 999 Serial.println(randNumber); // выводим число в Serial Port delay(1000); // ждём одну секунду }
Если вы запустите этот скетч, увидите, что после каждого перезапуска платы последовательность чисел будет повторяться. Чтобы последовательность не повторялась, необходимо запустить генератор случайных чисел со случайным параметром. Для этого предусмотрена функция randomSeed(). В качестве параметра функции зададим номер свободного аналогового пина. Шум с него инициализирует генератор случайных чисел.
long randNumber; void setup(){ Serial.begin(9600); randomSeed(analogRead(0)); } void loop() { randNumber = random(10, 100); Serial.println(randNumber); delay(1000); }
Это самый простой игровой автомат. Arduino Uno, пара светодиодов и тактовая кнопка. Нажимаете кнопку — случайным образом загорается один из светодиодов: или красный, или зелёный. Угадали какой загорится, можно подавать заявку на участие в «Битве экстрасенсов».
В проекте использовались:
// подключим библиотеку для работы с кнопками #include <TroykaButton.h> // Пины светодиодов #define LRED 8 #define LGREEN 10 // Пин кнопки #define BUTTON 6 // создаем объект класса TroykaButton TroykaButton but(BUTTON); unsigned long timer = 0; void setup() { // определяем пины как входы/выходы pinMode (LRED, OUTPUT); pinMode (LGREEN, OUTPUT); pinMode (BUTTON, INPUT_PULLUP); // инициализируем последовательность случайных чисел randomSeed(analogRead(A3)); // инициализируем кноку but.begin(); } void loop() { // считываем значение кнопки but.read(); // было ли короткое нажатие? if (but.isClick()) { // задаем случайное значение для "монеты" int coin = random(2); // проверяем, что за значение: if (coin) { // если 1, то зеленый светодиод горит 1 секунду timer = millis(); while (millis() - timer < 1000) { digitalWrite(LGREEN, HIGH); } digitalWrite(LGREEN, LOW); } else { // если 0, то красный светодиод горит 1 секунду timer = millis(); while (millis() - timer < 1000) { digitalWrite(LRED, HIGH); } digitalWrite(LRED, LOW); } } }
Игровой автомат генерирует трёхзначное число. Если всецифры в нём совпали — Bingo! Если нет, попробуйте свою удачу ещё раз.
Игровой автомат собран в образовательных целях. Использовать подобные устройства для получения прибыли запрещено законами Российской Федерации.
В проекте использовались:
// Подключаем библиотеку для работы с дисплеем #include <QuadDisplay2.h> #include <TroykaButton.h> // Пин для пищалки #define BUZZER 4 // Пин для кнопки #define BUTTON 6 // Пин для дисплея #define QUADDISPLAY 10 // ноты для мелодий #define NOTE_C3 131 #define NOTE_CS3 139 #define NOTE_D3 147 #define NOTE_DS3 156 #define NOTE_E3 165 #define NOTE_F3 175 #define NOTE_FS3 185 #define NOTE_G3 196 #define NOTE_GS3 208 #define NOTE_A3 220 #define NOTE_AS3 233 #define NOTE_B3 247 #define NOTE_C4 262 #define NOTE_CS4 277 #define NOTE_D4 294 #define NOTE_DS4 311 #define NOTE_E4 330 #define NOTE_F4 349 #define NOTE_FS4 370 #define NOTE_G4 392 #define NOTE_GS4 415 #define NOTE_A4 440 #define NOTE_AS4 466 #define NOTE_B4 494 #define NOTE_C5 523 // Номер октавы #define OCTAVE 2 // Длительность таймера #define CLOCK 1000 // создаем объект класса QuadDisplay и передаем номер пина CS QuadDisplay qd(QUADDISPLAY); // создаем объект для работы с кнопкой с параметром номер пина TroykaButton button(BUTTON); // создаем флаг для кнопки bool buttonFlag = true; // создаем объект класса long для хранения счетчика времени unsigned long timer; // создаем массив для хранения цифр дисплея const uint8_t digits[] = {QD_0, QD_1, QD_2, QD_3, QD_4, QD_5, QD_6, QD_7, QD_8, QD_9}; // создаем массив с анимацией ожидания const uint8_t animated[] = {0b11111011, 0b11110111, 0b11101111, 0b11011111, 0b10111111, 0b01111111, 0b11111011}; // создаем массив с нотами для стартовой мелодии int startTune[] = {NOTE_C4, NOTE_C4, NOTE_G4, NOTE_C5, NOTE_G4, NOTE_C5}; // создаем массив с длительностями нот для стартовой мелодии int durationStartTune[] = {100, 100, 100, 300, 100, 300}; // создаем массив с нотами для мелодии победы int gameWin[] = {NOTE_C4, NOTE_F4, NOTE_C4, NOTE_F4, NOTE_C4, NOTE_F4, NOTE_C4, NOTE_F4, NOTE_G4, NOTE_F4, NOTE_E4, NOTE_F4, NOTE_G4}; // создаем массив с длительностями нот для мелодии победы int durationGameWin[] = {100, 200, 100, 200, 100, 400, 100, 100, 100, 100, 200, 100, 500}; void setup() { // инициализируем дисплей qd.begin(); // инициализируем кноку button.begin(); } void loop() { // запускаем цикл воспроизводящий надпись "Play", которая прерывается нажатием кнопки timer = millis(); buttonFlag = !buttonFlag; while (millis() - timer < CLOCK) { if (buttonFlag) { qd.displayDigits(QD_P, QD_L, QD_A, QD_Y); } else { qd.displayClear(); } // считываем значение кнопки button.read(); // было ли короткое нажатие? if (button.isClick()) { // создаем массив символов для отображения выпавшего числа uint8_t value[] = {QD_NONE, QD_NONE, QD_NONE}; // воспроизводим стартовую мелодию melody(startTune, durationStartTune, sizeof(startTune) / sizeof(int)); // запускаем функцию генерации случайного числа bandit(value); // воспроизводим анимацию cartoon(value); if (value[0] == value[1] && value[1] == value[2] && value[0] == value[2]) { melody(gameWin, durationGameWin, sizeof(gameWin) / sizeof(int)); } else { if (value[0] == value[1] || value[1] == value[2] || value[0] == value[2]) { melody(gameWin, durationGameWin, 4); } } buttonFlag = true; } } } // функция, которая генерирует случайное число void bandit(uint8_t value[]) { randomSeed(analogRead(A3)); // инициализируем последовательность случайных чисел for (int i = 0; i < 3; i++) { // записываем случайные числа в массив value[i] = digits [random(0, 9)]; } } // функция, которая воспроизводит анимацию показа числа на дисплее void cartoon (uint8_t value[]) { for (int j = 0; j <= 4; j++) { for (int i = 0; i < (sizeof (animated) / sizeof(uint8_t)); i++) { timer = millis(); while (millis() - timer < (CLOCK / 20)) { switch (j) { case 0: { qd.displayDigits (animated[i], animated[i], animated[i], QD_NONE); break; } case 1: { qd.displayDigits (value[0], animated[i], animated[i], QD_NONE); break; } case 2: { qd.displayDigits (value[0], value[1], animated[i], QD_NONE); break; } case 3: { qd.displayDigits (value[0], value[1], value[2], QD_NONE); break; } } } } } } // функция воспроизведения мелодий void melody(int melody[], int noteDurations[], int noteCount) { // Играем мелодию for (int thisNote = 0; thisNote < noteCount; thisNote++) { tone(BUZZER, OCTAVE * melody[thisNote]); delay(noteDurations[thisNote]); noTone(BUZZER); } }