123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266 |
- #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';
- }
|