#include <LiquidCrystal_I2C.h>
#include <TM1637TinyDisplay.h>
TM1637TinyDisplay counter(2, 3);
TM1637TinyDisplay maxCounter(5, 4);
LiquidCrystal_I2C lcd(0x27,20,4);
byte snake[] = {
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
};
byte food[] = {
B00100,
B01110,
B01110,
B11111,
B11111,
B01110,
B01110,
B00100,
};
int score = 0, maxScore = 0;
byte snakeH[80] = {0};
byte snakeV[80] = {0};
byte foodH = 5, foodV = 2;
int vert = 0, horz = 0;
int direction = 0; // 0: stop, 1: up, 2: down, 3: left, 4: right
int frame = 0;
void setup() {
// init data
snakeH[80] = {0};
snakeV[80] = {0};
foodH = 5, foodV = 2;
direction = 0;
score = 0;
// init counter
counter.begin();
counter.showNumber(score);
// init max counter
maxCounter.begin();
maxCounter.showNumber(maxScore);
randomSeed(analogRead(A3));
// init analog joystick
pinMode(A2,2);
// init lcd
lcd.init();
lcd.backlight();
lcd.createChar(0, snake);
lcd.createChar(1, food);
lcd.home();
lcd.write(0);
Serial.begin(9600);
}
void mov() {
vert=analogRead(A0);
horz=analogRead(A1);
if (direction != 0) {
for (int i = score + 1; i > 0; i--) {
snakeH[i] = snakeH[i - 1];
snakeV[i] = snakeV[i - 1];
}
}
if(vert > 530) {
// move up
if (direction != 2) {
direction = 1;
snakeV[0]--;
}
}
else if(vert < 490) {
// move down
if (direction != 1) {
direction = 2;
snakeV[0]++;
snakeV[0] = snakeV[0] % 4;
}
}
else if(horz > 530){
// move left
if (direction != 4) {
direction = 3;
snakeH[0]--;
}
}
else if (horz < 490) {
// move right
if (direction != 3) {
direction = 4;
snakeH[0]++;
snakeH[0] = snakeH[0] % 20;
}
} else {
if (direction == 1) {
snakeV[0]--;
} else if (direction == 2) {
snakeV[0]++;
snakeV[0] = snakeV[0] % 4;
} else if (direction == 3) {
snakeH[0]--;
} else if (direction == 4) {
snakeH[0]++;
snakeH[0] = snakeH[0] % 20;
}
}
snakeH[0] = constrain(snakeH[0], 0, 19);
snakeV[0] = constrain(snakeV[0], 0, 3);
}
void updateScore() {
counter.showNumber(score);
if (score > maxScore) {
maxScore = score;
maxCounter.showNumber(maxScore);
}
}
void placeFood() {
bool foodPlaced = false;
while (!foodPlaced) {
foodH = random(0, 20);
foodV = random(0, 4);
foodPlaced = true;
for (int i = 0; i < score; i++) {
if (snakeH[i] == foodH && snakeV[i] == foodV) {
foodPlaced = false;
break;
}
}
}
}
void display() {
lcd.clear();
for (int i = 0; i <= score; i++) {
lcd.setCursor(snakeH[i], snakeV[i]);
lcd.write(0);
}
lcd.setCursor(foodH, foodV);
lcd.write(1);
}
bool checkGameOver() {
for (int i = 1; i <= score; i++) {
if (snakeH[0] == snakeH[i] && snakeV[0] == snakeV[i]) {
return true;
}
}
return false;
}
void loop() {
frame = (frame + 1) % 3;
if (frame == 0) {
mov();
} else {
if (snakeH[0] == foodH && snakeV[0] == foodV) {
score++;
placeFood();
}
if (checkGameOver()) {
lcd.clear();
lcd.print("Game Over!");
delay(3000);
setup();
return;
}
display();
updateScore();
delay(200);
}
}