snake.ino 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. #define BOARD_LENGTH 8
  2. #define SNAKE_MAX_SIZE 32
  3. struct pair {
  4. int x;
  5. int y;
  6. };
  7. class Snake {
  8. private:
  9. char state;
  10. int snake_size;
  11. pair pos[64];
  12. pair get_next_move(pair p);
  13. pair fruit_pos;
  14. bool fruit;
  15. public:
  16. Snake() {
  17. this->state = 'R';
  18. this->snake_size = 4;
  19. fruit = false;
  20. for (int i = 0; i < snake_size ; ++i) {
  21. pair p;
  22. p.x = 7;
  23. p.y = i;
  24. this->pos[0] = p;
  25. }
  26. }
  27. void change_state(char state) {
  28. if (state != 'I') {
  29. // if currently moving up or down and state change is
  30. // left or right, then update
  31. if ((state == 'R' || state == 'L') &&
  32. (this->state == 'U' || this->state == 'D')) {
  33. this->state = state;
  34. }
  35. else if ((state == 'U' || state == 'D') &&
  36. (this->state == 'R' || this->state == 'L')) {
  37. this->state = state;
  38. }
  39. }
  40. //else ignore
  41. }
  42. void snake_to_matrix(int (*pixels)[BOARD_LENGTH]) {
  43. for (int i = 0; i < BOARD_LENGTH; ++i) {
  44. for (int j = 0; j < BOARD_LENGTH; ++j) {
  45. pixels[i][j] = LOW; // CLEAR ALL PIXELS;
  46. }
  47. }
  48. for (int i = 0; i < snake_size; ++i) {
  49. pair p = pos[i];
  50. pixels[p.x][p.y] = HIGH; // TURN ON PIXELS OF SNAKE
  51. }
  52. if (fruit) {
  53. pixels[fruit_pos.x][fruit_pos.y] = HIGH;
  54. }
  55. }
  56. pair snake_head() {
  57. return pos[0];
  58. }
  59. void generate_fruit() {
  60. if (!fruit) {
  61. fruit = true;
  62. // random inclusive (starts at 0)
  63. fruit_pos.x = random(7);
  64. fruit_pos.y = random(7);
  65. }
  66. }
  67. void grow();
  68. void next_move() {
  69. for (int i = snake_size; i > 0; --i) {
  70. pos[i] = pos[i - 1];
  71. }
  72. pos[0] = get_next_move(pos[0]);
  73. if (fruit) {
  74. if (pos[0].x == fruit_pos.x && pos[0].y == fruit_pos.y) {
  75. grow();
  76. fruit = false;
  77. }
  78. }
  79. }
  80. bool eats_itself() {
  81. for (int i = 1; i < snake_size; ++i) {
  82. if (pos[0].x == pos[i].x && pos[0].y == pos[i].y) {
  83. return true;
  84. }
  85. }
  86. return false;
  87. }
  88. };
  89. pair Snake::get_next_move(pair p)
  90. {
  91. pair r(p);
  92. switch (state) {
  93. case 'U':
  94. r.x = (p.x + BOARD_LENGTH - 1) % BOARD_LENGTH;
  95. r.y = p.y;
  96. break;
  97. case 'D':
  98. r.x = (p.x + 1) % BOARD_LENGTH;
  99. r.y = p.y;
  100. break;
  101. case 'R':
  102. r.x = p.x;
  103. r.y = (p.y + 1) % BOARD_LENGTH;
  104. break;
  105. case 'L':
  106. r.x = p.x;
  107. r.y = (p.y + BOARD_LENGTH - 1) % BOARD_LENGTH;
  108. break;
  109. }
  110. return r;
  111. }
  112. void Snake::grow()
  113. {
  114. if (snake_size < SNAKE_MAX_SIZE) {
  115. pos[snake_size] = pos[snake_size - 1];
  116. ++snake_size;
  117. }
  118. }
  119. const int row[8] = { 2, 7, 19, 5, 13, 18, 12, 16 };
  120. const int col[8] = { 6, 11, 10, 3, 17, 4, 8, 9 };
  121. // 2-dimensional array of pixels:
  122. int pixels[8][8];
  123. // cursor position:
  124. int x = 5;
  125. int y = 5;
  126. Snake snake;
  127. // A BIG SAD CROSS
  128. int dead[8][8] = {
  129. {HIGH, LOW, LOW, LOW, LOW, LOW, LOW, HIGH},
  130. {LOW, HIGH, LOW, LOW, LOW, LOW, HIGH, LOW},
  131. {LOW, LOW, HIGH, LOW, LOW, HIGH, LOW, LOW},
  132. {LOW, LOW, LOW, HIGH, HIGH, LOW, LOW, LOW},
  133. {LOW, LOW, LOW, HIGH, HIGH, LOW, LOW, LOW},
  134. {LOW, LOW, HIGH, LOW, LOW, HIGH, LOW, LOW},
  135. {LOW, HIGH, LOW, LOW, LOW, LOW, HIGH, LOW},
  136. {HIGH, LOW, LOW, LOW, LOW, LOW, LOW, HIGH},
  137. };
  138. /**
  139. * The setup routine runs once when you press reset.
  140. */
  141. void setup()
  142. {
  143. Serial.begin(9600); // 9600 bps
  144. // initialize the I/O pins as outputs
  145. // iterate over the pins:
  146. for (int this_pin = 0; this_pin < 8; ++this_pin) {
  147. // initialize the output pins:
  148. pinMode(col[this_pin], OUTPUT);
  149. pinMode(row[this_pin], OUTPUT);
  150. // take the col pins (i.e. the cathodes) high to ensure that
  151. // the LEDS are off:
  152. digitalWrite(col[this_pin], HIGH);
  153. }
  154. // initialize the pixel matrix:
  155. for (int x = 0; x < 8; ++x) {
  156. for (int y = 0; y < 8; ++y) {
  157. pixels[x][y] = HIGH;
  158. }
  159. }
  160. randomSeed(analogRead(0));
  161. }
  162. /**
  163. * The loop routine runs over and over again forever.
  164. */
  165. void loop()
  166. {
  167. snake.generate_fruit();
  168. snake.next_move();
  169. snake.snake_to_matrix(pixels);
  170. for (int i = 0; i < 30; ++i) {
  171. display_pixels();
  172. snake.change_state(read_sensors());
  173. }
  174. // draw the screen:
  175. if (snake.eats_itself()) {
  176. for (int i = 0; i < 3; i++) {
  177. for (int j = 0; j < 100; ++j) {
  178. display_pixels();
  179. }
  180. delay(500);
  181. }
  182. for (int i = 0; i < 8; ++i) {
  183. for (int j = 0; j < 8; ++j) {
  184. pixels[i][j] = dead[i][j];
  185. }
  186. }
  187. while (true) {
  188. display_pixels();
  189. }
  190. }
  191. }
  192. /**
  193. * Prints the pixels array in the matrix
  194. */
  195. void display_pixels()
  196. {
  197. for (int c = 0; c < 8; ++c) {
  198. digitalWrite(col[c], LOW);
  199. for (int r = 0; r < 8; ++r) {
  200. digitalWrite(row[r], pixels[r][c]);
  201. }
  202. delay(1);
  203. display_clear();
  204. }
  205. }
  206. /**
  207. * Remove empty display light
  208. * 清空显示
  209. */
  210. void display_clear()
  211. {
  212. for (int i = 0; i < 8; ++i) {
  213. digitalWrite(row[i], LOW);
  214. digitalWrite(col[i], HIGH);
  215. }
  216. }
  217. /**
  218. * Returns the current joystick input with some leeway
  219. * I means Iddle
  220. * L means Left
  221. * R means Right
  222. * U means Up
  223. * D means Down
  224. */
  225. char read_sensors()
  226. {
  227. //int clicked = digitalRead(z); // if 0, then clicked
  228. //if(!clicked) return 'C';
  229. x = map(analogRead(A0), 0, 1023, 0, 10) - 5;
  230. y = map(analogRead(A1), 0, 1023, 0, 10) - 5;
  231. // test if joystick is the middle with some leeway
  232. if (abs(x) <= 3 && abs(y) <= 3) {
  233. return 'I';
  234. // test if move in x axis is > than in y axis
  235. } else if (abs(x) > abs(y)) {
  236. if (x > 1) {
  237. return 'R';
  238. } else {
  239. return 'L';
  240. }
  241. } else {
  242. if (y > 1) {
  243. return 'U';
  244. } else {
  245. return 'D';
  246. }
  247. }
  248. return 'I';
  249. }