Загрузка данных
#include <LedControl.h>
// --- ПРОТОТИПЫ ФУНКЦИЙ (чтобы Wokwi не ругался) ---
void initGame();
void readJoystick();
void moveSnake();
void spawnFood();
void drawGame();
void endGame();
void handleGameOver();
void updateRGB();
void setRGB(int r, int g, int b);
// --- ПИНЫ MAX7219 ---
#define DIN_PIN 11
#define CS_PIN 10
#define CLK_PIN 13
// --- ПИНЫ ---
#define JOY_X A0
#define JOY_Y A1
#define JOY_BTN 2
#define BUZZER 9
#define RGB_R 3
#define RGB_G 5
#define RGB_B 6
// --- ОБЪЕКТ ---
LedControl matrix = LedControl(DIN_PIN, CLK_PIN, CS_PIN, 1);
// --- ИГРОВЫЕ ПЕРЕМЕННЫЕ ---
const int SIZE = 8;
int snakeX[64], snakeY[64];
int snakeLength = 3;
int dirX = 1, dirY = 0;
int foodX, foodY;
int score = 0;
bool gameOver = false;
// --- ТАЙМЕРЫ ---
unsigned long lastMove = 0;
unsigned long moveInterval = 250;
unsigned long lastJoyCheck = 0;
void setup() {
Serial.begin(9600);
matrix.shutdown(0, false);
matrix.setIntensity(0, 8);
matrix.clearDisplay(0);
pinMode(JOY_BTN, INPUT_PULLUP);
pinMode(BUZZER, OUTPUT);
pinMode(RGB_R, OUTPUT);
pinMode(RGB_G, OUTPUT);
pinMode(RGB_B, OUTPUT);
randomSeed(analogRead(A2));
initGame();
Serial.println(F("=== SNAKE 8x8 ==="));
Serial.println(F("Use joystick to move. Press button to restart."));
}
void loop() {
if (gameOver) {
handleGameOver();
return;
}
if (millis() - lastJoyCheck > 50) {
lastJoyCheck = millis();
readJoystick();
}
if (millis() - lastMove > moveInterval) {
lastMove = millis();
moveSnake();
drawGame();
}
}
void initGame() {
snakeLength = 3;
snakeX[0] = 4; snakeY[0] = 4;
snakeX[1] = 3; snakeY[1] = 4;
snakeX[2] = 2; snakeY[2] = 4;
dirX = 1;
dirY = 0;
score = 0;
gameOver = false;
spawnFood();
setRGB(0, 255, 0);
Serial.println(F("[GAME] Started"));
}
void readJoystick() {
int x = analogRead(JOY_X);
int y = analogRead(JOY_Y);
if (x < 300 && dirX != 1) {
dirX = -1;
dirY = 0;
}
else if (x > 700 && dirX != -1) {
dirX = 1;
dirY = 0;
}
else if (y < 300 && dirY != 1) {
dirX = 0;
dirY = -1;
}
else if (y > 700 && dirY != -1) {
dirX = 0;
dirY = 1;
}
if (digitalRead(JOY_BTN) == LOW) {
delay(50);
if (digitalRead(JOY_BTN) == LOW) {
initGame();
matrix.clearDisplay(0);
}
}
}
void moveSnake() {
for (int i = snakeLength - 1; i > 0; i--) {
snakeX[i] = snakeX[i - 1];
snakeY[i] = snakeY[i - 1];
}
snakeX[0] += dirX;
snakeY[0] += dirY;
if (snakeX[0] < 0 || snakeX[0] >= SIZE || snakeY[0] < 0 || snakeY[0] >= SIZE) {
endGame();
return;
}
for (int i = 1; i < snakeLength; i++) {
if (snakeX[0] == snakeX[i] && snakeY[0] == snakeY[i]) {
endGame();
return;
}
}
if (snakeX[0] == foodX && snakeY[0] == foodY) {
score++;
snakeLength++;
tone(BUZZER, 1500, 100);
Serial.print(F("[SCORE] "));
Serial.println(score);
spawnFood();
updateRGB();
}
}
void spawnFood() {
bool valid = false;
while (!valid) {
foodX = random(0, SIZE);
foodY = random(0, SIZE);
valid = true;
for (int i = 0; i < snakeLength; i++) {
if (snakeX[i] == foodX && snakeY[i] == foodY) {
valid = false;
break;
}
}
}
}
void drawGame() {
matrix.clearDisplay(0);
for (int i = 0; i < snakeLength; i++) {
matrix.setLed(0, snakeY[i], snakeX[i], true);
}
if (millis() % 500 < 250) {
matrix.setLed(0, foodY, foodX, true);
}
}
void endGame() {
gameOver = true;
tone(BUZZER, 500, 500);
setRGB(255, 0, 0);
Serial.print(F("[GAME OVER] Score: "));
Serial.println(score);
}
void handleGameOver() {
static unsigned long lastBlink = 0;
static bool state = false;
if (millis() - lastBlink > 300) {
lastBlink = millis();
state = !state;
for (int r = 0; r < 8; r++) {
for (int c = 0; c < 8; c++) {
matrix.setLed(0, r, c, state);
}
}
}
if (digitalRead(JOY_BTN) == LOW) {
delay(50);
if (digitalRead(JOY_BTN) == LOW) {
matrix.clearDisplay(0);
initGame();
}
}
}
void updateRGB() {
if (score < 5) {
setRGB(0, 255, 0);
} else if (score < 10) {
setRGB(255, 255, 0);
} else if (score < 15) {
setRGB(255, 128, 0);
} else {
setRGB(255, 0, 0);
}
}
void setRGB(int r, int g, int b) {
analogWrite(RGB_R, r);
analogWrite(RGB_G, g);
analogWrite(RGB_B, b);
}