#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 fruit_pos; bool fruit; public: Snake() { this->state = 'R'; this->snake_size = 4; fruit = false; for (int i = 0; i < snake_size ; ++i) { pair p; p.x = 7; p.y = i; this->pos[0] = p; } } void change_state(char state) { if (state != 'I') { // if currently moving up or down and state change is // left or right, then update if ((state == 'R' || state == 'L') && (this->state == 'U' || this->state == 'D')) { this->state = state; } else if ((state == 'U' || state == 'D') && (this->state == 'R' || this->state == 'L')) { this->state = state; } } //else ignore } 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] = LOW; // CLEAR ALL PIXELS; } } for (int i = 0; i < snake_size; ++i) { pair p = pos[i]; pixels[p.x][p.y] = HIGH; // TURN ON PIXELS OF SNAKE } if (fruit) { pixels[fruit_pos.x][fruit_pos.y] = HIGH; } } pair snake_head() { return pos[0]; } void generate_fruit() { if (!fruit) { fruit = true; // random inclusive (starts at 0) fruit_pos.x = random(7); fruit_pos.y = random(7); } } void grow(); 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 == fruit_pos.x && pos[0].y == fruit_pos.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 'R': r.x = p.x; r.y = (p.y + 1) % BOARD_LENGTH; break; case 'L': 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 }; 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; // A BIG SAD CROSS int dead[8][8] = { {HIGH, LOW, LOW, LOW, LOW, LOW, LOW, HIGH}, {LOW, HIGH, LOW, LOW, LOW, LOW, HIGH, LOW}, {LOW, LOW, HIGH, LOW, LOW, HIGH, LOW, LOW}, {LOW, LOW, LOW, HIGH, HIGH, LOW, LOW, LOW}, {LOW, LOW, LOW, HIGH, HIGH, LOW, LOW, LOW}, {LOW, LOW, HIGH, LOW, LOW, HIGH, LOW, LOW}, {LOW, HIGH, LOW, LOW, LOW, LOW, HIGH, LOW}, {HIGH, LOW, LOW, LOW, LOW, LOW, LOW, HIGH}, }; /** * The setup routine runs once when you press reset. */ void setup() { Serial.begin(9600); // 9600 bps // initialize the I/O pins as outputs // iterate over the pins: for (int this_pin = 0; this_pin < 8; ++this_pin) { // initialize the output pins: pinMode(col[this_pin], OUTPUT); pinMode(row[this_pin], OUTPUT); // take the col pins (i.e. the cathodes) high to ensure that // the LEDS are off: digitalWrite(col[this_pin], 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)); } /** * The loop routine runs over and over again forever. */ void loop() { snake.generate_fruit(); snake.next_move(); snake.snake_to_matrix(pixels); for (int i = 0; i < 30; ++i) { display_pixels(); snake.change_state(read_sensors()); } // draw the screen: if (snake.eats_itself()) { for (int i = 0; i < 3; i++) { for (int j = 0; j < 100; ++j) { display_pixels(); } delay(500); } for (int i = 0; i < 8; ++i) { for (int j = 0; j < 8; ++j) { pixels[i][j] = dead[i][j]; } } while (true) { display_pixels(); } } } /** * Prints the pixels array in the matrix */ void display_pixels() { for (int c = 0; c < 8; ++c) { digitalWrite(col[c], LOW); for (int r = 0; r < 8; ++r) { digitalWrite(row[r], pixels[r][c]); } delay(1); display_clear(); } } /** * Remove empty display light * 清空显示 */ void display_clear() { for (int i = 0; i < 8; ++i) { digitalWrite(row[i], LOW); digitalWrite(col[i], HIGH); } } /** * Returns the current joystick input with some leeway * I means Iddle * L means Left * R means Right * U means Up * D means Down */ 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; // test if joystick is the middle with some leeway if (abs(x) <= 3 && abs(y) <= 3) { return 'I'; // test if move in x axis is > than in y axis } else if (abs(x) > abs(y)) { if (x > 1) { return 'R'; } else { return 'L'; } } else { if (y > 1) { return 'U'; } else { return 'D'; } } return 'I'; }