#include <fstream>
#include <iostream>
#include <array>
#include "utils.h"
#define MIN_VALUE 1
#define MAX_VALUE 10
#define MAX_TRIES 3
#define QUESTIONS 10
#define PENALTY_POINTS 3
#define POINTS_PER_ANSWER 10
using namespace std;
const char* format[] = {
"? x %d = %d",
"%d x ? = %d",
"%d x %d = ?",
"? x ? = %d"
};
int next() {
return MIN_VALUE + rand() % (MAX_VALUE - MIN_VALUE + 1);
}
array<int, 3> getEquation() {
int a = next(), b = next();
return {a, b, a * b};
}
int getCode(array<int, 3> equation) {
return stoi(
to_string(equation[0]) +
to_string(equation[1]) +
to_string(equation[2])
);
}
// TODO: ESP32 Wroom Sound Implementation
int buzzer(int attempts) {
cout << "BUZZER: " << MAX_TRIES - attempts << " attempts remaining" << endl;
return PENALTY_POINTS;
}
// g++ main.cpp -o main; ./main
int main() {
// Initialize memory and variables scoping
int memory[QUESTIONS];
fill(memory, memory + QUESTIONS, -1);
srand(time(NULL));
int input, counter = 0, currentPoints = 0;
// Solve as many questions as defined
while (counter < QUESTIONS) {
// Generate equation and "hash"
array<int, 3> nums = getEquation();
memory[counter] = getCode(nums);
int option = rand() % 4;
// Allow different formats for the same equation
memory[counter] *= 10;
memory[counter] += option;
// Overwrite duplicate equation code
while (hasDuplicates(memory)) {
nums = getEquation();
memory[counter] = getCode(nums);
memory[counter] *= 10;
memory[counter] += option;
}
// printArray(memory);
int points = POINTS_PER_ANSWER, attempts = 0;
// One free variable
if (option < 3) {
int expected = nums[option];
// Shift values to format
for (int i = option; i < 2; i++) {
nums[i] = nums[i + 1];
}
do {
printf(format[option], nums[0], nums[1]);
cout << endl << "? = ";
cin >> input;
if (input == expected) { // User solved the equation
cout << "OK" << endl;
counter++;
currentPoints += points;
cout << "Points: " << currentPoints << endl;
break;
} else { // User failed
points -= buzzer(++attempts);
}
} while (attempts < MAX_TRIES);
// Two free variables
} else {
do {
printf(format[option], nums[2]);
cout << endl << "? = ";
cin >> input;
// The equation code is ignored, the user "redefines" it
if (nums[2] % input == 0 && input <= MAX_VALUE) {
int expected = nums[2] / input;
memory[counter] = stoi(
to_string(input) + to_string(expected) +
to_string(nums[2]) + to_string(option)
);
cout << "? = ";
cin >> input;
if (input == expected) {
cout << "OK" << endl;
counter++;
currentPoints += points;
cout << "Points: " << currentPoints << endl;
break;
} else {
points -= buzzer(++attempts);
}
} else {
points -= buzzer(++attempts);
}
} while (attempts < MAX_TRIES);
}
}
return 0;
}