Added puzzle color Remember
This commit is contained in:
parent
7ad21cd1d4
commit
f1f17cf754
5
terminal/puzzle_colorRemember/.gitignore
vendored
Normal file
5
terminal/puzzle_colorRemember/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
.pio
|
||||
.vscode/.browse.c_cpp.db*
|
||||
.vscode/c_cpp_properties.json
|
||||
.vscode/launch.json
|
||||
.vscode/ipch
|
||||
17
terminal/puzzle_colorRemember/platformio.ini
Normal file
17
terminal/puzzle_colorRemember/platformio.ini
Normal file
@ -0,0 +1,17 @@
|
||||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[env:nanoatmega328new]
|
||||
platform = atmelavr
|
||||
board = nanoatmega328new
|
||||
framework = arduino
|
||||
lib_deps =
|
||||
adafruit/Adafruit NeoPixel@^1.15.2
|
||||
robtillaart/PCF8575@^0.2.4
|
||||
327
terminal/puzzle_colorRemember/src/main.cpp
Normal file
327
terminal/puzzle_colorRemember/src/main.cpp
Normal file
@ -0,0 +1,327 @@
|
||||
|
||||
// ================== Projekt: Modul 2 ==================
|
||||
// SPIELMECHANIK – mit Gewinnanimation + Gewinnsignal
|
||||
//
|
||||
// Fix integriert:
|
||||
// - zeitbasierte Entprellung pro Taster
|
||||
// - verhindert Mehrfachregistrierung eines einzelnen Tastendrucks
|
||||
#include <Arduino.h>
|
||||
#include <Wire.h>
|
||||
#include <PCF8575.h>
|
||||
#include <Adafruit_NeoPixel.h>
|
||||
|
||||
// ------------------ Hardware ------------------
|
||||
|
||||
PCF8575 expander(0x20);
|
||||
|
||||
#define PIN_NEOPIXEL_BUTTONS 4
|
||||
#define NUM_NEOPIXEL_BUTTONS 18
|
||||
|
||||
#define PIN_NEOPIXEL_LOESUNG 6
|
||||
#define NUM_NEOPIXEL_LOESUNG 6
|
||||
|
||||
#define PIN_POWER_ON 13
|
||||
#define PIN_TRIGGER_SHUFFLE 2
|
||||
#define PIN_SEND_WIN 5
|
||||
|
||||
// ------------------ Timing ------------------
|
||||
|
||||
#define WIN_OFF_DELAY_MS 300
|
||||
#define WIN_STEP_DELAY_MS 60
|
||||
#define DEBOUNCE_TIME_MS 200 // <<< Entprellzeit
|
||||
|
||||
Adafruit_NeoPixel pixelsButtons(
|
||||
NUM_NEOPIXEL_BUTTONS,
|
||||
PIN_NEOPIXEL_BUTTONS,
|
||||
NEO_RGB + NEO_KHZ800
|
||||
);
|
||||
|
||||
Adafruit_NeoPixel pixelsSolution(
|
||||
NUM_NEOPIXEL_LOESUNG,
|
||||
PIN_NEOPIXEL_LOESUNG,
|
||||
NEO_RGB + NEO_KHZ800
|
||||
);
|
||||
|
||||
// ------------------ Mapping ------------------
|
||||
|
||||
enum ButtonSource { SRC_NANO, SRC_PCF8575 };
|
||||
|
||||
struct LedButtonMap {
|
||||
uint8_t ledIndex;
|
||||
ButtonSource source;
|
||||
uint8_t pin;
|
||||
};
|
||||
|
||||
const LedButtonMap ledButtonMap[18] = {
|
||||
{ 0, SRC_NANO, A0 }, { 1, SRC_NANO, A1 }, { 2, SRC_NANO, A2 }, { 3, SRC_NANO, A3 },
|
||||
{ 4, SRC_NANO, 7 }, { 5, SRC_NANO, 8 },
|
||||
{ 6, SRC_PCF8575, 0 }, { 7, SRC_PCF8575, 1 }, { 8, SRC_PCF8575, 2 }, { 9, SRC_PCF8575, 3 },
|
||||
{10, SRC_PCF8575, 4 }, {11, SRC_PCF8575, 5 }, {12, SRC_PCF8575, 6 }, {13, SRC_PCF8575, 7 },
|
||||
{14, SRC_PCF8575, 8 }, {15, SRC_PCF8575, 9 }, {16, SRC_PCF8575,10 }, {17, SRC_PCF8575,11 }
|
||||
};
|
||||
|
||||
// ------------------ Pride-Farben (dunkler) ------------------
|
||||
|
||||
const uint8_t prideColors[6][3] = {
|
||||
{25, 0, 0},
|
||||
{35, 10, 0},
|
||||
{25, 25, 0},
|
||||
{ 0, 25, 0},
|
||||
{ 0, 0, 25},
|
||||
{20, 0, 25}
|
||||
};
|
||||
|
||||
// ------------------ Spielzustände ------------------
|
||||
|
||||
uint8_t solutionOrder[6];
|
||||
uint8_t expectedOrder[6];
|
||||
int8_t buttonAssignment[18];
|
||||
bool winActive = false;
|
||||
bool powerOnState = true;
|
||||
|
||||
|
||||
bool lastPressed[18];
|
||||
unsigned long ledOffTime[18];
|
||||
unsigned long lastPressTime[18]; // <<< Entprellspeicher
|
||||
|
||||
uint8_t progressIndex = 0;
|
||||
bool lastTriggerState = LOW;
|
||||
|
||||
// ------------------ Hilfsfunktionen ------------------
|
||||
|
||||
bool readButton(uint8_t i) {
|
||||
if (ledButtonMap[i].source == SRC_NANO)
|
||||
return digitalRead(ledButtonMap[i].pin) == LOW;
|
||||
return expander.read(ledButtonMap[i].pin) == LOW;
|
||||
}
|
||||
|
||||
// ------------------ Neues Spiel ------------------
|
||||
|
||||
void generateNewGame() {
|
||||
|
||||
for (uint8_t i = 0; i < 6; i++) solutionOrder[i] = i;
|
||||
|
||||
for (int i = 5; i > 0; i--) {
|
||||
int j = random(i + 1);
|
||||
uint8_t t = solutionOrder[i];
|
||||
solutionOrder[i] = solutionOrder[j];
|
||||
solutionOrder[j] = t;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < 6; i++)
|
||||
expectedOrder[i] = solutionOrder[5 - i];
|
||||
|
||||
for (uint8_t i = 0; i < 6; i++) {
|
||||
uint8_t c = solutionOrder[i];
|
||||
pixelsSolution.setPixelColor(
|
||||
i,
|
||||
pixelsSolution.Color(
|
||||
prideColors[c][0],
|
||||
prideColors[c][1],
|
||||
prideColors[c][2]
|
||||
)
|
||||
);
|
||||
}
|
||||
pixelsSolution.show();
|
||||
|
||||
for (uint8_t i = 0; i < 18; i++) {
|
||||
buttonAssignment[i] = -1;
|
||||
pixelsButtons.setPixelColor(i, 0);
|
||||
ledOffTime[i] = 0;
|
||||
lastPressTime[i] = 0;
|
||||
}
|
||||
pixelsButtons.show();
|
||||
|
||||
uint8_t idx[18];
|
||||
for (uint8_t i = 0; i < 18; i++) idx[i] = i;
|
||||
|
||||
for (int i = 17; i > 0; i--) {
|
||||
int j = random(i + 1);
|
||||
uint8_t t = idx[i];
|
||||
idx[i] = idx[j];
|
||||
idx[j] = t;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < 6; i++)
|
||||
buttonAssignment[idx[i]] = solutionOrder[i];
|
||||
|
||||
progressIndex = 0;
|
||||
}
|
||||
|
||||
// ------------------ Gewinnanimation + Signal ------------------
|
||||
|
||||
void winAnimation() {
|
||||
|
||||
winActive = true;
|
||||
digitalWrite(PIN_SEND_WIN, HIGH);
|
||||
|
||||
// 1) letzte korrekte Farbe stehen lassen
|
||||
delay(500);
|
||||
|
||||
// 2) ALLES AUS (inkl. Off-Timer löschen)
|
||||
for (uint8_t i = 0; i < 18; i++)
|
||||
ledOffTime[i] = 0;
|
||||
|
||||
pixelsSolution.clear();
|
||||
pixelsButtons.clear();
|
||||
pixelsSolution.show();
|
||||
pixelsButtons.show();
|
||||
delay(WIN_OFF_DELAY_MS);
|
||||
|
||||
// 3) richtige Reihenfolge (umgekehrt), Lösung + Taster synchron
|
||||
for (int i = 5; i >= 0; i--) {
|
||||
|
||||
uint8_t color = solutionOrder[i];
|
||||
|
||||
// Lösungs-LED
|
||||
pixelsSolution.setPixelColor(
|
||||
i,
|
||||
pixelsSolution.Color(
|
||||
prideColors[color][0],
|
||||
prideColors[color][1],
|
||||
prideColors[color][2]
|
||||
)
|
||||
);
|
||||
|
||||
// zugehöriger Taster
|
||||
for (uint8_t b = 0; b < 18; b++) {
|
||||
if (buttonAssignment[b] == color) {
|
||||
pixelsButtons.setPixelColor(
|
||||
b,
|
||||
pixelsButtons.Color(
|
||||
prideColors[color][0],
|
||||
prideColors[color][1],
|
||||
prideColors[color][2]
|
||||
)
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pixelsSolution.show();
|
||||
pixelsButtons.show();
|
||||
delay(WIN_STEP_DELAY_MS);
|
||||
}
|
||||
|
||||
digitalWrite(PIN_SEND_WIN, LOW);
|
||||
winActive = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// ------------------ Setup ------------------
|
||||
|
||||
void setup() {
|
||||
randomSeed(analogRead(A0));
|
||||
|
||||
Wire.begin();
|
||||
expander.begin();
|
||||
|
||||
pinMode(PIN_TRIGGER_SHUFFLE, INPUT);
|
||||
pinMode(PIN_POWER_ON, INPUT);
|
||||
powerOnState = digitalRead(PIN_POWER_ON);
|
||||
pinMode(PIN_SEND_WIN, OUTPUT);
|
||||
digitalWrite(PIN_SEND_WIN, LOW);
|
||||
|
||||
pinMode(A0, INPUT_PULLUP);
|
||||
pinMode(A1, INPUT_PULLUP);
|
||||
pinMode(A2, INPUT_PULLUP);
|
||||
pinMode(A3, INPUT_PULLUP);
|
||||
pinMode(7, INPUT_PULLUP);
|
||||
pinMode(8, INPUT_PULLUP);
|
||||
|
||||
for (uint8_t i = 0; i < 12; i++)
|
||||
expander.write(i, HIGH);
|
||||
|
||||
pixelsButtons.begin();
|
||||
pixelsSolution.begin();
|
||||
|
||||
generateNewGame();
|
||||
|
||||
for (uint8_t i = 0; i < 18; i++)
|
||||
lastPressed[i] = false;
|
||||
}
|
||||
|
||||
// ------------------ Loop ------------------
|
||||
|
||||
void loop() {
|
||||
if (powerOnState && digitalRead(PIN_POWER_ON) == LOW)
|
||||
{
|
||||
powerOnState = false;
|
||||
pixelsSolution.begin();
|
||||
for (size_t i = 0; i < 6; i++)
|
||||
{
|
||||
pixelsSolution.setPixelColor(i, pixelsSolution.Color(0, 0, 0, 0));
|
||||
}
|
||||
pixelsSolution.show();
|
||||
pixelsButtons.begin();
|
||||
for (size_t i = 0; i < 18; i++)
|
||||
{
|
||||
pixelsButtons.setPixelColor(i, pixelsButtons.Color(0, 0, 0, 0));
|
||||
}
|
||||
pixelsButtons.show();
|
||||
|
||||
}
|
||||
// Detecting turn-on
|
||||
if (!powerOnState && digitalRead(PIN_POWER_ON) == HIGH)
|
||||
{
|
||||
generateNewGame();
|
||||
powerOnState = true;
|
||||
}
|
||||
if (!powerOnState)
|
||||
{
|
||||
// We are turned-off and stop anything after here
|
||||
return;
|
||||
}
|
||||
unsigned long now = millis();
|
||||
|
||||
bool trigger = digitalRead(PIN_TRIGGER_SHUFFLE);
|
||||
if (trigger && !lastTriggerState) {
|
||||
generateNewGame();
|
||||
}
|
||||
lastTriggerState = trigger;
|
||||
|
||||
for (uint8_t i = 0; i < 18; i++) {
|
||||
bool pressed = readButton(i);
|
||||
|
||||
if (pressed && !lastPressed[i] &&
|
||||
(now - lastPressTime[i] > DEBOUNCE_TIME_MS)) {
|
||||
|
||||
lastPressTime[i] = now;
|
||||
int8_t color = buttonAssignment[i];
|
||||
|
||||
if (color >= 0) {
|
||||
pixelsButtons.setPixelColor(
|
||||
i,
|
||||
pixelsButtons.Color(
|
||||
prideColors[color][0],
|
||||
prideColors[color][1],
|
||||
prideColors[color][2]
|
||||
)
|
||||
);
|
||||
pixelsButtons.show();
|
||||
ledOffTime[i] = now + 1000;
|
||||
}
|
||||
|
||||
if (color < 0 || color != expectedOrder[progressIndex]) {
|
||||
progressIndex = 0;
|
||||
} else {
|
||||
progressIndex++;
|
||||
if (progressIndex == 6) {
|
||||
winAnimation();
|
||||
progressIndex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!winActive && ledOffTime[i] && now >= ledOffTime[i]) {
|
||||
|
||||
pixelsButtons.setPixelColor(i, 0);
|
||||
pixelsButtons.show();
|
||||
ledOffTime[i] = 0;
|
||||
}
|
||||
|
||||
lastPressed[i] = pressed;
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user