Sélectionner un éléments aléatoirement dans un tableau

Bonjour,
Je suis débutant sur arduino et c'est mon tout premier projet. :cold_sweat:
Je dois donc créer une interface sur un écran lcd affichant une question et 4 propositions.

J'aimerais alors pouvoir sélectionner et afficher une question aléatoirement parmi plusieurs contenu dans un tableau et vérifier que cette question n'a pas déjà été sectionner. (Je ne sais pas du tout si c'est la meilleur façon de faire)

J'aurais besoin de votre aide je ne sais pas du tout comment m'y prendre. :frowning:
Merci beaucoup

ICI : random() - Arduino Reference

Je suppose que tu sais qu’un index de tableau commence à zéro ?

Oui et voilà justement voilà ce que j'ai fait mais les valeurs retourner sont des chiffre et non pas des chaînes de caractères... Je ne vois pas où est le problème...

int Tab[]={"test1","test2","test3","test4"};
int Alea;
void setup() {
  Serial.begin(9600);
}
void loop() {
  Alea=random(0,4);
  Serial.println(Tab[Alea]);
  delay(500);
}

Merci de votre aide.

JE suis allé demander à Google "arduino reference random" qui m'a renvoyé sagement vers https://www.arduino.cc/reference/en/language/functions/random-numbers/random/:
déjà, vous pouvez sélectionner une question parmi N -je suppose qu'elles sont fixes- par:
questions[random(0, N-1)];

une solution, pour tenir compte que vous ne voulez pas répéter les question, est de permuter la question tirée au sort avec la dernière, et de décréter que vous n'aurez plus que N-1 questions disponibles;
une autre solution évite des permutations, et consiste à marquer comme "précédemment posée" (un tableau auxilliaire de booleans) les questions précédemment posée, et à tirer au sort jusqu'à ce que la question soit ... une nouvelle question (faire attention à ne pas boucler si toutes les questions ont déjà été posées)

int Tab={“test1”,“test2”,“test3”,“test4”};

deviendrait char Tab[6]={“test1”,“test2”,“test3”,“test4”};

6 : pour tenir compte que vos chaînes se terminent par zero.

dbrion06:
int Tab={"test1","test2","test3","test4"};

deviendrait char Tab[6]={"test1","test2","test3","test4"};

6 : pour tenir compte que vos chaînes se terminent par zero.

Tout à fait, ou pour faire plus simple et économiser de la mémoire car à mon avis toutes les chaines n'auront pas la même longueur

const char* Tab[] = {"test1","test2","test3","test4"};

concernant random(0, N-1) attention car la fonction random(min, max) ne retourne jamais la valeur max, donc si on veut pouvoir avoir la dernière entrée du tableau, il faut faire un random(0, N) si N est le nombre d'éléments du tableau de questions

@Yan_azer lisez les règles du forum et corrigez votre post ci dessus et rajoutez les code tags autour du code:
[code]`` [color=blue]// votre code ici[/color] ``[/code].

ça doit ressembler à cela:// votre code ici
(faites aussi ctrl-T (PC) or cmd-T (Mac) dans l'IDE avant de copier le code pour qu'il soit indenté correctement)

Merci beaucoup pour votre aide ! :smiley:

@JML merci beaucoup (j'hesitais -et n'avais pas la doc sous les yeux, qui était dépourvue d'ambiguité pour la borne max).

on peut ensuite s’amuser à faire un mélange aléatoire des entrées du tableau pour que les questions sortent dans un ordre différent à chaque fois

const char* tab[] = {"test1", "test2", "test3", "test4"};
const byte N = sizeof(tab) / sizeof(tab[0]);

void melange()
{
  for (byte i = 0; i < N - 1; i++) {
    byte j = random(i, N);
    const char* echange = tab[i];
    tab[i] = tab[j];
    tab[j] = echange;
  }
  for (byte i = 0; i < N; i++)  Serial.println(tab[i]);
}

void setup() {
  Serial.begin(115200);
  randomSeed(analogRead(A0));
}

void loop() {
  Serial.println(F("-----------"));
  melange();
  delay(1000);
}

Moi, grand je joue aux cartes, avant de distribuer je mélange le paquet.

On peut faire pareil ici : pour mélanger quatre valeurs, il suffit d'en échanger deux au hasard et de répéter ça plusieurs fois, disons dix.
Ensuite, on lit le tableau dans l'ordre

Damned, grillé par J-M-L

:smiley: :disappointed_relieved: :cold_sweat:

Le problème que je vois, c'est que, pour chaque question, il y a 4 reponses possibles, si bien que le tableau de pointeurs vers des chaines terminées par 0 n'est pas la structure intermédiaire (je suppose que les 4 réponses possibles sont spécifiques à une question..)
en fait, une question est 5 pointeurs vers des chaines (la question, l'indication 1, ....4))?
du genre
const char* Tab = {"test1","test2","test3","test4"};
devient
const char Tab[5][6] = {{"test1", "v01", "v02","v03","v05"},
{"test2","r11", "r12","r13","r15"},
{"test3","v01", "v02","v03","v05"},
{"test4","v01", "v02","v03","v05"}};

@J-M-L : Ce que je propose est légèrement différent : avec ton algorithme, si le générateur de nombres aléatoires fournit la suite 2 1 4 3 le tableau sera inchangé. D'autres cas similaires donnent le même résultat.

lesept:
@J-M-L : Ce que je propose est légèrement différent : avec ton algorithme, si le générateur de nombres aléatoires fournit la suite 2 1 4 3 le tableau sera inchangé. D'autres cas similaires donnent le même résultat.

Non parce que vous ne pouvez pas échanger avec un élément déjà échangé (random commence à i)

dbrion06:
Le problème que je vois, c'est que, pour chaque question, il y a 4 reponses possibles, si bien que le tableau de pointeurs vers des chaines terminées par 0 n'est pas la structure intermédiaire (je suppose que les 4 réponses possibles sont spécifiques à une question..)
en fait, une question est 5 pointeurs vers des chaines (la question, l'indication 1, ....4))?

oui on peut mettre une structure à la place de chaîne bien entendu

J-M-L:
random commence à i

Juste, je n'avais pas vu cette subtilité... Merci

Ça explique le N-1 de la boucle.

je me suis amusé à faire un mélange des questions d’un QCM avec une structure qui contient une référence à la bonne réponse, bien sûr quand on échange des réponses, il faut échanger aussi l’index de la bonne réponse. on peut suivre cela sur la console série

const byte nbReponses = 4;

struct QCM_t {
  const char* question;
  byte bonneReponse;
  const char* reponses[nbReponses];
};

// les QCM:
QCM_t Q1 = {"Question 1", 0, {"Reponse 1-1 OK", "Reponse 1-2", "Reponse 1-3", "Reponse 1-4"}};
QCM_t Q2 = {"Question 2", 1, {"Reponse 2-1", "Reponse 2-2 OK", "Reponse 2-3", "Reponse 2-4"}};
QCM_t Q3 = {"Question 3", 2, {"Reponse 3-1", "Reponse 3-2", "Reponse 3-3 OK", "Reponse 3-4"}};
QCM_t Q4 = {"Question 4", 3, {"Reponse 4-1", "Reponse 4-2", "Reponse 4-3", "Reponse 4-4 OK"}};


// le tableau des QCM
QCM_t* QCM[] = {&Q1, &Q2, &Q3, &Q4 };
const byte N = sizeof(QCM) / sizeof(QCM[0]); // le nombre de questions dans le QCM

// on secoue le tout
void melangeQCM()
{
  // on mélange les questions
  for (byte i = 0; i < N - 1; i++) {
    byte j = random(i, N);
    QCM_t* echange = QCM[i];
    QCM[i] = QCM[j];
    QCM[j] = echange;
  }

  // on mélange les réponses pour l'entrée QCM[i]
  for (byte i = 0; i < N; i++) {
    for (byte r = 0; r < nbReponses - 1; r++) {
      byte k = random(r, nbReponses);
      const char* permute = QCM[i]->reponses[r];
      QCM[i]->reponses[r] = QCM[i]->reponses[k];
      QCM[i]->reponses[k] = permute;
      // si on a déplacé la bonne réponse on échange
      if (QCM[i]->bonneReponse == k) QCM[i]->bonneReponse = r;
      else if (QCM[i]->bonneReponse == r) QCM[i]->bonneReponse = k;
    }
  }
}

void imprimeQCM()
{
  // on imprime le QCM
  for (byte i = 0; i < N; i++)  {
    Serial.print(i + 1);
    Serial.print(F(" : "));
    Serial.println(QCM[i]->question);
    for (byte r = 0; r < nbReponses; r++) {
      Serial.print(F("\t"));
      Serial.print(r + 1);
      Serial.print(F(" : "));
      Serial.print(QCM[i]->reponses[r]);
      if (r == QCM[i]->bonneReponse) Serial.print(F("\t<<== OK"));
      Serial.println();
    }
  }
}


void setup()
{
  Serial.begin(115200);
  randomSeed(analogRead(A0));
  Serial.println(F("----- LE QCM SANS MODIFICATION ------"));
  imprimeQCM();
}

void loop()
{
  Serial.println(F("-----------"));
  melangeQCM();
  imprimeQCM();
  delay(5000);
}
[color=blue]
[color=green]----- LE QCM SANS MODIFICATION ------
1 : Question 1
	1 : Reponse 1-1 OK	<<== OK
	2 : Reponse 1-2
	3 : Reponse 1-3
	4 : Reponse 1-4
2 : Question 2
	1 : Reponse 2-1
	2 : Reponse 2-2 OK	<<== OK
	3 : Reponse 2-3
	4 : Reponse 2-4
3 : Question 3
	1 : Reponse 3-1
	2 : Reponse 3-2
	3 : Reponse 3-3 OK	<<== OK
	4 : Reponse 3-4
4 : Question 4
	1 : Reponse 4-1
	2 : Reponse 4-2
	3 : Reponse 4-3
	4 : Reponse 4-4 OK	<<== OK[/color]
-----------
1 : Question 1
	1 : Reponse 1-2
	2 : Reponse 1-1 OK[color=red]	<<== OK[/color]
	3 : Reponse 1-3
	4 : Reponse 1-4
2 : Question 4
	1 : Reponse 4-3
	2 : Reponse 4-4 OK[color=red]	<<== OK[/color]
	3 : Reponse 4-2
	4 : Reponse 4-1
3 : Question 2
	1 : Reponse 2-3
	2 : Reponse 2-4
	3 : Reponse 2-2 OK[color=red]	<<== OK[/color]
	4 : Reponse 2-1
4 : Question 3
	1 : Reponse 3-2
	2 : Reponse 3-4
	3 : Reponse 3-1
	4 : Reponse 3-3 OK[color=red]	<<== OK[/color]
-----------
1 : Question 4
	1 : Reponse 4-1
	2 : Reponse 4-2
	3 : Reponse 4-3
	4 : Reponse 4-4 OK[color=red]	<<== OK[/color]
2 : Question 3
	1 : Reponse 3-3 OK[color=red]	<<== OK[/color]
	2 : Reponse 3-1
	3 : Reponse 3-4
	4 : Reponse 3-2
3 : Question 1
	1 : Reponse 1-4
	2 : Reponse 1-2
	3 : Reponse 1-3
	4 : Reponse 1-1 OK[color=red]	<<== OK[/color]
4 : Question 2
	1 : Reponse 2-2 OK[color=red]	<<== OK[/color]
	2 : Reponse 2-3
	3 : Reponse 2-1
	4 : Reponse 2-4

[/color]

On voit bien que le bon N° de réponse suit dans les mélanges

:slight_smile:

Bonjour,
Désolé de ne répondre que maintenant, mais j'aurais encore quelques questions. :cold_sweat:

Après quelques recherches, je crois avoir compris que vous avez créer une "structure" pour lier les questions et les réponses, mais je ne comprends malheureusement pas vraiment comment cela fonctionne (comment on accède à un élément, l'affiche, le déplace, etc...)

De plus, @J-M-L j'ai essayé d’exécuter votre code pour mélanger le QCM pour l’adapter à ma situation mais ma console ne m'affiche que des caractère comme : ".@)?+*?!" savez-vous pourquoi ?

Merci encore pour votre aide :smiley:

Faut lire un tuto sur le langage C —> open classrooms à cela en stock pour vous

Pour l’affichage sans doute que vous n’avez pas mis votre console à 115200 bauds

D'accord merci beaucoup je vais regarder ça !