C++

C language linked list to achieve snake game


Read and learn the source code, and made simple comments and modifications, which only used linked list data structure, very suitable for beginners of C language learning to read.

The program can be compiled and run under VS2013.

#include<stdio.h>
#include<time.h>
#include<windows.h>
#include<stdlib.h>

#define U 1
#define D 2
#define L 3
#define R 4  // The state of the snake, U On:   ; D : under; L: On the left  R Right:

typedef struct SNAKE // The snake 1 A node
{
 int x;
 int y;
 struct SNAKE *next;
}snake;

// The global variable //
int score = 0, add = 10;// Total score and food score per meal.
int status, sleeptime = 200;// The time interval for each run
snake *head, *food;// Snake head pointer, food pointer
snake *q;// The pointer used to traverse the snake
int endGamestatus = 0; // At the end of the game, 1 : hit a wall; 2 : bite yourself; 3 : quit the game voluntarily.

// Declare all functions //
void Pos();
void creatMap();
void initSnake();
int biteSelf();
void createFood();
void cantCrossWall();
void snakeMove();
void pause();
void runGame();
void initGame();
void endGame();
void gameStart();

void Pos(int x, int y)// Set cursor position
{
 COORD pos;
 HANDLE hOutput;
 pos.X = x;
 pos.Y = y;
 hOutput = GetStdHandle(STD_OUTPUT_HANDLE);// Returns a handle to a standard input, output, or error device / Handle to the error screen buffer
 SetConsoleCursorPosition(hOutput, pos);
}

void creatMap()// Create a map
{
 int i;
 for (i = 0; i<58; i += 2)// Print top and bottom border
 {
  Pos(i, 0);
  printf(" s ");//1 Two squares take up two positions
  Pos(i, 26);
  printf(" s ");
 }
 for (i = 1; i<26; i++)// Print left and right border
 {
  Pos(0, i);
  printf(" s ");
  Pos(56, i);
  printf(" s ");
 }
}

void initSnake()// Initializes the snake body
{
 snake *tail;
 int i;
 tail = (snake*)malloc(sizeof(snake));// Start with the tail of the snake x,y Set the starting position //
 tail->x = 24;
 tail->y = 5;
 tail->next = NULL;
 for (i = 1; i <= 4; i++)// The initial length is 4
 {
  head = (snake*)malloc(sizeof(snake));
  head->next = tail;
  head->x = 24 + 2 * i;
  head->y = 5;
  tail = head;
 }
 while (tail != NULL)// From head to toe, output snake body
 {
  Pos(tail->x, tail->y);
  printf(" s ");
  tail = tail->next;
 }
}
//??
int biteSelf()// Judge if you bit yourself
{
 snake *self;
 self = head->next;
 while (self != NULL)
 {
  if (self->x == head->x && self->y == head->y)
  {
   return 1;
  }
  self = self->next;
 }
 return 0;
}

void createFood()// Random food
{
 snake *food_1;
 srand((unsigned)time(NULL));// To prevent the same random number being generated each time, the seed is set to time
 food_1 = (snake*)malloc(sizeof(snake));
 while ((food_1->x % 2) != 0) // Make sure it's an even number, so that the food can meet the snake head
 {
  food_1->x = rand() % 52 + 2;
 }
 food_1->y = rand() % 24 + 1;
 q = head;
 while (q->next == NULL)
 {
  if (q->x == food_1->x && q->y == food_1->y) // Determine if the body of the snake overlaps with the food
  {
   free(food_1);
   createFood();
  }
  q = q->next;
 }
 Pos(food_1->x, food_1->y);
 food = food_1;
 printf(" s ");
}

void cantCrossWall()// Can't wear wall
{
 if (head->x == 0 || head->x == 56 || head->y == 0 || head->y == 26)
 {
  endGamestatus = 1;
  endGame();
 }
}

void snakeMove()// Snakes' , on U, Under the D, On the left L, right R
{
 snake * nexthead;
 cantCrossWall();

 nexthead = (snake*)malloc(sizeof(snake));
 if (status == U)
 {
  nexthead->x = head->x;
  nexthead->y = head->y - 1;
  if (nexthead->x == food->x && nexthead->y == food->y)// If the 1 A food //
  {
   nexthead->next = head;
   head = nexthead;
   q = head;
   while (q != NULL)
   {
    Pos(q->x, q->y);
    printf(" s ");
    q = q->next;
   }
   score = score + add;
   createFood();
  }
  else            // If there is no food //
  {
   nexthead->next = head;
   head = nexthead;
   q = head;
   while (q->next->next != NULL)
   {
    Pos(q->x, q->y);
    printf(" s ");
    q = q->next;
   }
   Pos(q->next->x, q->next->y);
   printf(" ");
   free(q->next);
   q->next = NULL;
  }
 }
 if (status == D)
 {
  nexthead->x = head->x;
  nexthead->y = head->y + 1;
  if (nexthead->x == food->x && nexthead->y == food->y) // There is food
  {
   nexthead->next = head;
   head = nexthead;
   q = head;
   while (q != NULL)
   {
    Pos(q->x, q->y);
    printf(" s ");
    q = q->next;
   }
   score = score + add;
   createFood();
  }
  else        // There is no food
  {
   nexthead->next = head;
   head = nexthead;
   q = head;
   while (q->next->next != NULL)
   {
    Pos(q->x, q->y);
    printf(" s ");
    q = q->next;
   }
   Pos(q->next->x, q->next->y);
   printf(" ");
   free(q->next);
   q->next = NULL;
  }
 }
 if (status == L)
 {
  nexthead->x = head->x - 2;
  nexthead->y = head->y;
  if (nexthead->x == food->x && nexthead->y == food->y)// There is food
  {
   nexthead->next = head;
   head = nexthead;
   q = head;
   while (q != NULL)
   {
    Pos(q->x, q->y);
    printf(" s ");
    q = q->next;
   }
   score = score + add;
   createFood();
  }
  else        // There is no food
  {
   nexthead->next = head;
   head = nexthead;
   q = head;
   while (q->next->next != NULL)
   {
    Pos(q->x, q->y);
    printf(" s ");
    q = q->next;
   }
   Pos(q->next->x, q->next->y);
   printf(" ");
   free(q->next);
   q->next = NULL;
  }
 }
 if (status == R)
 {
  nexthead->x = head->x + 2;
  nexthead->y = head->y;
  if (nexthead->x == food->x && nexthead->y == food->y)// There is food
  {
   nexthead->next = head;
   head = nexthead;
   q = head;
   while (q != NULL)
   {
    Pos(q->x, q->y);
    printf(" s ");
    q = q->next;
   }
   score = score + add;
   createFood();
  }
  else           // There is no food
  {
   nexthead->next = head;
   head = nexthead;
   q = head;
   while (q->next->next != NULL)
   {
    Pos(q->x, q->y);
    printf(" s ");
    q = q->next;
   }
   Pos(q->next->x, q->next->y);
   printf(" ");
   free(q->next);
   q->next = NULL;
  }
 }
 if (biteSelf() == 1)  // Judge if you're going to bite yourself
 {
  endGamestatus = 2;
  endGame();
 }
}

void pause()// suspended
{
 while (1)
 {
  Sleep(300);
  if (GetAsyncKeyState(VK_SPACE))
  {
   break;
  }

 }
}

void runGame()// Control of the game
{

 Pos(64, 15);
 printf(" You can't walk through walls. You can't bite yourself \n");
 Pos(64, 16);
 printf(" With write . left . please . → separately control the movement of the snake .");
 Pos(64, 17);
 printf("F1  To speed up, F2  To slow down \n");
 Pos(64, 18);
 printf("ESC  : quit the game .space : pause the game .");
 Pos(64, 20);
 printf("C Language research centre  www.clang.cc");
 status = R;
 while (1)
 {
  Pos(64, 10);
  printf(" Score: %d ", score);
  Pos(64, 11);
  printf(" Score per food: %d points ", add);
  if (GetAsyncKeyState(VK_UP) && status != D)
  {
   status = U;
  }
  else if (GetAsyncKeyState(VK_DOWN) && status != U)
  {
   status = D;
  }
  else if (GetAsyncKeyState(VK_LEFT) && status != R)
  {
   status = L;
  }
  else if (GetAsyncKeyState(VK_RIGHT) && status != L)
  {
   status = R;
  }
  else if (GetAsyncKeyState(VK_SPACE))
  {
   pause();
  }
  else if (GetAsyncKeyState(VK_ESCAPE))
  {
   endGamestatus = 3;
   break;
  }
  else if (GetAsyncKeyState(VK_F1))
  {
   if (sleeptime >= 50)
   {
    sleeptime = sleeptime - 30;
    add = add + 2;
    if (sleeptime == 320)
    {
     add = 2;// To prevent to 1 And then we add it back again
    }
   }
  }
  else if (GetAsyncKeyState(VK_F2))
  {
   if (sleeptime<350)
   {
    sleeptime = sleeptime + 30;
    add = add - 2;
    if (sleeptime == 350)
    {
     add = 1; // Guaranteed minimum score 1
    }
   }
  }
  Sleep(sleeptime);
  snakeMove();
 }
}

void initGame()// Start interface
{
 Pos(40, 12);

 system("title C Language research centre  www.clang.cc");
 printf(" Welcome to the snake game! ");
 Pos(40, 25);
 printf("    C Language research centre  www.clang.cc.\n");
 system("pause");
 system("cls");
 Pos(25, 12);
 printf(" With write . left . please . → separately control the movement of the snake,  F1  To speed up, 2  To slow down \n");
 Pos(25, 13);
 printf(" The acceleration will result in higher scores. \n");
 system("pause");
 system("cls");
}

void endGame()// End of the game
{

 system("cls");
 Pos(24, 12);
 if (endGamestatus == 1)
 {
  printf(" Sorry, you hit the wall. Game over .");
 }
 else if (endGamestatus == 2)
 {
  printf(" Sorry, you bit yourself. Game over .");
 }
 else if (endGamestatus == 3)
 {
  printf(" Your game is over. ");
 }
 Pos(24, 13);
 printf(" Your score is %d\n", score);
 while (getchar() != 'y')
 {
  printf("close?[y]");
 }
 exit(0);
}

void gameStart()// Game initialization
{
 system("mode con cols=100 lines=30");
 initGame();
 creatMap();
 initSnake();
 createFood();
}

int main()
{
 gameStart();
 runGame();
 endGame();
 return 0;
}