Code

//Snake source: https://www.youtube.com/watch?v=IkTK6WMlMs4 & http://pastebin.com/yiDBzjvZ

#include <LiquidCrystal.h>
#include <Time.h>

// LCD variables
LiquidCrystal lcd(8, 13, 9, 4, 5, 6, 7);
int adc_key_val[5] = {50, 200, 400, 600, 800 };
int NUM_KEYS = 5;
int adc_key_in;
int key = -1;
int oldkey = -1;
int pressedKey = -1;

// project variables
int pinIn = 3;
int pinOut = 2;
int reading;
int previous = LOW;
long lastTime;
long checkTime = 100;
bool snakeMode = false;
bool clockMode = false;

// clock variables
bool settingClock, settingTime, settingDate;
bool settingHour, settingMinute;
bool settingDay, settingMonth, settingYear;
int h, m, s, d, n, y, dMax;

//snake variables
unsigned long time, timeNow;
int gameSpeed;
boolean skip, gameOver, gameStarted;
int olddir;
int selectedLevel, levels;

boolean x[16][80];
byte myChar[8];
byte nullChar[8] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
boolean special;

struct partdef
{
  int row, column, dir; //0 - up, 1 - down, 2 - right, 3 - left
  struct partdef *next;
};
typedef partdef part;

part *head, *tail;
int i, j, collected;
long pc, pr;

void startF()
{
  gameOver = false;
  gameStarted = false;
  selectedLevel = 1;
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Select to Start");
  collected = 0;
  gameSpeed = 8;
  createSnake(3);
  time = 0;
}

void setup()
{
  pinMode(pinIn, INPUT_PULLUP);
  pinMode(pinOut, OUTPUT);
  Serial.begin(9600);
  lcd.begin(16, 2);
  setTime(12, 00, 00, 01, 01, 2016);
  levels = 5; //number of lvls
  checkMode();
}

void loop()
{
  while (snakeMode)
  {
    if (!gameOver && !gameStarted)
    {
      adc_key_in = analogRead(0);    // read the value from the sensor
      key = get_key(adc_key_in);  // convert into key press
      if (key != oldkey)   // if keypress is detected
      {
        delay(50);  // wait for debounce time
        adc_key_in = analogRead(0);    // read the value from the sensor
        key = get_key(adc_key_in);    // convert into key press
        if (key != oldkey)
        {
          oldkey = key;
          if (key >= 0)
          {
            olddir = head->dir;
            if (key == 1 && selectedLevel < levels) selectedLevel++;
            if (key == 2 && selectedLevel > 1) selectedLevel--;
            if (key == 4)
            {
              lcd.clear();
              selectedLevel--;
              newPoint();
              gameStarted = true;
            }
            else
            {
              lcd.setCursor(14, 0);
              lcd.print(selectedLevel);
            }
          }
        }
      }
    }
    if (!gameOver && gameStarted)
    {
      skip = false; //skip the second moveAll() function call if the first was made
      adc_key_in = analogRead(0);    // read the value from the sensor
      key = get_key(adc_key_in);  // convert into key press
      if (key != oldkey)   // if keypress is detected
      {
        delay(50);  // wait for debounce time
        adc_key_in = analogRead(0);    // read the value from the sensor
        key = get_key(adc_key_in);    // convert into key press
        if (key != oldkey)
        {
          oldkey = key;
          if (key >= 0)
          {
            olddir = head->dir;
            if (key == 0 && head->dir != 3) head->dir = 2;
            if (key == 1 && head->dir != 1) head->dir = 0;
            if (key == 2 && head->dir != 0) head->dir = 1;
            if (key == 3 && head->dir != 2) head->dir = 3;

            if (olddir != head->dir)
            {
              skip = true;
              delay(1000 / gameSpeed);
              moveAll();
              drawMatrix();
            }
          }
        }
      }
      if (!skip)
      {
        timeNow = millis();
        if (timeNow - time > 1000 / gameSpeed)
        {
          moveAll();
          drawMatrix();
          time = millis();
        }
      }
    }
    if (gameOver)
    {
      adc_key_in = analogRead(0);    // read the value from the sensor
      key = get_key(adc_key_in);  // convert into key press
      if (key != oldkey)   // if keypress is detected
      {
        delay(50);  // wait for debounce time
        adc_key_in = analogRead(0);    // read the value from the sensor
        key = get_key(adc_key_in);    // convert into key press
        if (key != oldkey)
        {
          oldkey = key;
          if (key >= 0)
          {
            startF();
          }
        }
      }
    }
    checkMode();
  }
  while (clockMode)
  {
    if (settingTime)
      setTime();
    else if (settingDate)
      setDate();
    else
      printTimeDate();

    readingInput();

    lcd.noBlink();
    checkMode();
  }
}

void checkMode()
{
  lcd.clear();
  reading = digitalRead(pinIn);
  Serial.println(reading);
  if (reading == 1)
  {
    snakeMode = true;
    clockMode = false;
    startF();
  }
  else if (reading == 0)
  {
    snakeMode = false;
    clockMode = true;
  }
}

bool isKeyPressed()
{
  if (clockMode)
  {
    adc_key_in = analogRead(0);    // read the value from the sensor
    key = get_key(adc_key_in);  // convert into key press
    if (key != oldkey)   // if keypress is detected
    {
      delay(50);  // wait for debounce time
      adc_key_in = analogRead(0);    // read the value from the sensor
      key = get_key(adc_key_in);    // convert into key press
      if (key != oldkey)
      {
        oldkey = key;
        return true;
      }
    }
    delay(100);
    return false;
  }
}

void printTimeDate()
{
  lcd.setCursor(4, 0);
  if (hour() < 10)
    lcd.print(0);
  lcd.print(hour());
  lcd.print(":");
  if (minute() < 10)
    lcd.print(0);
  lcd.print(minute());
  lcd.print(":");
  if (second() < 10)
    lcd.print(0);
  lcd.print(second());
  lcd.setCursor(1, 1);
  lcd.print(dayShortStr(weekday()));
  lcd.setCursor(5, 1);
  if (day() < 10)
    lcd.print(0);
  lcd.print(day());
  lcd.print("/");
  if (month() < 10)
    lcd.print(0);
  lcd.print(month());
  lcd.print("/");
  lcd.print(year());
}

void setTime()
{
  lcd.clear();
  lcd.setCursor(4, 0);
  lcd.print("Set time:");
  lcd.setCursor(4, 1);
  if (h < 10)
    lcd.print(0);
  lcd.print(h);
  lcd.print(":");
  if (m < 10)
    lcd.print(0);
  lcd.print(m);
  lcd.print(":00");
  if (settingHour)
    lcd.setCursor(5, 1);
  else if (settingMinute)
    lcd.setCursor(8, 1);
  lcd.blink();
}

void setDate()
{
  lcd.clear();
  lcd.setCursor(4, 0);
  lcd.print("Set date:");
  lcd.setCursor(3, 1);
  if (d < 10)
    lcd.print(0);
  lcd.print(d);
  lcd.print("/");
  if (n < 10)
    lcd.print(0);
  lcd.print(n);
  lcd.print("/");
  lcd.print(y);
  if (settingDay)
    lcd.setCursor(4, 1);
  else if (settingMonth)
    lcd.setCursor(7, 1);
  else if (settingYear)
    lcd.setCursor(12, 1);
  lcd.blink();
}

void readingInput()
{
  if (isKeyPressed())
  {
    if (key == 0) // right key
    {
      if (settingTime)
      {
        if (settingHour)
        {
          settingMinute = true;
          settingHour = false;
        }
        else if (settingMinute)
        {
          settingHour = true;
          settingMinute = false;
        }
      }
      else if (settingDate)
      {
        if (settingDay)
        {
          settingMonth = true;
          settingDay = false;
        }
        else if (settingMonth)
        {
          settingYear = true;
          settingMonth = false;
        }
        else if (settingYear)
        {
          settingDay = true;
          settingYear = false;
        }
      }
    }
    if (key == 1) // up key
    {
      if (settingTime)
      {
        if (settingHour)
        {
          h++;
          if (h > 23)
            h = 0;
        }
        else if (settingMinute)
        {
          m++;
          if (m > 59)
            m = 0;
        }
      }
      else if (settingDate)
      {
        if (settingDay)
        {
          d++;
          if (d > dMax)
            d = 1;
        }
        else if (settingMonth)
        {
          n++;
          if (n > 12)
            n = 1;
          updateMaxDay();
        }
        else if (settingYear)
        {
          y++;
          updateMaxDay();
        }
      }
    }
    if (key == 2) // down key
    {
      if (settingTime)
      {
        if (settingHour)
        {
          h--;
          if (h < 0)
            h = 23;
        }
        else if (settingMinute)
        {
          m--;
          if (m < 0)
            m = 59;
        }
      }
      else if (settingDate)
      {
        if (settingDay)
        {
          d--;
          if (d < 1)
            d = dMax;
        }
        else if (settingMonth)
        {
          n--;
          if (n < 1)
            n = 12;
          updateMaxDay();
        }
        else if (settingYear)
        {
          y--;
          updateMaxDay();
        }
      }
    }
    if (key == 3) // left key
    {
      if (settingTime)
      {
        if (settingHour)
        {
          settingMinute = true;
          settingHour = false;
        }
        else if (settingMinute)
        {
          settingHour = true;
          settingMinute = false;
        }
      }
      else if (settingDate)
      {
        if (settingDay)
        {
          settingYear = true;
          settingDay = false;
        }
        else if (settingYear)
        {
          settingMonth = true;
          settingYear = false;
        }
        else if (settingMonth)
        {
          settingDay = true;
          settingMonth = false;
        }
      }
    }
    if (key == 4) // select key
    {
      updateMaxDay();
      lcd.clear();
      if (!settingClock)
      {
        settingTime = true;
        settingClock = true;
        settingHour = true;
        h = hour();
        m = minute();
        s = 0;
        d = day();
        n = month();
        y = year();
      }
      else if (settingTime)
      {
        settingHour = false;
        settingDay = true;
        settingTime = false;
        settingDate = true;
      }
      else if (settingDate)
      {
        settingDay = false;
        settingDate = false;
        settingClock = false;
        setTime(h, m, s, d, n, y);
      }
    }
    key = -1;
  }
}

void updateMaxDay()
{
  if (n == 2)
  {
    if (y % 4 == 0)
      dMax = 29;
    else
      dMax = 28;
  }
  else if (n == 4 || n == 6 || n == 9 || n == 11)
    dMax = 30;
  else
    dMax = 31;
}

// Convert ADC value to key number
int get_key(unsigned int input)
{
  int k;
  for (k = 0; k < NUM_KEYS; k++)
  {
    if (input < adc_key_val[k])
    {
      return k;
    }
  }
  if (k >= NUM_KEYS)k = -1;  // No valid key pressed
  return k;
}

void drawMatrix()
{
  int cc = 0;
  if (!gameOver)
  {
    x[pr][pc] = true;
    for (int r = 0; r < 2; r++)
    {
      for (int c = 0; c < 16; c++)
      {
        special = false;
        for (int i = 0; i < 8; i++)
        {
          byte b = B00000;
          if (x[r * 8 + i][c * 5 + 0]) {
            b += B10000;
            special = true;
          }
          if (x[r * 8 + i][c * 5 + 1]) {
            b += B01000;
            special = true;
          }
          if (x[r * 8 + i][c * 5 + 2]) {
            b += B00100;
            special = true;
          }
          if (x[r * 8 + i][c * 5 + 3]) {
            b += B00010;
            special = true;
          }
          if (x[r * 8 + i][c * 5 + 4]) {
            b += B00001;
            special = true;
          }
          myChar[i] = b;
        }
        if (special)
        {
          lcd.createChar(cc, myChar);
          lcd.setCursor(c, r);
          lcd.write(byte(cc));
          cc++;
        }
        else
        {
          lcd.setCursor(c, r);
          lcd.write(254);
        }
      }
    }
  }
}

void freeList()
{
  part *p, *q;
  p = tail;
  while (p != NULL)
  {
    q = p;
    p = p->next;
    free(q);
  }
  head = tail = NULL;
}

void gameOverFunction()
{
  delay(1000);
  lcd.clear();
  freeList();
  lcd.setCursor(3, 0);
  lcd.print("Game Over!");
  lcd.setCursor(4, 1);
  lcd.print("Score: ");
  lcd.print(collected);
  delay(1000);
}

void growSnake()
{
  part *p;
  p = (part*)malloc(sizeof(part));
  p->row = tail->row;
  p->column = tail->column;
  p->dir = tail->dir;
  p->next = tail;
  tail = p;
}

void newPoint()
{
  part *p;
  p = tail;
  boolean newp = true;
  while (newp)
  {
    pr = random(16);
    pc = random(80);
    newp = false;
    while (p->next != NULL && !newp)
    {
      if (p->row == pr && p->column == pc) newp = true;
      p = p->next;
    }
  }
  if (collected < 13 && gameStarted) growSnake();
}

void moveHead()
{
  switch (head->dir) // 1 step in direction
  {
    case 0: head->row--; break;
    case 1: head->row++; break;
    case 2: head->column++; break;
    case 3: head->column--; break;
    default : break;
  }
  if (head->column >= 80) head->column = 0;
  if (head->column < 0) head->column = 79;
  if (head->row >= 16) head->row = 0;
  if (head->row < 0) head->row = 15;

  part *p;
  p = tail;
  while (p != head && !gameOver) // self collision
  {
    if (p->row == head->row && p->column == head->column) gameOver = true;
    p = p->next;
  }
  if (gameOver)
    gameOverFunction();
  else
  {
    x[head->row][head->column] = true;

    if (head->row == pr && head->column == pc) // point pickup check
    {
      collected++;
      if (gameSpeed < 25) gameSpeed += 3;
      newPoint();
    }
  }
}

void moveAll()
{
  part *p;
  p = tail;
  x[p->row][p->column] = false;
  while (p->next != NULL)
  {
    p->row = p->next->row;
    p->column = p->next->column;
    p->dir = p->next->dir;
    p = p->next;
  }
  moveHead();
}

void createSnake(int n) // n = size of snake
{
  for (i = 0; i < 16; i++)
    for (j = 0; j < 80; j++)
      x[i][j] = false;

  part *p, *q;
  tail = (part*)malloc(sizeof(part));
  tail->row = 7;
  tail->column = 39 + n / 2;
  tail->dir = 3;
  q = tail;
  x[tail->row][tail->column] = true;
  for (i = 0; i < n - 1; i++) // build snake from tail to head
  {
    p = (part*)malloc(sizeof(part));
    p->row = q->row;
    p->column = q->column - 1; //initial snake id placed horizoltally
    x[p->row][p->column] = true;
    p->dir = q->dir;
    q->next = p;
    q = p;
  }
  if (n > 1)
  {
    p->next = NULL;
    head  = p;
  }
  else
  {
    tail->next = NULL;
    head = tail;
  }
}

Leave a comment