#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 10, 9, 8, 7);
int upPin = 5 , downPin=3 , rightPin =4 ,leftPin=6;
int stepPin=2;
int ledTest = 13;
bool upState=false ,rightState=false ,leftState=false;
bool stepState=false,downState=false;
short const screenWidth = 5*16; // set the screen dimension
short const screenHeight = 8*2;
bool display[screenWidth * screenHeight];
const char arraySize = 30;
class vector{
public:
char x,y;
vector(){ x=-1,y=0; }
vector(char Xinput ,char Yinput)
{
x = Xinput;
y = Yinput;
}
vector operator + (const vector &right) {return addition(right);}
vector operator +=(const vector &right) {return addition(right);}
vector addition(const vector &right)
{
vector copy = *this;
copy.x +=right.x;
copy.y +=right.y;
return copy;
}
};
vector direction = vector(1,0); // parameter
vector currentHeadPosition = vector(3,5);
vector newHeadPosition;
vector divmod(unsigned char numerator , unsigned char denumerator)
{
unsigned char value=0;
while (value <= numerator)
value += denumerator;
if (value > numerator)
value -= denumerator;
return vector(value/denumerator ,numerator-value);
}
unsigned char getRand(unsigned char number)
{
unsigned char numerator = rand();
unsigned char value=0;
while (value <= numerator)
value += number;
if (value > numerator)
value -= number;
return numerator-value;
}
inline bool vectorIntersection(vector &v1 , vector &v2)
{ return v1.x == v2.x && v1.y == v2.y; }
class snakeBody{
public:
vector bodyArray[arraySize];
unsigned short indexStart = -1;
unsigned short indexEnd = 2;
snakeBody() {
bodyArray[0] = vector(1,5);
bodyArray[1] = vector(2,5);
bodyArray[2] = vector(3,5);
}
void makeMove()
{
++indexStart;++indexEnd;
bodyArray[(divmod(indexStart,arraySize)).y] = vector(-1,0);
bodyArray[(divmod(indexEnd,arraySize)).y] = newHeadPosition;
currentHeadPosition = newHeadPosition;
}
bool checkForHit(){
for (unsigned char index =0 ; index < arraySize ; ++index)
{
if ((bodyArray[index]).x != -1)
{
if (vectorIntersection(bodyArray[index], newHeadPosition))
return false;
}
}
return true;
}
void writeBody()
{
for (unsigned short index=0 ; index < arraySize ; ++index)
{
vector v = bodyArray[index];
if (v.x != -1)
display[v.y * screenWidth + v.x] = 1;
}
}
void increaseSize()
{
--indexStart;
}
};
snakeBody snakeInstance;
class food {
public:
vector foodTopLeftPosition;
food(){selectPosition();}
food(unsigned char x, unsigned char y)
{
foodTopLeftPosition = vector(x,y);
}
void writeFoodPositions(){
display[foodTopLeftPosition.y * screenWidth + foodTopLeftPosition.x]=true;
}
void checkForIntersection()
{
if (vectorIntersection(foodTopLeftPosition , currentHeadPosition))
{
hitFood();
}
}
void hitFood()
{
selectPosition();
snakeInstance.increaseSize();
}
void setPoint(unsigned char x , unsigned char y)
{
foodTopLeftPosition = vector(x,y);
}
private:
void selectPosition()
{
// srand(time(0));
unsigned char x = getRand(screenWidth-2);
unsigned char y = getRand(screenHeight-2);
foodTopLeftPosition = vector(x,y);
}
};
food foodInstance = food(10,5);
inline unsigned char powFoTwo(unsigned char power)
{
unsigned char value=1;
while (power >=1)
{value *=2;--power;}
return value;
}
/*
verticalBlock *640
charactor *5
veritcalLIne *80
iteration
*/
void generateCharactor()
{
for (unsigned char verticalBlock=0 ; verticalBlock<2 ; ++verticalBlock)
{
for (unsigned char charactor=0 ; charactor < 16 ; ++charactor)
{
byte cell[8];
for (unsigned char verticalLine=0 ; verticalLine<8 ; ++verticalLine)
{
unsigned char lineValue=0;
for (unsigned char iteration = 0 ; iteration<5 ; ++iteration)
{
bool element = display[verticalBlock*640 + charactor*5 + verticalLine*80 + iteration];
if(element)
{lineValue += powFoTwo(5-iteration);}
}
cell[verticalLine] = (byte)lineValue;
}
lcd.createChar(charactor+verticalBlock*16+1,cell);
}
}
}
void writeCharater()
{
for (unsigned short y=0 ; y <2 ;++y)
{
for (unsigned short x=0 ; x < 16 ; ++x)
{
lcd.setCursor(x,y);
lcd.write(1+y*16+x);
}
}
}
void cleanDisplay()
{
for (bool &c:display)
{
c = false;
}
}
void makeOneMove(){
if (snakeInstance.checkForHit())
{
snakeInstance.makeMove();
snakeInstance.writeBody();
}
else {} // game over
}
void lifeCircle(){
cleanDisplay();
newHeadPosition = direction + currentHeadPosition;
foodInstance.checkForIntersection();
foodInstance.writeFoodPositions();
makeOneMove();
generateCharactor();
writeCharater();
}
// end of the program
void setup()
{
pinMode(upPin,INPUT);
pinMode(downPin,INPUT);
pinMode(rightPin,INPUT);
pinMode(leftPin,INPUT);
pinMode(stepPin,INPUT);
pinMode(ledTest,OUTPUT);
lcd.begin(16, 2);
for (int index=0 ; index < 16 ; ++index)
{
byte oneChar[8];
for (int oneLine=0 ; oneLine < 8 ; ++oneLine)
{
oneChar[oneLine] = index;
}
lcd.createChar(index ,oneChar);
lcd.setCursor(index,0);
lcd.write(index);
}
}
void loop()
{
if (!upState && digitalRead(upPin)== HIGH)
{
upState = true;
}
else if (upState && digitalRead(upPin)== LOW)
{
upState = true;
}
if (!downState && digitalRead(downPin)== HIGH)
{
downState = true;
}
else if (downState && digitalRead(downPin)== LOW)
{
downState = true;
}
if (!rightState && digitalRead(rightPin)== HIGH)
{
rightState = true;
}
else if (rightState && digitalRead(rightPin)== LOW)
{
rightState = true;
}
if (!leftState && digitalRead(leftPin)== HIGH)
{
leftState = true;
}
else if (leftState && digitalRead(leftPin)== LOW)
{
leftState = true;
}
if (!stepState && digitalRead(stepPin)== HIGH)
{
stepState = true;
}
else if (stepState && digitalRead(stepPin)== LOW)
{
stepState = true;
}
}