#include <LiquidCrystal_I2C.h>
// Pin definitions
#define BTN_1_PIN 2
#define BTN_2_PIN 3
#define BTN_3_PIN 4
#define BTN_4_PIN 5
#define BTN_ENTER_PIN A0
#define LED_R1_PIN 13
#define LED_B1_PIN 12
#define LED_R2_PIN 11
#define LED_B2_PIN 10
#define LED_R3_PIN 9
#define LED_B3_PIN 8
#define LED_R4_PIN 7
#define LED_B4_PIN 6
LiquidCrystal_I2C lcd(0x27,16,2);
// Game variables
char guess[5] = "0000";
char* history[] = {
"3222"
};
int history_index = 0;
int current_digit = 0;
bool game_over = false;
// Function declarations
void setup();
void loop();
void generate_code(bool repeat, int length, char* code);
void get_score(const char* secret, const char* guess, int* peg_a, int* peg_b);
void turn_off_leds();
void render_leds(int peg_a, int peg_b);
void render_history(const char* secret, char** history, int entry);
void play_game(const char* secret);
void update_display();
void setup() {
Serial.begin(9600);
// Initialize LCD
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Welcome to MasterMind");
lcd.setCursor(0, 1);
lcd.print("Your goal is to guess my secret combination.");
delay(2000);
// Initialize pins
pinMode(BTN_1_PIN, INPUT_PULLUP);
pinMode(BTN_2_PIN, INPUT_PULLUP);
pinMode(BTN_3_PIN, INPUT_PULLUP);
pinMode(BTN_4_PIN, INPUT);
pinMode(BTN_ENTER_PIN, INPUT);
pinMode(LED_R1_PIN, OUTPUT);
pinMode(LED_B1_PIN, OUTPUT);
pinMode(LED_R2_PIN, OUTPUT);
pinMode(LED_B2_PIN, OUTPUT);
pinMode(LED_R3_PIN, OUTPUT);
pinMode(LED_B3_PIN, OUTPUT);
pinMode(LED_R4_PIN, OUTPUT);
pinMode(LED_B4_PIN, OUTPUT);
turn_off_leds();
// Generate secret code
char* code = NULL;
code = generate_code(true, 8);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("I am thinking a number: ");
lcd.setCursor(0, 1);
// Start the game
play_game(code);
}
void turn_off_leds() {
digitalWrite(LED_R1_PIN, LOW);
digitalWrite(LED_B1_PIN, LOW);
digitalWrite(LED_R2_PIN, LOW);
digitalWrite(LED_B2_PIN, LOW);
digitalWrite(LED_R3_PIN, LOW);
digitalWrite(LED_B3_PIN, LOW);
digitalWrite(LED_R4_PIN, LOW);
digitalWrite(LED_B4_PIN, LOW);
}
void render_leds(int peg_a, int peg_b){
turn_off_leds();
int red_leds[] = {LED_R1_PIN, LED_R2_PIN, LED_R3_PIN, LED_R4_PIN};
int blue_leds[] = {LED_B1_PIN, LED_B2_PIN, LED_B3_PIN, LED_B4_PIN};
for (int i = 0; i < peg_a; i++){
digitalWrite(red_leds[i], HIGH);
}
for (int i = 0; i < peg_b; i++){
digitalWrite(blue_leds[i], HIGH);
}
}
void get_score(const char* secret, const char* guess, int* peg_a, int* peg_b){
*peg_a = 0;
*peg_b = 0;
for (int i = 0; i < 4; i++){
if (secret[i] == guess[i]){
(*peg_a)++;
}
else{
for (int j = 0; j < 4; j++){
if (secret[i] == guess[j]){
(*peg_b)++;
break;
}
}
}
}
}
void play_game(const char* secret){
while (game_over == false){
update_display();
while (digitalRead(BTN_1_PIN) == HIGH && digitalRead(BTN_2_PIN) == HIGH && digitalRead(BTN_3_PIN) == HIGH && digitalRead(BTN_4_PIN) == HIGH && digitalRead(BTN_ENTER_PIN) == HIGH){
// Wait for any button to be pressed
}
if (digitalRead(BTN_1_PIN) == LOW){
guess[current_digit] = (guess[current_digit] - '0' + 1) % 10 + '0';
}
if (digitalRead(BTN_2_PIN) == LOW){
guess[current_digit] = (guess[current_digit] - '0' + 9) % 10 + '0';
}
if (digitalRead(BTN_3_PIN) == LOW){
current_digit = (current_digit + 1) % 4;
}
if (digitalRead(BTN_4_PIN) == LOW){
current_digit = (current_digit + 3) % 4;
}
if (digitalRead(BTN_ENTER_PIN) == LOW){
int peg_a, peg_b;
get_score(secret, guess, &peg_a, &peg_b);
render_leds(peg_a, peg_b);
for (int i = 0; i < 4; i++){
history[history_index][i] = guess[i];
}
history[history_index][4] = '\0';
history_index++;
if (peg_a == 4){
game_over = true;
lcd.clear();
render_history(secret, history, history_index);
lcd.setCursor(0, 1);
lcd.print("Well done! You win in ");
lcd.print(history_index);
lcd.print(" guesses!");
while (digitalRead(BTN_1_PIN) == HIGH && digitalRead(BTN_2_PIN) == HIGH && digitalRead(BTN_3_PIN) == HIGH && digitalRead(BTN_4_PIN) == HIGH && digitalRead(BTN_ENTER_PIN) == HIGH){
// Wait for any button to be pressed
}
game_over = false;
history_index = 0;
turn_off_leds();
current_digit = 0;
for (int i = 0; i < 4; i++){
guess[i] = '0';
}
return;
}
if (history_index == 10){
game_over = true;
lcd.clear();
render_history(secret, history, history_index);
lcd.setCursor(0, 1);
lcd.print("Game over! My secret was ");
lcd.print(secret);
while (digitalRead(BTN_1_PIN) == HIGH && digitalRead(BTN_2_PIN) == HIGH && digitalRead(BTN_3_PIN) == HIGH && digitalRead(BTN_4_PIN) == HIGH && digitalRead(BTN_ENTER_PIN) == HIGH){
// Wait for any button to be pressed
}
game_over = false;
history_index = 0;
turn_off_leds();
current_digit = 0;
for (int i = 0; i < 4; i++){
guess[i] = '0';
}
}
}
}
}
void loop() {
}
char* generate_code(bool repeat, int length) {
randomSeed(analogRead(0));
if (length < 1){
return NULL;
}
if (repeat == false && length > 10){
return NULL;
}
char* code = (char*)malloc(length+1);
for (int i = 0; i < length; i++){
code[i] = random(10) + '0';
if (repeat == false){
for (int j = 0; j < i; j++){
if (code[i] == code[j]){
i--;
break;
}
}
}
}
code[length] = '\0';
return code;
}
void render_history(const char* secret, char** history, int entry){
for (int i = 0; i < entry; i++){
int peg_a, peg_b;
get_score(secret, history[i], &peg_a, &peg_b);
lcd.print(i+1);
lcd.print(": ");
lcd.print(history[i]);
lcd.print(" ");
for (int j = 0; j < peg_a; j++){
lcd.print("R");
}
for (int j = 0; j < peg_b; j++){
lcd.print("B");
}
lcd.print("\n");
}
}
void update_display(){
lcd.clear();
render_history(guess, history, history_index);
lcd.print("Your guess: ");
lcd.print(guess);
}