161 lines
3.9 KiB
C
161 lines
3.9 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <time.h>
|
|
#include <ncurses.h>
|
|
|
|
#include "snake.h"
|
|
|
|
#define WIDTH 20
|
|
#define HEIGHT 20
|
|
|
|
typedef struct {
|
|
int x;
|
|
int y;
|
|
} Point;
|
|
|
|
typedef struct {
|
|
Point body[100]; // Maximum length of the snake
|
|
int length;
|
|
} Snake;
|
|
|
|
Point food;
|
|
Snake snake;
|
|
int direction; // 0: UP, 1: DOWN, 2: LEFT, 3: RIGHT
|
|
|
|
void setup() {
|
|
snake.length = 1;
|
|
snake.body[0].x = WIDTH / 2;
|
|
snake.body[0].y = HEIGHT / 2;
|
|
direction = 3; // Start moving to the right
|
|
generateFood();
|
|
}
|
|
|
|
|
|
void draw() {
|
|
clear(); // Clear the screen
|
|
|
|
for (int i = 0; i < WIDTH + 2; i++)
|
|
printw("#");
|
|
printw("\n");
|
|
|
|
for (int i = 0; i < HEIGHT; i++) {
|
|
for (int j = 0; j < WIDTH; j++) {
|
|
if (j == 0)
|
|
printw("#"); // Left wall
|
|
if (i == food.y && j == food.x)
|
|
printw("*"); // Food
|
|
else {
|
|
int isSnakePart = 0;
|
|
for (int k = 0; k < snake.length; k++) {
|
|
if (snake.body[k].x == j && snake.body[k].y == i) {
|
|
printw("O"); // Snake body
|
|
isSnakePart = 1;
|
|
}
|
|
}
|
|
if (!isSnakePart)
|
|
printw(" ");
|
|
}
|
|
if (j == WIDTH - 1)
|
|
printw("#"); // Right wall
|
|
}
|
|
printw("\n");
|
|
}
|
|
|
|
for (int i = 0; i < WIDTH + 2; i++)
|
|
printw("#");
|
|
printw("\n");
|
|
refresh(); // Refresh the screen to show changes
|
|
}
|
|
|
|
|
|
void input() {
|
|
keypad(stdscr, TRUE); // Enable special keys
|
|
halfdelay(1); // Wait for input for a short time
|
|
|
|
int ch = getch();
|
|
switch (ch) {
|
|
case KEY_UP:
|
|
if (direction != 1) direction = 0; // Up
|
|
break;
|
|
case KEY_DOWN:
|
|
if (direction != 0) direction = 1; // Down
|
|
break;
|
|
case KEY_LEFT:
|
|
if (direction != 3) direction = 2; // Left
|
|
break;
|
|
case KEY_RIGHT:
|
|
if (direction != 2) direction = 3; // Right
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
void logic() {
|
|
Point prevSegment = snake.body[0];
|
|
Point prev2Segment;
|
|
|
|
// Update the head of the snake based on the direction
|
|
switch (direction) {
|
|
case 0: // UP
|
|
snake.body[0].y--;
|
|
break;
|
|
case 1: // DOWN
|
|
snake.body[0].y++;
|
|
break;
|
|
case 2: // LEFT
|
|
snake.body[0].x--;
|
|
break;
|
|
case 3: // RIGHT
|
|
snake.body[0].x++;
|
|
break;
|
|
}
|
|
|
|
// Update the body segments
|
|
for (int i = 1; i < snake.length; i++) {
|
|
prev2Segment = snake.body[i];
|
|
snake.body[i] = prevSegment;
|
|
prevSegment = prev2Segment;
|
|
}
|
|
|
|
// Check if the snake has eaten the food
|
|
if (snake.body[0].x == food.x && snake.body[0].y == food.y) {
|
|
snake.length++;
|
|
generateFood(); // Generate new food
|
|
}
|
|
}
|
|
|
|
void generateFood() {
|
|
int validPosition = 0;
|
|
while (!validPosition) {
|
|
food.x = rand() % WIDTH;
|
|
food.y = rand() % HEIGHT;
|
|
|
|
// Check if the food position overlaps with the snake
|
|
validPosition = 1; // Assume valid until proven otherwise
|
|
for (int i = 0; i < snake.length; i++) {
|
|
if (snake.body[i].x == food.x && snake.body[i].y == food.y) {
|
|
validPosition = 0; // Found overlap, need to generate again
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int gameOver() {
|
|
// Check for wall collisions
|
|
if (snake.body[0].x < 0 || snake.body[0].x >= WIDTH ||
|
|
snake.body[0].y < 0 || snake.body[0].y >= HEIGHT) {
|
|
return 1; // Game over due to wall collision
|
|
}
|
|
|
|
// Check for self-collision
|
|
for (int i = 1; i < snake.length; i++) {
|
|
if (snake.body[i].x == snake.body[0].x &&
|
|
snake.body[i].y == snake.body[0].y) {
|
|
return 1; // Game over due to self-collision
|
|
}
|
|
}
|
|
|
|
return 0; // Game is still running
|
|
}
|