Skip to content

Instantly share code, notes, and snippets.

@kamiyaowl
Last active August 29, 2015 14:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kamiyaowl/98df263356ecea657a22 to your computer and use it in GitHub Desktop.
Save kamiyaowl/98df263356ecea657a22 to your computer and use it in GitHub Desktop.
snake for Arduino
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdint.h>
typedef int8_t boolean;
#define true 1
#define false 0
#define WIDTH 32
#define HEIGHT 16
#define CENTER_X (WIDTH / 2)
#define CENTER_Y (HEIGHT / 2)
#define QUEUE_SIZE (WIDTH * HEIGHT)
#define UP 0
#define DOWN 1
#define LEFT 2
#define RIGHT 3
#define DIRECTIONS 4
#define DIRECTION_NONE 10
#define EMPTY '+'
#define FILL '*'
#define TARGET '@'
//ゲームグラフィックならめっちゃ楽に書ける
char snake_draw_field[HEIGHT][WIDTH];
uint16_t current_x,current_y,target_x,target_y;
uint8_t snake_dir;
uint32_t search_data;
boolean is_found;
/* ======================================== */
uint32_t queue_data[QUEUE_SIZE];
uint16_t queue_head;
uint16_t queue_size;
void queue_init() {
uint16_t i;
for(i = 0 ; i < QUEUE_SIZE ; ++i)
queue_data[i] = 0;
queue_head = 0;
queue_size = 0;//ADCで最初にenqueueできるように
}
void enqueue(uint32_t data) {
if(queue_size >= QUEUE_SIZE) abort();
uint16_t p = (queue_head + queue_size) % QUEUE_SIZE;
queue_data[p] = data;
++queue_size;
}
uint32_t dequeue() {
if(queue_size == 0) abort();
uint32_t data = queue_data[queue_head];
queue_head = (queue_head + 1) % QUEUE_SIZE;
--queue_size;
return data;
}
//Queueの要素全てに関数を適用します
void queue_all(void (*f)(uint32_t)){
uint16_t i;
for(i = 0 ; i < queue_size ; ++i)
f(queue_data[(i + queue_head) % QUEUE_SIZE]);
}
void queue_print_all() {
uint16_t i;
for(i = 0 ; i < QUEUE_SIZE ; ++i) {
if(i == queue_head) printf("[");
if(i == (queue_head + queue_size) % QUEUE_SIZE) printf("]");
printf("%0x ",queue_data[i]);
}
printf("\n");
}
void queue_elem_print(uint32_t data) {
printf("%d ",data);
}
void queue_print() {
uint16_t i;
queue_all(queue_elem_print);
printf("\n");
}
/* ======================================== */
///private functions
uint16_t snake_score() {
return queue_size;
}
boolean snake_is_crear(){
return queue_size == QUEUE_SIZE;
}
void snake_add_head(uint16_t x,uint16_t y){
enqueue(x << 16 | y);
}
void snake_remove_tail(){
dequeue();
}
void snake_field_init(){
uint16_t i,j;
for(j = 0 ; j < HEIGHT ; ++j)
for(i = 0 ; i < WIDTH ; ++i)
snake_draw_field[j][i] = EMPTY;
}
void snake_field_map(uint32_t data) {
snake_draw_field[data & 0xff][data >> 16] = FILL;
}
void snake_target_map(){
snake_draw_field[target_y][target_x] = TARGET;
}
void snake_search(uint32_t data) {
if(data == search_data) is_found = true;
}
boolean snake_find(uint16_t x,uint16_t y){
search_data = x << 16 | y;
is_found = false;
queue_all(snake_search);
return is_found;
}
void snake_create_target(){
uint16_t nx,ny;
do {
nx = rand() % WIDTH;
ny = rand() % HEIGHT;
}while(snake_find(nx,ny));
//apply
target_x = nx;
target_y = ny;
}
boolean snake_ahead(uint8_t dir){
if(dir != DIRECTION_NONE) snake_dir = dir;
//valid
//アンダーフローを考慮
uint16_t nx = current_x;
uint16_t ny = current_y;
switch(snake_dir) {
case UP:
--ny;
break;
case DOWN:
++ny;
break;
case LEFT:
--nx;
break;
case RIGHT:
++nx;
break;
}
if(nx >= WIDTH || ny >= HEIGHT) return false;
if(snake_find(nx,ny)) return false;
//add
current_x = nx;
current_y = ny;
snake_add_head(current_x,current_y);
//target get?
if(current_x == target_x && current_y == target_y) {
if(snake_is_crear()) {
printf("+++++ GAME CLEAR +++++\n");
return true;
}
snake_create_target();
} else {
snake_remove_tail();
}
return true;
}
/* ======================================== */
//public functions
void snake_init() {
queue_init();
snake_field_init();
current_x = CENTER_X;
current_y = CENTER_Y;
snake_add_head(current_x,current_y);
snake_dir = rand() % DIRECTIONS;
snake_create_target();
}
boolean snake_update(uint8_t dir) {
if(!snake_ahead(dir)) return false;
//ゲーム描画なら別の方法でかける
snake_field_init();
snake_target_map();
queue_all(snake_field_map);
return true;
}
void snake_print() {
uint16_t i,j;
//init
//print
for(j = 0 ; j < HEIGHT ; ++j) {
for(i = 0 ; i < WIDTH ; ++i) {
printf("%c",snake_draw_field[j][i]);
}
printf("\n");
}
printf("score = %d\n",snake_score());
}
/* ======================================== */
int main(void) {
uint8_t dir = DIRECTION_NONE;
char c;
srand(time(NULL));//TODO replace other
snake_init();
while(true) {
printf("W,S,A,D>");
scanf("%c%*c",&c);
switch(c){
case 'w':
dir = UP;
break;
case 's':
dir = DOWN;
break;
case 'a':
dir = LEFT;
break;
case 'd':
dir = RIGHT;
break;
case 'n':
snake_init();
break;
case 'q':
return 0;
}
if(!snake_update(dir)){
printf("===== GAME OVER =====\n");
printf("score = %d\n",snake_score());
snake_init();
} else {
snake_print();
}
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment