Алгоритм выбора с условием

А их не надо менять случайным образом. Доступность пункта меню должна проверяться в момент его отображения, если уж на то пошло.

Но вы, похоже, не поняли смысла. Каждый пункт меню здесь - отдельный объект, описанный структурой MenuItem. В этой структуре можно хранить не только признак активности и строку, но и черта лысого: идентификаторы, ссылку на родительский пункт меню, ссылку на дочернее меню и т.д., и т.п. Все в одном месте. И работать с ним соответственно

2 лайка

Да это все понятно… Это не совсем у меня меню. А доступность выбора как раз так и делаю, проверка перед самим выбором.

А это без разницы. Если у чего-то больше одного свойства, то лучше оформлять его объектом

1 лайк

Согласен. Я в курсе и про списки, коллекции, листы, деревья, итэмы и т.д… Но в данном слу, ае у меня задача гораздо проще именно так как я её и описал в самом начале… Возможно кто-то меня понял несовсем верно, но самое главное намекнули на решение… Спасибо

Если честно - у меня даже мыслей нет как «ещё проще» сделать то, что описано в #1

Подход к написанию рекурсии неверный.

Запомните, первое (от слова совсем первое), что должно делаться в рекурсивной функции – проверка параметра, зависящего от глубины.

Вы же её вляпали в 24-ую строку. Ну, хорошо, к Вам изначально обратились с параметром, который больше-равен maxItem (а это делается в строке №11 когда текущий currentIndex равен 4). И? Вы в строке №21 полезли проверять menuItemStat[5], т.е. вылезли за границу массива, там оказался “не ноль” и … Вы вернули пятёрку. Дальше также вернули шестёрку. А потом (в menuItemStat[7]) оказалась false и всё восстановилось.

Если бы Ваша рекурсивная функция начиналась бы так:

uint8_t getNextIndex(uint8_t currInd) {
    if (currInd >= maxItem) currInd = 0;
// дальше сами пишите

эта проблема никогда не возникла бы.

Запомните, проверка - первое, всё остальное - потом.

3 лайка

Спасибо Евгений Петрович, я уже с подсказки @andriano это понял. :slight_smile:

Ночью приехал, но что-то спать очень хотелось…)))

Вот:

Спойлер
#define ITEM_COUNT 5
byte Ind;

byte * fillArr(byte Arr[], byte ArrCnt) {
  Arr[0] = 0;
  Arr[1] = 0;
  Arr[2] = 0;
  Arr[3] = 0;
  Arr[4] = 0;
  //for (byte n = 0; n < ArrCnt; n++) Arr[n] = random(10);
  return Arr;
}

byte getNextIndex (byte CurrInd, byte Arr[], byte itemCount) {
  if (CurrInd >= itemCount) return 0;
  for (byte n = CurrInd; n < itemCount; n++)
    if (Arr[n]) return n + 1;
  return 0;
}

void setup() {
  Serial.begin(115200);
}

void loop() {
  byte IArr[ITEM_COUNT];
  Ind = getNextIndex (Ind, fillArr(IArr, ITEM_COUNT), ITEM_COUNT);
  Serial.println(Ind);
  delay(500);
}

Без рекурсий и с учетом динамичного (в fillArr закомментировать <вообще удалить, они для теста, как собсно и рандомные, тут потом будет "реальное "заполнение> статичные присваивание и раскомментировать рандомные) изменения состояний и проверкой их перед вычислением следующего индекса… Так же все пункты могут быть выключены…
В fillArr я буду предварительно собирать массив состояний на данный момент времени “пунктов”
Как то так… С дороги может где и накосячил, проснулся, написал и сразу сюда… может на попкорн еще успею :wink:

ЗЫЖ Возможно ITEM_COUNT не обязательно передавать в функции а работать с ним напрямую…

А так если

const uint8_t Size = 5;// количество пунктов меню
uint8_t menuItemStat[] = {1, 0, 1, 1, 1};

void setup() {
  Serial.begin(9600);
}

void printItem(byte num){
  Serial.print("item  ");
  Serial.println(num);
}

void loop() {
 static uint8_t n = 0;
 if( menuItemStat[n]) printItem(n);
 n++;                                      //или то же самое в цикле for
 if(n > Size - 1)
 n = 0;
  delay(500);
}

Где у меня многомерные?))
ЗЫЖ в 49 это мой код… Только не нужно если что на аккаунты переключаться, захожу с разных устройств, поэтому так…

Возможно… , но какой?
С указателями? Но сам алгоритм правильный… За границы массива я не выхожу… Думаю спорить нет смысла…

Может быть, раз такое простое решение сделать через ж… рекурсию, да ещё и с явным выходом за границы массива… :wink:

Удаляюсь, чтобы не смущать своим присутствием.

Так то там локальный массив (одномерный!) передаётся в обе функции

Ай Ай Ай…))) Не хорошо…
Я критику уважаю, …но когда говорят, что я дурак, только потому что сделал лучше(надеюсь на это :slight_smile: ) и умывают руки… Не понимаю (
Ну и да ладно…

Как по мне здесь косяк ИМХО.
В функцию передаём параметром массив без размера.
Уже внутри функции выходим за границы, а там, как повезёт.
Это если я правильно понял недавно обсуждавшуюся тему

Массивы так и передаются… Указателями…
А что бы не выходить за границы туда же (в функции) передаются и их размеры… Хотя в моем случае можно и не передавать, а использовать напрямую константу ИТЕМ_КОУНТ

Нет, там немного о другом… Там о самих массивах, Ане об указателях на них…

Что такое массив? Это область памяти из эн байтов идущих подряд. Размерность указывается в объявлении массива. И умножает я на размер элемента массива… В байтах.
Что такое имя массива? Это указатель на первую ячкйку(байт) массива…
Так как я передаю в функцию указатель на массив с известной длинной, то я не выхожу за границы

Но ведь локально созданный массив не сохраняется с выходом из функции?

Впрочем, подожду, может кто-нибудь из опытных прокомментирует, тем более непонятно, зачем так усложнять