#include <Wire.h>
#include <hd44780.h> // main hd44780 header
#include <hd44780ioClass/hd44780_I2Cexp.h> // i2c expander i/o class header
#include <OneButton.h>
// CHANGER ICI LE NOMBRE DE QUESTIONS DANS UNE PARTIE
constexpr uint8_t nombreDeQuestions = 5;
hd44780_I2Cexp lcd;
const int LCD_COLS = 20;
const int LCD_ROWS = 4;
const byte pinLedVerte = 3;
const byte pinBuzzer = 9;
OneButton boutonJouer(2);
OneButton boutonJoueur1(12);
OneButton boutonJoueur2(11);
unsigned long scoreJ1, scoreJ2;
bool scoreJ1Fait, scoreJ2Fait;
enum : uint8_t {DEBUT, QUESTION, DECOMPTE, ATTENTE, FIN} etat = DEBUT;
struct Departement {
const char indicatif[4];
const char nom[30];
};
static const Departement lesDepartements[] PROGMEM = {
{"1", "Ain"},
{"2", "Aisne"},
{"3", "Allier"},
{"4", "Alpes-de-Haute-Provence"},
{"5", "Hautes-Alpes"},
{"6", "Alpes-Maritimes"},
{"7", "Ardeche"},
{"8", "Ardennes"},
{"9", "Ariege"},
{"10", "Aube"},
{"11", "Aude"},
{"12", "Aveyron"},
{"13", "Bouches-du-Rhone"},
{"14", "Calvados"},
{"15", "Cantal"},
{"16", "Charente"},
{"17", "Charente-Maritime"},
{"18", "Cher"},
{"19", "Correze"},
{"2A", "Corse-du-Sud"},
{"2B", "Haute-Corse"},
{"21", "Cote-d'Or"},
{"22", "Cotes-d'Armor"},
{"23", "Creuse"},
{"24", "Dordogne"},
{"25", "Doubs"},
{"26", "Drome"},
{"27", "Eure"},
{"28", "Eure-et-Loir"},
{"29", "Finistere"},
{"30", "Gard"},
{"31", "Haute-Garonne"},
{"32", "Gers"},
{"33", "Gironde"},
{"34", "Herault"},
{"35", "Ille-et-Vilaine"},
{"36", "Indre"},
{"37", "Indre-et-Loire"},
{"38", "Isere"},
{"39", "Jura"},
{"40", "Landes"},
{"41", "Loir-et-Cher"},
{"42", "Loire"},
{"43", "Haute-Loire"},
{"44", "Loire-Atlantique"},
{"45", "Loiret"},
{"46", "Lot"},
{"47", "Lot-et-Garonne"},
{"48", "Lozere"},
{"49", "Maine-et-Loire"},
{"50", "Manche"},
{"51", "Marne"},
{"52", "Haute-Marne"},
{"53", "Mayenne"},
{"54", "Meurthe-et-Moselle"},
{"55", "Meuse"},
{"56", "Morbihan"},
{"57", "Moselle"},
{"58", "Nievre"},
{"59", "Nord"},
{"60", "Oise"},
{"61", "Orne"},
{"62", "Pas-de-Calais"},
{"63", "Puy-de-Dome"},
{"64", "Pyrenees-Atlantiques"},
{"65", "Hautes-Pyrenees"},
{"66", "Pyrenees-Orientales"},
{"67", "Bas-Rhin"},
{"68", "Haut-Rhin"},
{"69", "Rhone"},
{"70", "Haute-Saone"},
{"71", "Saone-et-Loire"},
{"72", "Sarthe"},
{"73", "Savoie"},
{"74", "Haute-Savoie"},
{"75", "Paris"},
{"76", "Seine-Maritime"},
{"77", "Seine-et-Marne"},
{"78", "Yvelines"},
{"79", "Deux-Sevres"},
{"80", "Somme"},
{"81", "Tarn"},
{"82", "Tarn-et-Garonne"},
{"83", "Var"},
{"84", "Vaucluse"},
{"85", "Vendee"},
{"86", "Vienne"},
{"87", "Haute-Vienne"},
{"88", "Vosges"},
{"89", "Yonne"},
{"90", "Territoire de Belfort"},
{"91", "Essonne"},
{"92", "Hauts-de-Seine"},
{"93", "Seine-Saint-Denis"},
{"94", "Val-de-Marne"},
{"95", "Val-d'Oise"},
{"971", "Guadeloupe"},
{"972", "Martinique"},
{"973", "Guyane"},
{"974", "La Reunion"},
{"975", "Mayotte"},
};
constexpr size_t nbDepartements = sizeof lesDepartements / sizeof * lesDepartements;
uint8_t ordreInterrogation[nbDepartements];
size_t indiceInterrogation;
unsigned long chrono, decompte;
const unsigned long dureeAttente = 3000;
void configurationInitiale() {
etat = DEBUT;
digitalWrite(pinLedVerte, HIGH);
lcd.clear();
lcd.print(F("--- DEPARTEMENTS ---"));
lcd.setCursor(0, 1); lcd.print(F("appuyer sur le"));
lcd.setCursor(5, 2); lcd.print(F("bouton vert"));
lcd.setCursor(10, 3); lcd.print(F("pour JOUER"));
}
void preparerJeu() {
lcd.clear();
lcd.setCursor(0, 3); lcd.print(F("J1: 000"));
lcd.setCursor(13, 3); lcd.print(F("J2: 000"));
// on initialise dans l'ordre
for (size_t i = 0; i < nbDepartements; i++) ordreInterrogation[i] = i;
// on fait un mélange des éléments (algo de Fisher-Yates)
for (size_t i = nbDepartements - 1; i > 0; --i) {
size_t r = random(0, i + 1);
uint8_t tmpSwap = ordreInterrogation[i];
ordreInterrogation[i] = ordreInterrogation[r];
ordreInterrogation[r] = tmpSwap;
}
scoreJ1 = scoreJ2 = 0;
indiceInterrogation = 0;
digitalWrite(pinLedVerte, LOW);
etat = QUESTION;
}
void afficherScore() {
char buf[10];
snprintf(buf, sizeof buf, "%03lu", scoreJ1);
lcd.setCursor(4, 3); lcd.print(buf);
snprintf(buf, sizeof buf, "%03lu", scoreJ2);
lcd.setCursor(17, 3); lcd.print(buf);
}
void debut() {
switch (etat) {
case DEBUT: preparerJeu(); break;
case ATTENTE:
digitalWrite(pinLedVerte, LOW);
scoreJ1Fait = false;
scoreJ2Fait = false;
if (++indiceInterrogation >= nombreDeQuestions)
etat = FIN;
else
etat = QUESTION;
break;
default: break;
}
}
void scoreJoueur1() {
if (!scoreJ1Fait && etat == ATTENTE) {
scoreJ1Fait = true;
scoreJ1++;
afficherScore();
}
}
void scoreJoueur2() {
if (!scoreJ2Fait && etat == ATTENTE) {
scoreJ2Fait = true;
scoreJ2++;
afficherScore();
}
}
void setup() {
pinMode(pinLedVerte, OUTPUT);
pinMode(pinBuzzer, OUTPUT);
randomSeed(analogRead(A0));
boutonJouer.attachClick(debut);
boutonJoueur1.attachClick(scoreJoueur1);
boutonJoueur2.attachClick(scoreJoueur2);
Serial.begin(115200); Serial.println();
int result = lcd.begin(LCD_COLS, LCD_ROWS);
if (result) {
Serial.print("LCD initialization failed: ");
Serial.println(result);
hd44780::fatalError(result);
}
lcd.print(F("--- DEPARTEMENTS ---"));
configurationInitiale();
}
void loop() {
boutonJouer.tick();
boutonJoueur1.tick();
boutonJoueur2.tick();
switch (etat) {
case DEBUT: // on attend l'appui du bouton vert
break;
case QUESTION:
lcd.setCursor(0, 0); for (uint8_t i = 0; i < LCD_COLS; i++) lcd.write(' '); // on efface la ligne de question
lcd.setCursor(0, 1); for (uint8_t i = 0; i < LCD_COLS; i++) lcd.write(' '); // on efface la ligne de réponse
lcd.setCursor(0, 2); for (uint8_t i = 0; i < LCD_COLS; i++) lcd.write(' '); // on efface la ligne de réponse
lcd.setCursor(0, 0); lcd.print(F("Dept "));
lcd.print((const __FlashStringHelper*) lesDepartements[ordreInterrogation[indiceInterrogation]].indicatif);
lcd.print(F(" ?"));
decompte = chrono = millis();
etat = DECOMPTE;
break;
case DECOMPTE:
if (millis() - decompte >= 100) {
char buf[10];
snprintf(buf, sizeof buf, "%4lu", (dureeAttente - (millis() - chrono)));
lcd.setCursor(16, 0); lcd.print(buf);
decompte = millis();
tone(pinBuzzer, (dureeAttente - (millis() - chrono)), 15);
}
if (millis() - chrono >= dureeAttente) { // temps écoulé
tone(pinBuzzer, 2000, 50); delay(60);
tone(pinBuzzer, 3000, 50);
char buf[LCD_COLS + 1];
snprintf(buf, sizeof buf, "(%03u/%03u)", indiceInterrogation + 1, nombreDeQuestions );
lcd.setCursor(11, 0); lcd.print(buf); // on efface le décompte
strncpy_P(buf, lesDepartements[ordreInterrogation[indiceInterrogation]].nom, LCD_COLS );
buf[LCD_COLS] = '\0';
lcd.setCursor(0, 1); lcd.print(buf); // affichage tronqué éventuellement...
digitalWrite(pinLedVerte, HIGH);
etat = ATTENTE;
}
break;
case ATTENTE: // on attend l'appui du bouton vert
break;
case FIN: // le jeu est fini
lcd.clear();
lcd.setCursor(0, 3); lcd.print(F("J1: 000"));
lcd.setCursor(13, 3); lcd.print(F("J2: 000"));
if (scoreJ1 > scoreJ2) {
lcd.print(F("Joueur 1 VAINQUEUR"));
} else if (scoreJ1 < scoreJ2) {
lcd.print(F("Joueur 2 VAINQUEUR"));
} else {
lcd.print(F("JOUEURS EX AEQUO"));
}
afficherScore();
etat = DEBUT;
digitalWrite(pinLedVerte, HIGH);
break;
}
}JOUER
SCORE J1
SCORE J2