Как проделать рандомайз?
- Войдите на сайт для отправки комментариев
Ср, 01/07/2020 - 13:46
Пришла в голову дурная блажь повыпендриваться с 7-сегментными модулями на мах7219. Их шесть штук, в каждом по 8 разрядов. Что хочу: в хаотичном порядке заполнить все разряды всех модулей "восьмерками". Понятно, что у нас для таких целей есть функция random(). Вот только, как сделать, чтобы в поисках случайного числа не участвовали уже зажженные разряды с "восьмеркой" - никак не допетрю. Дайте подсказку, ссылку, пояснение, (я уже совсем обнаглел) - скетчик... Заранее благодарен!
Массив из 48-ми булевых переменных же? Или двухмерный 6х8 по вкусу?
Массив из 48-ми булевых переменных же? Или двухмерный 6х8 по вкусу?
Про массив того или иного вида - это понятно. Меня (видимо, был косноязычен) интересует процесс исключения из функции random () уже исполненных (зажженных) элементов массива. Вроде, рэндом в каждом очередном цикле все равно будет выбирать из исходного количества чисел. Тем самым, скорость заполнения табло станет заметно уменьшаться по мере зажигания все большего числа элементов. Или я не так рассуждаю?
Можно конечно и на массиве с отметками уже зажженных элементов. По нему циклически бегает индекс. Генерим рандом 1-48 и перемещаем индекс на этот рандом, пропуская уже занятые. Но плохо, последние элементы долго искать.
Есть и другой подход. Массив из 48 элементов заполняем последовательно значениями от 1 до 48. Рандомно генерим два номер элемента. И обмениваем их содержимое. Так повторяем пока не надоест. По сути массив перетасовывается. Далее в элементе 0 - номер первого зажигаемого разряда, в элементе 1 - номер следующего и так до конца.
Эта задача на собеседованиях встречается. Первое решение считают не оптимальным.
есть стандартный алгоритм перемешивания, называется std::random_shuffle. Исходники - открыты.
Новый вопрос. Вот простенький скетч:
#include <LedControl.h> //Загрузка библиотеки индикаторов на мах7219 //Пины управления индикацией int pin_din_1=32; //Пин din цепочки №1 int pin_cs_1=30; //Пин cs цепочки №1 int pin_clk_1=28; //Пин clk цепочки №1 //GND цепочки №1 int pin_din_2=33; //Пин din цепочки №2 int pin_cs_2=31; //Пин cs цепочки №2 int pin_clk_2=29; //Пин clk цепочки №2 //GND цепочки №2 //Cоздаём объекты класса LedControl [din,clk,cs,X)]четвертая цифра "X" - количество модулей. Управляем двумя цепочками модулей по 6 элементов LedControl lc_1 = LedControl(pin_din_1, pin_clk_1, pin_cs_1, 6); LedControl lc_2 = LedControl(pin_din_2, pin_clk_2, pin_cs_2, 6); //Переменные теста индикации int ind; int dig; void setup () { //Выводим индикаторы из спящего режима for (ind=0;ind<6;ind++) { //Цепочка №1 lc_1.shutdown(ind, false); //Выводим из спящего режима lc_1.setIntensity(ind,1); //Яркость дисплея на 1. Всего возможных режимов яркости от 0 до 15 lc_1.clearDisplay(ind); //Очистить дисплей //Цепочка №2 lc_2.shutdown(ind, false); //Выводим из спящего режима lc_2.setIntensity(ind,1); //Яркость дисплея на 1. Всего возможных режимов яркости от 0 до 15 lc_2.clearDisplay(ind); //Очистить дисплей } //Выравнивание яркости модулей индикаторов lc_1.setIntensity(0,5); lc_2.setIntensity(1,6); lc_2.setIntensity(5,5); } void loop () { ind=random (6); dig=random (8); lc_1.setDigit (ind,dig,8,false); delay (20); }И что я вижу? Каждый раз при запуске программы последовательность прописывания индикаторов одна и та же. Или я что-то не понимаю и делаю не так (скорее всего!) или где тогда произвольный выбор чисел?
randomSeed()
Поставил вместо "random" "randomSeed". Гадость какую-то говорит компилятор: "void value not ignored as it ought to be". Перевел, но не понял: "Значение void не игнорируется, как надо". Если не трудно - поправьте неверную строку.
Наверное надо посмотреть синтаксис, а не копипастить бездумно?
Да нету у ардуинки случайных чисел! 100500 раз обсуждалось. Хотите истинно случайное число - делайте его аппаратно на шумящих элементах.
Содрал тупо с нашего сайта отсюда: http://arduino.ru/Reference/RandomSeed
Получилось:
#include <LedControl.h> //Загрузка библиотеки индикаторов на мах7219 //Пины управления индикацией int pin_din_1=32; //Пин din цепочки №1 int pin_cs_1=30; //Пин cs цепочки №1 int pin_clk_1=28; //Пин clk цепочки №1 //GND цепочки №1 int pin_din_2=33; //Пин din цепочки №2 int pin_cs_2=31; //Пин cs цепочки №2 int pin_clk_2=29; //Пин clk цепочки №2 //GND цепочки №2 //Cоздаём объекты класса LedControl [din,clk,cs,X)]четвертая цифра "X" - количество модулей. Управляем двумя цепочками модулей по 6 элементов LedControl lc_1 = LedControl(pin_din_1, pin_clk_1, pin_cs_1, 6); LedControl lc_2 = LedControl(pin_din_2, pin_clk_2, pin_cs_2, 6); //Переменные теста индикации int ind; int dig; void setup () { //Выводим индикаторы из спящего режима for (ind=0;ind<6;ind++) { //Цепочка №1 lc_1.shutdown(ind, false); //Выводим из спящего режима lc_1.setIntensity(ind,1); //Яркость дисплея на 1. Всего возможных режимов яркости от 0 до 15 lc_1.clearDisplay(ind); //Очистить дисплей //Цепочка №2 lc_2.shutdown(ind, false); //Выводим из спящего режима lc_2.setIntensity(ind,1); //Яркость дисплея на 1. Всего возможных режимов яркости от 0 до 15 lc_2.clearDisplay(ind); //Очистить дисплей } //Выравнивание яркости модулей индикаторов lc_1.setIntensity(0,5); lc_2.setIntensity(1,6); lc_2.setIntensity(5,5); randomSeed(0); } void loop () { ind=random(6); dig=random(8); lc_1.setDigit (ind,dig,8,false); delay (20); }Ничего не изменилось.
Содрал тупо с нашего сайта отсюда
А надо было не тупо драть, а хотяб прочитать описание этой функции ))) Ну чтоб понять что это не по теме того что хотели. Я так понял вы решили советов, которых просили не слушать?
По вашему новому вопросу - random генерит псевдослучайное число из циклической последовательности некоторой. randomSeed сместит текущее положение в последовательности.
И что я вижу? Каждый раз при запуске программы последовательность прописывания индикаторов одна и та же. Или я что-то не понимаю ...........
Фсё-то ты панимашь, возможно даже и больше, чем надо. Вопросы твои всё больше и больше похожи на некий оччень тонкий глум форумный. Хотя вроде не школьнег......
А по поводу рандома - дык так оно и будет, ибо каждый раз дурдуина стартует по одному и тому-же сценарию.
Для того, чтобы изменить сценарий - нужно добавить ещё хотя-бы один элемент "рандомности" , например, время. И тогда всё будет так, как ты и хотел изначально (задача поиска пустого горшка для тех, кому ..... срочно) ))))))))))))))))))))))))))))))))))))))))))))))))))
Щас миллис добавит...
)))
Блин, мужики! Ну хорош меня пинать. Это не глум вовсе. Я - старый бэсиковод. Там в отличие от С (как я понимаю) рандомайз абсолютно честный: задал предел - и все: генерируется случайное число "от и до". Я ж не знал, что тут все по-другому. Рекомендуете миллис вставить. А что это даст? Миллис же будет тем же самым, то есть, последовательность заполнения не изменится. Ну уж коль пошла такая пьянка, поправьте скетч, чтоб я понял, в чем затыка. А уж если к комментариями...
Миллс нипамагёт, он так0же стартанёт вместе с процом ))))))))))))))))))))))))))))
Здеся надо чонить отдельное от ардуины - т.е. отдельные часы или ещё что отдельное... ну хоть фазу в электросети...
Миллс нипамагёт, он так0же стартанёт вместе с процом ))))))))))))))))))))))))))))
Здеся надо чонить отдельное от ардуины - т.е. отдельные часы или ещё что отдельное... ну хоть фазу в электросети...
То есть, если, скажем, один из выводов Ахххх висит в воздухе и болтается как говно в проруби, с него можно взять аналогрид, и от этого плясать?
Все, проделал randomSeed с со свободного вывода А0. Сработало. Все спасибо, процесс понял.
Дядько, ну раздэзь функцию рандома и сам всё поймёшь.
И по поводу ног аналоговых - напиши простую функцию вывода значений в сериал да посмотри на "аналоговую рандомность" ))))))))
В примере с сайта как раз с А0 рэндомсид и делался.
От он и сработал :)
Массив из 48-ми булевых переменных же? Или двухмерный 6х8 по вкусу?
Про массив того или иного вида - это понятно. Меня (видимо, был косноязычен) интересует процесс исключения из функции random () уже исполненных (зажженных) элементов массива. Вроде, рэндом в каждом очередном цикле все равно будет выбирать из исходного количества чисел. Тем самым, скорость заполнения табло станет заметно уменьшаться по мере зажигания все большего числа элементов. Или я не так рассуждаю?
А хто мешат замутить асинхронную функцию и считать "наперёд" в отдельный массив?
Чото типа вывод синхронизировать по таймеру или любому другому событию а массив вычислять "наперёд" , разделив функцию на несколько коротких итераций? Не???
Вот тебе твоя игрушка на JS. Посмотреть можно на любом онлайн редакторе или в броузере открыть, сохранив как .html файл. Можно на https://js.do скопипастив туда.
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <link href="styles/style.css" rel="stylesheet" type="text/css"> <title>Случайный порядок</title> </head> <body> <canvas width="400" height="300"></canvas> <script> var canvas = document.querySelector("canvas"); var context = canvas.getContext("2d"); context.fillStyle = "red"; context.strokeStyle = "black"; context.lineWidth = 2; function D7(x, y, cx,w=36,h=36,l=8) { this.x = x; this.y = y; this.w = w; this.h = h; this.l = l; this.context = cx; this.show = function (...ii) { for (i=0; i< ii.length; i++) { switch (ii[i]) { case 1: this.context.fillRect(x + l + 1, y, w - 2 * l - 2, l); break; case 2: this.context.fillRect(x + w - l, y, l, h - 1); break; case 3: this.context.fillRect(x + w - l, y + h + 1, l, h - 1); break; case 4: this.context.fillRect(x + l + 1, y + 2 * h - l, w - 2 * l - 2, l); break; case 5: this.context.fillRect(x, y + h + 1, l, h - 1); break; case 6: this.context.fillRect(x, y, l, h - 1); break; case 7: this.context.fillRect(x + l + 1, y + h - l / 2, w - 2 * l - 2, l); break; case 8: this.context.fillRect(x + w + 1, y + 2 * h - l, l, l); break; } } } } d7a = new Array(6); for (i = 0; i < 6; i++) { d7a[i] = new D7(30+i*46,30 , context); } seg = new Array(48); for (i=0; i<48;i++) seg[i] = i; for (i = 47; i > 0; i--) { j = Math.floor(Math.random() * (i + 1)); tmp = seg[i]; seg[i] = seg[j]; seg[j] = tmp; } var iii = 0; function mySt () { d7a[Math.floor(seg[iii]/8)].show(seg[iii]%8+1); iii++; if (iii > 48) iii=0; } tId = setInterval(mySt,100); setTimeout(() => { clearInterval(tId); }, 4900); </script> </body> </html>