#include "LedControl.h"
LedControl lc=LedControl(11,13,10,1);
int startingToggle = 0; //1 = start game, 0 = waiting for input
int joystickXMax = 1023;
int joystickXMin = 0;
int joystickYMax = 1023;
int joystickYMin = 0;
int currentHeadLocationX = 3;
int currentHeadLocationY = 3;
int curretXDirection = 0;
int curretYDirection = 0;
int previousXDirection = 0;
int previousYDirection = 0;
int snakeLength = 1;
int snakeLengthMax = 64;
int foodLocationX;
int foodLocationY;
int analogX=0;
int analogY=0;
const int gridRows = 8;
const int gridColumns = 8;
const int arrayRows = 2;
const int arrayColumns = gridRows * gridColumns;
int gameGrid[gridRows][gridColumns];
int snakeLocationsArray[arrayRows][arrayColumns];
void setup() {
Serial.begin(9600);
//Game grid initialization
for (int i = 0; i < gridRows; ++i) {
for (int j = 0; j < gridColumns; ++j) {
gameGrid[i][j] = 0;
}
}
for (int i = 0; i < arrayRows; ++i) {
for (int j = 0; j < arrayColumns; ++j) {
snakeLocationsArray[i][j] = -1;
}
}
//test snake
// printGameGrid();
// printLocationArray();
// Wake up the MAX72XX from power-saving mode
lc.shutdown(0, false);
// Set a medium brightness for the LEDs
lc.setIntensity(0, 8);
// Clear the display
lc.clearDisplay(0);
//waits till there is any analog movement till starting game
while(analogX == 0 && analogY == 0){
Serial.println("Move joystick to start game...");
// analogX = map(analogRead(A1), 0, 1023, -1, 1);// use normal map if your joystick is actually calibrated
// analogY = map(analogRead(A2), 0, 1023, -1, 1);
analogX = customMap(analogRead(A2), 0, 1023);
analogY = customMap(analogRead(A1), 0, 1023);
delay(500);
}
Serial.println("Starting in...");
delay(1000);
Serial.println("3");
delay(1000);
Serial.println("2");
delay(1000);
Serial.println("1");
delay(1000);
Serial.println("Go!");
startingToggle =1;
foodLocationGenerator();
}
int reMapColumn(int col) {
return 7 - col;
}
void loop() {
if(startingToggle == 1){
lc.setLed(0, reMapColumn(foodLocationX), foodLocationY, true);
// analogX = map(analogRead(A1), 0, 1023, -1, 1); // use normal map if your joystick is actually calibrated
// analogY = map(analogRead(A2), 0, 1023, -1, 1);
analogX = customMap(analogRead(A2), 0, 1023);
analogY = customMap(analogRead(A1), 0, 1023);
setCurrentDirection(analogX, analogY);
int tempHeadX = currentHeadLocationX;
int tempHeadY = currentHeadLocationY;
currentHeadLocationX += curretXDirection;
currentHeadLocationY += curretYDirection;
// Serial.print("Current Head Location X: ");
// Serial.println(currentHeadLocationX);
// Serial.print("Current Head Location Y: ");
// Serial.println(currentHeadLocationY);
// Serial.println(snakeLength);
//might change the signs to include or not include actual grid values
if(currentHeadLocationX >= gridRows || currentHeadLocationY >= gridColumns || currentHeadLocationX < 0 || currentHeadLocationY < 0){
Serial.println("GAME OVER");
gameReset();
}
else{
moveSnake(currentHeadLocationX,currentHeadLocationY);
if (currentHeadLocationX == foodLocationX && currentHeadLocationY == foodLocationY) {
snakeLength++; // Function to increase the size of the snake
foodLocationGenerator(); // Function to generate a new location for the food
}
if(isSnakeCheck(currentHeadLocationX,currentHeadLocationY)){//if returns true, run gameReset
gameReset();
}
locationToDisplay();
winCheck();
delay(200);
lc.clearDisplay(0);
}
}
}
void printGameGrid() {
for (int i = 0; i < gridRows; ++i) {
for (int j = 0; j < gridColumns; ++j) {
Serial.print(gameGrid[i][j]);
Serial.print(" "); // Add space for readability
}
Serial.println(); // New line after each row
}
Serial.println(); // Add an extra line for separation
}
void printLocationArray() {
for (int i = 0; i < arrayRows; ++i) {
for (int j = 0; j < arrayColumns; ++j) {
Serial.print(snakeLocationsArray[i][j]);
Serial.print(" "); // Add space for readability
}
Serial.println(); // New line after each row
}
Serial.println(); // Add an extra line for separation
}
void gameReset(){
lc.clearDisplay(0);
for (int i = 0; i < arrayRows; ++i) {
for (int j = 0; j < arrayColumns; ++j) {
snakeLocationsArray[i][j] = -1;
}
}
currentHeadLocationX = 3;
currentHeadLocationY = 3;
snakeLength = 1;
curretXDirection = 0;
curretYDirection = 0;
startingToggle = 0;
setup(); // never knew you could do this, but it makes complete sense
}
void setCurrentDirection(int x, int y){
//basically if the change is going to be in the opposite direction, just dont change the direction
if (x == 1 && curretXDirection != -1) {
curretXDirection = x;
curretYDirection = 0;
}
else if (x == -1 && curretXDirection != 1) {
curretXDirection = x;
curretYDirection = 0;
}
else if (y == 1 && curretYDirection != -1) {
curretYDirection = y;
curretXDirection = 0;
}
else if (y == -1 && curretYDirection != 1) {
curretYDirection = y;
curretXDirection = 0;
}
}
void moveSnake(int currentHeadLocationX, int currentHeadLocationY){
for(int i = arrayColumns-1; i > 0; i--){
snakeLocationsArray[0][i] = snakeLocationsArray[0][i-1];
snakeLocationsArray[1][i] = snakeLocationsArray[1][i-1];
}
snakeLocationsArray[0][0] = currentHeadLocationX;
snakeLocationsArray[1][0] = currentHeadLocationY;
if(snakeLength < arrayColumns){
snakeLocationsArray[0][snakeLength] = -1;
snakeLocationsArray[1][snakeLength] = -1;
}
}
void locationToDisplay(){
// lc.clearDisplay(0);
for(int i = 0; i< snakeLength; i++){
int x = snakeLocationsArray[0][i]; //how to use for loop for the rows part so that it can be change through variables?
int y = snakeLocationsArray[1][i];
// Serial.println(x);
// Serial.println(y);
if(x!= -1 && y != -1){
lc.setLed(0,reMapColumn(x),y,true);
}
}
}
void foodLocationGenerator(){
do{
foodLocationX = random(0, gridRows);
foodLocationY = random(0, gridColumns);
// foodLocationX = 1; //test
// foodLocationY = 1;
}
while(isSnakeCheck(foodLocationX, foodLocationY));// keep looking for radom values until the method returns false ( no matching cordinates)
}
bool isSnakeCheck(int x, int y){
for(int i = 1 ; i < snakeLength; i++){
if(snakeLocationsArray[0][i] == x && snakeLocationsArray[1][i] == y){
return true;
}
}
return false;// if no matching cordinates, return false
}
void winCheck(){
if(snakeLength == snakeLengthMax){
gameReset();
Serial.println("YOU WIN");
}
}
int customMap(int value, int minValue, int maxValue) {
int midValue = (minValue + maxValue) / 2;
int oneThirdAbove = midValue + (maxValue - midValue) / 3;
int oneThirdBelow = midValue - (midValue - minValue) / 3;
if (value >= oneThirdAbove)
return 1;
else if (value <= oneThirdBelow)
return -1;
else
return 0; // Value falls within the middle third
}