//importing libraries:
#include <LiquidCrystal.h>
#include <Keypad.h>
//Configuring the Button:
const int BUTTON = 2;
volatile boolean ON = false;
//Configuring the Buzzer:
const int BUZZER = 11;
//Configuring the LCD:
const int RS = 4;
const int E = 5;
const int D4 = 6;
const int D5 = 7;
const int D6 = 8;
const int D7 = 9;
const int A = 10;
LiquidCrystal lcd(RS, E, D4, D5, D6, D7);
//Configuring the joystick:
const int SEL = A0;
const int HORZ = A1;
const int VERT = A2;
//Configuring the keypad:
const int ROWS = 4;
const int COLS = 4;
char keys[ROWS][COLS] = {
{ '1', '2', '3', '+' },
{ '4', '5', '6', '-' },
{ '7', '8', '9', '*' },
{ ' ', '0', '=', '/' }
};
const byte rowPins[ROWS] = { 22, 24, 26, 28 }; // Pins connected to R1, R2, R3, R4
const byte colPins[COLS] = { 30, 32, 34, 36 }; // Pins connected to C1, C2, C3, C4
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
//Configuring the calculator:
byte arrowSymbol[8] = {
B00100,
B01110,
B10101,
B00100,
B00100,
B00100,
B00100,
B00100
};
String input1 = "";
String input2 = "";
char operation;
boolean isSecondNumber = false;
int mode;
boolean START = true;
boolean Begin = true;
// Spil indstillinger
const int MAX_LEVEL = 5; // Maximum niveau/levels i spillet
const int DISPLAY_TIME = 1000; // Tid i milisekunder som viser random tal sekvenserne
int sequence[MAX_LEVEL]; // Array til at gemme tal sekvenserne
int userInput[MAX_LEVEL]; // Array til at gemme brugeren/spiller input
int currentLevel = 1; // nuværende spil niveau/level
int cursorPosition = 0;
void setup() {
//alle pins er input pr default..
lcd.begin(16, 2);
pinMode(RS, OUTPUT);
pinMode(E, OUTPUT);
pinMode(D4, OUTPUT);
pinMode(D5, OUTPUT);
pinMode(D6, OUTPUT);
pinMode(D7, OUTPUT);
pinMode(A, OUTPUT);
pinMode(BUZZER, OUTPUT);
attachInterrupt(digitalPinToInterrupt(BUTTON), ONOFF, RISING);
lcd.createChar(0, arrowSymbol);
}
void ONOFF() {
static unsigned long last_interrupt_time = 0;
unsigned long interrupt_time = millis();
// If interrupts come faster than 200ms, assume it's a bounce and ignore
if (interrupt_time - last_interrupt_time > 200) {
ON = !ON;
if (ON) {
digitalWrite(BUZZER, HIGH);
digitalWrite(A, HIGH);
} else {
digitalWrite(BUZZER, LOW);
digitalWrite(A, LOW);
}
}
last_interrupt_time = interrupt_time;
}
void loop() {
//Serial.println(analogRead(SEL));
if (ON) {
lcd.display();
if (START) {
lcd.setCursor(0, 0);
lcd.print("Choose mode: ");
lcd.setCursor(0, 1);
lcd.print("1: Game; 2: Calc");
}
char key = keypad.getKey();
if (key && START) {
tone(BUZZER, 1000, 100);
if (key == '1') {
mode = 1;
START = false;
lcd.clear();
} else if (key == '2') {
mode = 2;
START = false;
lcd.clear();
}
}
if (mode == 1 && !START) {
if (Begin) {
randomSeed(analogRead(0)); // Initialisere random numre
lcd.print("Memory Game");
delay(2000);
lcd.clear();
Begin = false;
}
Game();
} else if (mode == 2 && !START) {
if (Begin) {
lcd.print("Calculator");
delay(2000);
lcd.clear();
Begin = false;
}
//delay(10);
Calculator();
}
} else {
Begin = true;
START = true;
lcd.noDisplay();
noTone(BUZZER);
lcd.clear();
}
}
boolean reset = false;
void Joystick() {
int horzValue = analogRead(HORZ); // Læser horisontale værdier/bevægelser
int vertValue = analogRead(VERT); // Læser vertikale værdier/bevægelser
// Cursor position på øverste række på LCD'en
// Horisontal bevægelser (venstre eller højre)
if (horzValue > 750) { // Joystick til højre
cursorPosition++;
lcd.setCursor(cursorPosition, 0);
delay(150);
if (cursorPosition > 15) { // begrænsning for cursoren så den ikke går ud er skærmens grænse til højre
cursorPosition = 15;
}
} else if (horzValue < 250) { // Joystick til venstre
cursorPosition--;
lcd.setCursor(cursorPosition, 0);
delay(150);
if (cursorPosition < 0) { // begrænsning for cursoren så den ikke går ud er skærmens grænse til venstre
cursorPosition = 0;
}
}
//Vertikal bevægelse (op eller ned, men vi begrænser den til øverste række)
if (vertValue > 750) { // Joystick skubbet op
lcd.setCursor(cursorPosition, 0); // fastholder cursoren til øverste række 0
} else if (vertValue < 250) { // Joystick skubbet ned
lcd.setCursor(cursorPosition, 0); // fastholder cursoren til øverste række 0
}
if (analogRead(SEL) == 0) {
resetCalculator();
}
}
String input = "";
char operation1;
void Calculator() {
Joystick();
lcd.setCursor(cursorPosition - 1, 1);
lcd.print(" ");
lcd.setCursor(cursorPosition + 1, 1);
lcd.print(" ");
lcd.setCursor(cursorPosition, 1);
lcd.write(byte(0));
lcd.setCursor(cursorPosition, 0);
char key = keypad.getKey();
if (key) {
tone(BUZZER, 1000, 100);
input += key;
cursorPosition++;
lcd.print(key);
if (key == ' ') {
input.remove(cursorPosition, 1);
}
if (key == '=') {
int operationIndex = -1;
for (int i = 0; i < input.length(); i++) {
char currentChar = input.charAt(i);
if (currentChar == '+' || currentChar == '-' || currentChar == '*' || currentChar == '/') {
operation = currentChar;
operationIndex = i;
break;
}
}
if (operationIndex != -1) {
String beforeOp = input.substring(0, operationIndex);
String afterOp = input.substring(operationIndex + 1);
double num1 = beforeOp.toDouble();
double num2 = afterOp.toDouble();
double result = 0;
switch (operation) {
case '+': result = num1 + num2; break;
case '-': result = num1 - num2; break;
case '*': result = num1 * num2; break;
case '/': result = num1 / num2; break;
}
lcd.setCursor(0, 1);
lcd.print("=");
lcd.print(result);
playSuccessTone();
delay(1000);
resetCalculator();
}
}
}
}
void playSuccessTone() {
tone(BUZZER, 523, 200);
delay(200);
tone(BUZZER, 659, 200);
delay(200);
tone(BUZZER, 784, 300);
delay(300);
noTone(BUZZER);
delay(3000);
}
void error() {
lcd.clear();
lcd.setCursor(5, 0);
lcd.print("ERROR!");
lcd.setCursor(5, 1);
lcd.print("ERROR!");
tone(BUZZER, 1000, 200);
delay(100);
tone(BUZZER, 600, 200);
delay(100);
tone(BUZZER, 400, 300);
delay(300);
noTone(BUZZER);
resetCalculator();
}
void resetCalculator() {
input1 = "";
input2 = "";
input = "";
operation1 = '\0';
isSecondNumber = false;
lcd.clear();
cursorPosition = 0;
}
void Game() {
if (ON) {
generateSequence(); // Generer random tal sekvens
displaySequence(); // viser tal sekvensen på skærmen
if (getUserInput()) { // modtager input fra brugeren og tjekker om det passer
currentLevel++; // går til næste niveau hvis niveauet er gennemført
if (currentLevel > MAX_LEVEL) { // checker hvis man har vundet
lcd.clear();
lcd.print("You Win!");
tone(BUZZER, 1000, 500); // afspiller you win lyden
delay(3000);
resetGame();
}
} else {
lcd.clear();
lcd.print("Game Over");
tone(BUZZER, 200, 1000); // afspiller lyd for gameover
delay(3000);
resetGame();
}
}
}
// funktionen generer random tal
void generateSequence() {
for (int i = 0; i < currentLevel; i++) {
sequence[i] = random(0, 10); // Generer et random til fra 0-9
}
}
// Funktionen viser display sekvensen
void displaySequence() {
lcd.clear();
lcd.print("Remember:");
delay(1000);
for (int i = 0; i < currentLevel; i++) {
lcd.clear();
lcd.print(sequence[i]);
tone(BUZZER, 500, 200); // laver lyd for hvert tast a keys
delay(DISPLAY_TIME);
lcd.clear();
delay(500); // delay mellem viste tal
}
}
// funktionen tjekker/validere input fra bruger/spiller
boolean getUserInput() {
lcd.clear();
lcd.print("Your Turn:");
int index = 0;
while (index < currentLevel) {
char key = keypad.getKey(); // Læs keypad input
if (key) { // tjek om en key er blevet trykket
if (key >= '0' && key <= '9') { // Validere numre input
tone(BUZZER, 1000, 100);
userInput[index] = key - '0'; // konverter char til int
lcd.setCursor(index, 1); // rykker cursor til input positionen
lcd.print(key); // viser key der er blevet trykket
index++;
}
}
}
delay(500);
// Validerer om inputtet er sandt
for (int i = 0; i < currentLevel; i++) {
if (userInput[i] != sequence[i]) {
return false; // Input er ikke sandt
}
}
return true; // Input er sandt
}
// Funktion til at genstarte spillet
void resetGame() {
currentLevel = 1;
lcd.clear();
lcd.print("Restarting...");
delay(2000);
lcd.clear();
}