#include #include #include /* typedef struct map_t { */ /* } Map; */ const int screenHeight = 800; const int screenWidth = 800; int fps = 60; int rows = 10; int cols = 10; int size; int food_x; int food_y; int score = 0; char score_text[16] = "0"; typedef enum directions { UP, DOWN, LEFT, RIGHT } Direction; typedef struct snake_body { int x; int y; } SnakeBody; typedef struct snake_t { SnakeBody *body; int max_length; int length; int direction; int frame_duration; bool alive; } Snake; Snake make_snake(int max_len, int speed){ Snake snek; if (max_len < 3){ snek.alive = false; snek.length = 0; return snek; } snek.body = (SnakeBody*) calloc(max_len, sizeof(SnakeBody)); snek.max_length = max_len; snek.length = 3; snek.body[0].x = GetRandomValue(0, cols - 1); snek.body[0].y = GetRandomValue(0, rows - 1); snek.frame_duration = fps / speed; snek.direction = snek.body[0].x < cols / 2 ? RIGHT : LEFT; snek.alive = true; snek.body[1] = snek.body[2] = snek.body[0]; snek.body[1].x += snek.direction == LEFT ? 1 : -1; snek.body[2].x += snek.direction == LEFT ? 2 : -2; return snek; } void free_snake(Snake* s){ free(s->body); } void grow_snake(Snake* s){ int i = s->length; if (i < s->max_length){ s->body[i] = (SnakeBody) { 2 * s->body[i - 1].x - s->body[i - 2].x, 2 * s->body[i - 1].y - s->body[i - 2].y }; s->length++; } } void draw_snake(Snake* s){ for (int i = 0; i < s->length; i++){ DrawRectangle(size * s->body[i].x, size * s->body[i].y, size, size, BLACK); } return ; } bool collides_with_snake(Snake* s, int x, int y){ for (int i = 0; i < s->length; i++){ if (s->body[i].x == x && s->body[i].y == y){ return true; } } return false; } void place_food(Snake* s){ do { food_x = GetRandomValue(0, cols - 1); food_y = GetRandomValue(0, rows - 1); } while (collides_with_snake(s, food_x, food_y)); } void move_snake(Snake* s){ SnakeBody temp1 = s->body[0]; SnakeBody temp2; switch (s->direction){ case LEFT: s->body[0].x--; if (s->body[0].x < 0 || s->body[0].x >= cols){ s->alive = false; } break; case RIGHT: s->body[0].x++; if (s->body[0].x < 0 || s->body[0].x >= cols){ s->alive = false; } break; case UP: s->body[0].y--; if (s->body[0].y < 0 || s->body[0].y >= rows){ s->alive = false; } break; case DOWN: s->body[0].y++; if (s->body[0].x < 0 || s->body[0].y >= rows){ s->alive = false; } break; } for (int i = 1; i < s->length; i++){ if (s->body[0].x == s->body[i].x && s->body[0].y == s->body[i].y){ s->alive = false; break; } temp2 = s->body[i]; s->body[i] = temp1; temp1 = temp2; } } /* int frame = 0; */ void update_snake(Snake* s){ static int frame = 0; if (frame++ > s->frame_duration){ move_snake(s); frame = 0; } int key; while ((key = GetKeyPressed()) != 0){ switch (key){ case KEY_W: s->direction = UP; break; case KEY_A: s->direction = LEFT; break; case KEY_S: s->direction = DOWN; break; case KEY_D: s->direction = RIGHT; break; case KEY_G: grow_snake(s); } } if (collides_with_snake(s, food_x, food_y)){ food_x = food_y = -1; score++; snprintf(score_text, 16, "%d", score); grow_snake(s); place_food(s); } } void draw_grid(int size){ /* DrawGrid(10, screenWidth / 10); */ for (int i = 0; i < rows; i++){ DrawLine(0, i * size, screenWidth, i * size, BLACK); } for (int j = 0; j < cols; j++){ DrawLine(j * size, 0, j * size, screenHeight, BLACK); } } void init_game(){ InitWindow(screenHeight, screenHeight, "Snek"); SetTargetFPS(fps); int width = screenWidth / cols; int height = screenHeight / rows; size = height > width ? width : height; } int main(void){ init_game(); Snake snek = make_snake(100, 5); while (!WindowShouldClose()){ BeginDrawing(); ClearBackground(WHITE); draw_grid(size); if (snek.alive){ update_snake(&snek); } else { DrawText("Died!", screenWidth / 2, screenHeight / 2, 20, BLACK); } if (food_x >= 0){ DrawRectangle(size * food_x, size * food_y, size, size, RED); } draw_snake(&snek); DrawText(score_text, 0, 0, 20, BLACK); EndDrawing(); } free_snake(&snek); CloseWindow(); return 0; }