arduino-snake/snake.ino
2020-02-12 22:38:07 +00:00

179 lines
4.0 KiB
C++

#define BOARD_LENGTH 8
struct pair {
int x;
int y;
};
class Snake {
private:
char state;
int snake_size;
pair pos[64];
pair get_next_move(pair p);
public:
Snake() {
this->state = 'U';
this->snake_size = 4;
for (int i = snake_size - 1; i >= 0; i--) {
pair p;
p.x = 5;
p.y = i;
this->pos[i] = p;
}
}
void change_state(char state) {
if (state != '\0'){
if((state == 'L' || state == 'R') && (this->state == 'U' || this->state=='D')) // if currently moving up or down and state change is left or right update
this->state = state;
else if((state == 'U' || state == 'D') && (this->state == 'L' || this->state=='R')) // the opposite
this->state = state;
}
//else ignore
}
void eat(pair p);
void snake_to_matrix(int (*pixels)[BOARD_LENGTH]){
for(int i = 0; i < BOARD_LENGTH; i++){
for(int j = 0; j < BOARD_LENGTH; j++){
pixels[i][j] = HIGH; // CLEAR ALL PIXELS;
}
}
for(int i = 0; i < snake_size; i++) {
pair p = pos[i];
pixels[p.x][p.y] = LOW; // TURN ON PIXELS OF SNAKE
}
}
void next_move();
pair snake_head() {
return pos[0];
}
};
pair Snake::get_next_move(pair p) {
pair r(p);
switch (state) {
case 'U':
r.x = (p.x + BOARD_LENGTH - 1) % BOARD_LENGTH;
r.y = p.y;
break;
case 'D':
r.x = (p.x + 1) % BOARD_LENGTH;
r.y = p.y;
break;
case 'L':
r.x = p.x;
r.y = (p.y + 1) % BOARD_LENGTH;
break;
case 'R':
r.x = p.x;
r.y = (p.y + BOARD_LENGTH - 1) % BOARD_LENGTH;
break;
}
return r;
}
void Snake::next_move() {
for (int i = snake_size; i > 0; i--) {
pos[i] = pos[i - 1];
}
pos[0] = get_next_move(pos[0]);
}
void Snake::eat(pair p) { pos[snake_size++] = p; }
const int row[8] = {2, 7, 19, 5, 13, 18, 12, 16};
// 2-dimensional array of column pin numbers:
const int col[8] = {6, 11, 10, 3, 17, 4, 8, 9};
// 2-dimensional array of pixels:
int pixels[8][8];
// cursor position:
int x = 5;
int y = 5;
Snake snake;
void setup() {
Serial.begin(9600); // 9600 bps
// initialize the I/O pins as outputs
// iterate over the pins:
for (int thisPin = 0; thisPin < 8; thisPin++) {
// initialize the output pins:
pinMode(col[thisPin], OUTPUT);
pinMode(row[thisPin], OUTPUT);
// take the col pins (i.e. the cathodes) high to ensure that
// the LEDS are off:
digitalWrite(col[thisPin], HIGH);
}
// initialize the pixel matrix:
for (int x = 0; x < 8; x++) {
for (int y = 0; y < 8; y++) {
pixels[x][y] = HIGH;
}
}
}
void loop() {
snake.change_state(read_sensors());
snake.snake_to_matrix(pixels);
snake.next_move();
// draw the screen:
for(int i = 0; i < 100; i++)
Display();
}
void readSensors() {
// turn off the last position:
pixels[x][y] = HIGH;
// read the sensors for X and Y values:
x = 7 - map(analogRead(A0), 0, 1022, 0, 7);
y = map(analogRead(A1), 0, 1022, 0, 7);
// set the new pixel position low so that the LED will turn on
// in the next screen refresh:
pixels[x][y] = LOW;
}
void Display()
{
for(int c = 0; c<8;c++)
{
digitalWrite(col[c],LOW);//use thr column
//loop
for(int r = 0;r<8;r++)
{
digitalWrite(row[r],(pixels[r][c]+1)%2);
}
delay(1);
Clear(); //Remove empty display light
}
}
void Clear() //清空显示
{
for(int i = 0;i<8;i++)
{
digitalWrite(row[i],LOW);
digitalWrite(col[i],HIGH);
}
}
char read_sensors() {
//int clicked = digitalRead(z); // if 0, then clicked
//if(!clicked) return 'C';
x = map(analogRead(A0),0,1023,0,10) - 5;
y = map(analogRead(A1),0,1023,0,10) - 5;
if(abs(x) <= 1 && abs(y) <= 1) { // test if joystick is the middle with some leeway
return '\0';
}else if(abs(x) > abs(y) ) { // test if move in x axis is > than in y axis
if(x > 1) return 'L';
else return 'R';
} else {
if(y > 1) return 'U';
else return 'D';
}
return '\0';
}