#define BOARD_LENGTH 8 #define SNAKE_MAX_SIZE 32 struct pair { int x; int y; }; class Snake { private: char state; int snake_size; pair pos[64]; pair get_next_move(pair p); pair fruitPos; bool fruit; public: Snake() { this->state = 'U'; this->snake_size = 4; fruit = false; 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 grow(); 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 } if(fruit) pixels[fruitPos.x][fruitPos.y] = LOW; } pair snake_head() { return pos[0]; } void generate_fruit() { if(!fruit) { fruit = true; fruitPos.x = random(7); fruitPos.y = random(7); } } void next_move() { for (int i = snake_size; i > 0; i--) { pos[i] = pos[i - 1]; } pos[0] = get_next_move(pos[0]); if (fruit) { if (pos[0].x == fruitPos.x && pos[0].y == fruitPos.y) { grow(); fruit = false; } } } bool eats_itself() { for(int i = 1; i < snake_size; i++) if( pos[0].x == pos[i].x && pos[0].y == pos[i].y ) return true; return false; } }; 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::grow() { if (snake_size < SNAKE_MAX_SIZE) { pos[snake_size] = pos[snake_size - 1]; ++snake_size; } } 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; } } randomSeed(analogRead(0)); } void loop() { if(random(20) == 0) snake.generate_fruit(); snake.snake_to_matrix(pixels); snake.next_move(); // draw the screen: if(snake.eats_itself()){ for(int i = 0; i < 3; i++){ for(int j = 0; j < 100; j++) Display(); delay(500); } int dead[8][8] = { {0,1,1,1,1,1,1,0}, {1,0,1,1,1,1,0,1}, {1,1,0,1,1,0,1,1}, {1,1,1,0,0,1,1,1}, {1,1,1,0,0,1,1,1}, {1,1,0,1,1,0,1,1}, {1,0,1,1,1,1,0,1}, {0,1,1,1,1,1,1,0}, }; for(int i = 0; i < 8; i++) for(int j = 0; j < 8; j++) pixels[i][j] = dead[i][j]; while(true) Display(); } for(int i = 0; i < 30; i++) { Display(); snake.change_state(read_sensors()); } } 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'; }