Crack the Code..... Pun intended. Holiday Gift

This code is not 100% perfect but I believe it can be understood without comments.

Here is my challenge. The first person to tell me what it does and is will get $20 via PayPal. Seriously

Good Luck.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

long randomNumber;
int randomA;
int randomB;
int randomC;
int randomD;
int randomCode;
int codeVal;

int realNumber;
int realA;
int realB;
int realC;
int realD;

int value;
int count;
int state;
int lastState;
int counter;

int relayPin = 5;
int SW = 2;
int CLK = 9;  // Pin 9 to clk on encoder
int DT = 8;  // Pin 8 to DT on encoder


void setup() {
  
  lcd.begin(16, 2);
  randomSeed(analogRead(0));
  pinMode (SW, INPUT);
  pinMode (CLK, INPUT);
  pinMode (DT, INPUT);
  pinMode  (relayPin, OUTPUT);
  //rotation = digitalRead(CLK);
  counter = 5;
  count = 0;
  lastState = digitalRead(CLK);
}

void loop() {

  lcd.setCursor(0, 0);
  lcd.print("  Code  #");
  lcd.setCursor(0, 1);
  lcd.print(" Access #");
  lcd.setCursor(11, 0);
  lcd.print(randomCode);

  if (count == 0) {
    randomGen();
  }

  if (digitalRead(SW) == HIGH); {
    delay(500);
    count++;
  }
  switch (count) {  //RotPosition = counter
    case 1:
      select();
      realA = (counter * 1000);
      lcd.setCursor(11, 1);
      lcd.print(counter);
      break;
    case 2:
      lcd.setCursor(11, 1);
      lcd.print("*");
      select();
      realB = (counter * 100);
      lcd.setCursor(12, 1);
      lcd.print(counter);
      break;
    case 3:
      lcd.setCursor(12, 1);
      lcd.print("*");
      select();
      realC = (counter * 10);
      lcd.setCursor(13, 1);
      lcd.print(counter);
      break;
    case 4:
      lcd.setCursor(13, 1);
      lcd.print("*");
      select();
      realD = (counter * 10);
      lcd.setCursor(14, 1);
      lcd.print(counter);
      break;
    case 5:
      lcd.setCursor(14, 1);
      lcd.print("*");
      delay(500);
      check();
      break;
  }
}

int select() {
  state = digitalRead(CLK);
  if (state != lastState) {
    if (digitalRead(DT) != state)
    {
      counter++;
    }
    else
    {
      counter--;
    }
  }
    if (digitalRead(SW) == HIGH); {
    delay(500);
    count++;
  }
}

int check() {
  realNumber = (realA + realB + realC + realD);
  codeVal = map (randomCode, 9999, 1111, 1111, 9999);

  if (codeVal == realNumber) {
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("    * ACCESS    ");
    lcd.setCursor(0,1);
    lcd.print("     GRANTED    ");
    delay(500);
    digitalWrite(relayPin, HIGH);
    delay(3000);
    digitalWrite(relayPin, LOW);
    count = 0;
    counter = 5;
    lcd.clear();
  }
}

int randomGen() {
  randomNumber = random(1, 10);
  randomA = (randomNumber * 1000);
  randomB = (randomNumber * 100);
  randomC = (randomNumber * 10);
  randomD = randomNumber;
  randomCode = (randomA + randomB + randomC + randomD);
  delay(100);
    if (digitalRead(SW) == HIGH); {
    delay(100);
    count++;
  }
  return randomCode;
}

It’s a device that’s intended to activate a relay when the user guesses the access #. An LCD displays a randomly generated code #. The user can adjust each digit of their guess using a rotary encoder and that number is displayed on the LCD, then press a button to commit their guess and then the guessed number is obfuscated with a *. The access number has an inverse relationship to the code # (e.g. if code is 3333, correct access number is 7777).

However, there are some serious bugs in the code which makes the device not work as intended. A semicolon at the end of the switch state checks:

if (digitalRead(SW) == HIGH); {

causes the code inside the following brace to always be run (as though the switch was permanently pressed). This causes the count to go 2, 4, 6… instead of the expected 2, 3, 4. So you end up with the Access # 55.

The IDE would display useful warning messages in the console that would indicate this bug if you turn on warnings in File > Preferences > Compiler warnings. I always leave mine set to “All”. This will also warn you of the other minor problem of the check function having an int type but not returning anything. That doesn’t actually break anything, but it doesn’t make much sense either. A similar issue is that randomGen returns an int but you don’t use the return value.

I would also suggest that you might want to restrict the counter value to 1-9. Currently you can set it to multiple digit numbers and negative numbers, which makes the display a bit screwy. The encoder reading code also doesn’t seem great to me. I would recommend that you use the Encoder library:
https://github.com/PaulStoffregen/Encoder
unless you’re really set on making your own implementation.

Yes. Correct. And as I stated, not 100% correct. Thanks for the tips. What is your PayPal?

Could have made it more challenging by using generic variable names and no global ones.

It’s Christmas lol nobody should have to work to hard.