1. 程式人生 > 程式設計 >C語言迴圈連結串列實現貪吃蛇遊戲

C語言迴圈連結串列實現貪吃蛇遊戲

本文例項為大家分享了C語言表實現貪吃蛇遊戲的具體程式碼,供大家參考,具體內容如下

總體思想

利用迴圈連結串列將一條蛇的座標進行儲存,然後利用gotoxy()函式(可以將游標定位到指定的位置),此時根據蛇的座標進行輸出“@”,輸出多幾個既可以產生一條蛇。通過遍歷迴圈連結串列進行蛇的移動,對迴圈連結串列的插入元素,產生蛇變長的效果。下面為各功能實現的函式

1.貪吃蛇地圖函式map()
2.蛇的移動move(),up(),left()等函式
3.產生食物food()和吃到食物eat_food()
4.蛇吃到食物時產生的變長效果snake_link()函式
5.判斷蛇的死亡,分別為撞牆hit_wall()和自殺suicide()

1.貪吃蛇地圖函式map()

遊戲地圖採用的是應該封閉的區域,採用一個數組a[25][50],將此陣列初始化為0,將遊戲牆的邊緣賦值為1,當陣列為0,輸出" ",陣列為1,輸出“#”,產生一個地圖。

程式碼如下:

void map() //建立蛇的地圖
{
 int a[25][50] = {0};
 int i,j;
 for(i = 0; i < 50; i++)
 {
  a[0][i] = 1;
  a[24][i] =1;
 }
 for(i = 0; i < 25; i++)
 {
  a[i][0] = 1;
  a[i][49] =1;
 }
 for(i = 0; i < 25; i++)
  for(j = 0; j < 50; j++)
  {
   if(j%50 == 0)
    printf("\n");
   if(a[i][j] == 0)
   {
    printf(" ");
   }
   else
   {
    printf("#");
   }
  }
}

2.蛇的移動move(),up(),left()等函式

move()函式主要對蛇的上下左右進行更改在此採用switch函式進行解決(下面程式碼中ch為全域性變數)
程式碼如下

void move(struct snake *p) //蛇的移動函式
{
 while(1)
 {
  ch = getch();
  switch(ch)
  {
  case 'W':p = up(p);break;
  case 'A':p = left(p);break;
  case 'D':p = right(p);break;
  case 'S':p = down(p);break;
  }
 }
}

讓蛇動起來的即我們主要對蛇的座標進行更改,此時蛇頭移動一次我們就利用gotoxy()函式進行輸出“@”,然後在蛇尾輸出“ ”,迴圈往復就可以產生蛇移動的效果,蛇的上下左右則只需在移動一個方向的時候對單一的座標x或y進行更改,然後對更改的座標儲存進迴圈連結串列即可。移動函式則主要有up(),left()等,因為做法差不多,在此只對up()函式進行展示

程式碼如下

struct snake *up(struct snake *p) //向上移動
{

 int x;
 int y;
 x = p->pre->x;     //將蛇頭座標賦值給x,y
 y = p->pre->y;
 while(p)      //對迴圈連結串列的遍歷,即蛇的遍歷
 {
  Sleep(SNAKE_SPEED);  //蛇移動的速度
  y--;      //向上移動則只需將縱座標進行減,就可以實現蛇向上移動的效果
  gotoxy(p->x,p->y);   //定位到蛇尾,輸出“ ”即蛇尾消失
  printf(" ");
  gotoxy(x,y);    //定位到蛇頭輸出,"@",結合上面的蛇尾消失又進行蛇頭列印,產生蛇移動的效果
  printf("@");
  suicide(p,x,y);   //判斷蛇頭是否撞到蛇身
  p = p->next;    //將蛇頭的座標變為下一個
  p->pre->x = x;    //此時將前一個蛇頭變成蛇尾,通過不斷的遍歷產生不斷移動的效果
  p->pre->y = y;
  food();     //產生食物
  eat_food(p,y);   //判斷是否吃到食物
  hit_wall(y);    //判斷是否撞牆
  if(kbhit()) break;  //判斷是否有按鍵輸入,有就進行蛇移動方向的改變
 }

 return p;
}

3.產生食物food()和吃到食物eat_food()

食物和吃到食物,產生食物則採用了產生隨機數,產生一個食物的x,y座標分別存放在全域性變數food_xy[2]數組裡面,最後利用gotoxy(food_xy[0],food_xy[1])隨機產生食物
程式碼如下

void food()      //產生食物
{
 int i;
 if(!flag)      //根據flag的值來判斷地圖上是否有食物
 {
  srand( (unsigned)time( NULL ) );
  for( i = 0; i < 2; i++ ) //對food_(x,y)來隨機賦值
  {
   food_xy[i] = rand()%24+2;
   while(food_xy[0] == 1 || food_xy[0] == 25) //這兩個while為了防止食物
    food_xy[0] = rand()%24+2;    //的座標與地圖的邊緣重疊
   while(food_xy[1] >= 49 || food_xy[1] == 1)
    food_xy[1] =rand()%24+2;
  }
  gotoxy(food_xy[0],food_xy[1]); //列印食物
  printf("*");
  flag = 1;
 }
}

吃到食物eat_food(),則我們只需判斷蛇頭是否和食物的座標重疊,若重疊則表明蛇吃到了食物

程式碼如下

void eat_food(struct snake *p,int x,int y)   //蛇吃到食物,即主要是對蛇頭的x,y座標和
{              //food_xy的座標進行匹配對比,若相同即調
 if(x == food_xy[0] && y == food_xy[1])   //snake_link函式即可
 {
  p = snake_link(p);
  flag = 0;          //表明食物被吃,準備重新產生食物
  printSnake(p);
  gotoxy(8,0);
  score = score + 1;       //得分
  printf("%d",score);
 }
}

4.蛇吃到食物時產生的變長效果snake_link()函式

蛇的變長,當蛇吃到食物的時候,此時我們將食物的座標變成蛇頭,然後進行重新的列印蛇,即可以有蛇變成的效果產生,實質為對迴圈連結串列進行元素的插入。

C語言迴圈連結串列實現貪吃蛇遊戲

即通過這樣將食物的座標插進去迴圈連結串列,達到蛇變成的效果
程式碼如下

struct snake *snake_link(struct snake *p)  //蛇的連線
{
 struct snake *q;
 q = (struct snake *)malloc(sizeof(struct snake)); //即主要是實現了對迴圈連結串列的插入元素,再
 q->x = food_xy[0];        //進行列印蛇,即可有吃到食物蛇變長的結果
 q->y = food_xy[1];
 q->pre = p->pre;
 p->pre->next = q;
 p->pre = q;
 q->next = p;
 return p;
}

5.判斷蛇的死亡,分別為撞牆hit_wall()和自殺suicide()

撞牆,則只需判斷蛇頭的單一座標x軸或者y軸是否與牆壁的座標是否相等,若相等則說明蛇撞牆了
程式碼如下

void hit_wall(int n)  //判斷蛇是否撞牆,即對蛇的單一座標x或者y進行判斷,若等於牆壁的值,即遊戲結束
{
 if(ch == 'W'|| ch == 'S' )
  if(n == 1 || n == 25)    //牆壁的座標值
  {
   gotoxy(0,26);
   printf("遊戲結束!");
   printf("你的得分:%d",score);
   exit(0);
  }
 if(ch == 'A'|| ch == 'D' )
  if(n == 0 || n == 49)
  {
   gotoxy(0,score);
   exit(0);
  }
}

自殺suicide()即蛇頭是否有撞到了蛇身,做法是把蛇頭的座標拿出來,與蛇身的座標進行對比如果相等,說明蛇頭撞到了蛇身,本質上是迴圈連結串列的值進行匹配,遍歷

程式碼如下

void suicide(struct snake *p,int y) //自殺,即撞到自己本身的時候遊戲結束
{
 struct snake *q;       //把蛇頭座標傳遞進來,然後與其自己身體座標做對比若有相等則表明,蛇頭撞到了蛇身
 q = p;
 while(q != p->next)      //即對迴圈連結串列的遍歷匹配
 {
  if(p->x == x && p->y == y)
  {
   gotoxy(0,score);
   exit(0);
  }
  else
   p = p->next;
 }
}

到此蛇的基本功能已經講完,以下是全部程式碼。

全部程式碼如下

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <conio.h>
#include <time.h>
#define SNAKE_SPEED 200 //蛇移動的速度
int score = 0;   //成績得分
int flag = 0;   //用於判斷地圖上是否存在食物,0為不存在食物
int food_xy[2];   //定位食物的位置
char ch;    //用來決定蛇的移動方向
struct snake //定義一條迴圈連結串列的蛇
{
 int x;
 int y;
 struct snake *next;
 struct snake *pre;
};

void HideCursor()//把蛇移動的時候產生的游標進行隱藏,隱藏游標函式
{
 CONSOLE_CURSOR_INFO cursor;
 cursor.bVisible = FALSE;
 cursor.dwSize = sizeof(cursor);
 HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
 SetConsoleCursorInfo(handle,&cursor);
}

void gotoxy(int x,int y) //定位游標函式,用來實現蛇的移動,和食物的出現(傳送x,y可以將游標定位到x,y)
{
 HideCursor();
 COORD coord = {x,y};
 SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),coord);
}

void map() //建立蛇的地圖
{
 int a[25][50] = {0};
 int i,j;
 for(i = 0; i < 50; i++)
 {
  a[0][i] = 1;
  a[24][i] =1;
 }
 for(i = 0; i < 25; i++)
 {
  a[i][0] = 1;
  a[i][49] =1;
 }
 for(i = 0; i < 25; i++)
  for(j = 0; j < 50; j++)
  {
   if(j%50 == 0)
    printf("\n");
   if(a[i][j] == 0)
   {
    printf(" ");
   }
   else
   {
    printf("#");
   }
  }
}

struct snake *createSnake() //給蛇進行初始化,構建一條蛇,本質為迴圈連結串列
{
 int i;
 struct snake *head,*p,*q;
 p = q = (struct snake *)malloc(sizeof(struct snake));
 head = NULL;
 head = p;
 head->pre = NULL;
 for( i = 0; i < 5; i++)
 {
  p->x = 25 - i;
  p->y = 13;
  p->pre = head->pre;
  head->pre = p;
  q->next = p;
  q = p;
  p = (struct snake *)malloc(sizeof(struct snake));
 }
 q->next = head;
 return head;

}

void printSnake(struct snake *p) //列印蛇,利用gotoxy()來對蛇進行列印,只需遍歷一次迴圈連結串列即可將座標視覺化為一條蛇
{
 struct snake *q;
 q = p;
 while(q != p->next)    //迴圈連結串列的遍歷
 {
  gotoxy(p->x,p->y);   //根據座標和定位游標函式來打@,實現輸出蛇
  printf("@");
  p = p->next;
 }
 gotoxy(p->x,p->y);
 printf("@");
 gotoxy(0,0);
 printf("你的得分:");   //初始化得分
}

void food()      //產生食物
{
 int i;
 if(!flag)      //根據flag的值來判斷地圖上是否有食物
 {
  srand( (unsigned)time( NULL ) );
  for( i = 0; i < 2; i++ ) //對food_(x,y)來隨機賦值
  {
   food_xy[i] = rand()%24+2;
   while(food_xy[0] == 1 || food_xy[0] == 25) //這兩個while為了防止食物的座標與地圖的邊緣重疊
    food_xy[0] = rand()%24+2;
   while(food_xy[1] >= 49 || food_xy[1] == 1)
    food_xy[1] =rand()%24+2;
  }
  gotoxy(food_xy[0],food_xy[1]); //列印食物
  printf("*");
  flag = 1;
 }
}

struct snake *snake_link(struct snake *p)  //蛇的連線
{
 struct snake *q;
 q = (struct snake *)malloc(sizeof(struct snake)); //即主要是實現了對迴圈連結串列的插入元素,再進行列印蛇,即可有吃到食物蛇變長的結果
 q->x = food_xy[0];
 q->y = food_xy[1];
 q->pre = p->pre;
 p->pre->next = q;
 p->pre = q;
 q->next = p;
 return p;
}

void eat_food(struct snake *p,y座標和food_xy的座標進行匹配對比,若相同即呼叫snake_link函式即可
{
 if(x == food_xy[0] && y == food_xy[1])
 {
  p = snake_link(p);
  flag = 0;
  printSnake(p);
  gotoxy(8,0);
  score = score + 1;
  printf("%d",score);
 }
}

void hit_wall(int n)  //判斷蛇是否撞牆,若等於牆壁的值,即遊戲結束
{
 if(ch == 'W'|| ch == 'S' )
  if(n == 1 || n == 25)
  {
   gotoxy(0,score);
   exit(0);
  }
}


void suicide(struct snake *p,score);
   exit(0);
  }

  else
   p = p->next;
 }
}

struct snake *up(struct snake *p) //向上移動
{

 int x;
 int y;
 x = p->pre->x;     //將蛇頭座標賦值給x,即蛇的遍歷
 {

  Sleep(SNAKE_SPEED);  //蛇移動的速度
  y--;      //向上移動則只需將縱座標進行減,有就進行蛇移動方向的改變
 }

 return p;


}

struct snake *left(struct snake *p) //向左移動
{
 int x;
 int y;
 x = p->pre->x;
 y = p->pre->y;
 while(p)
 {

  Sleep(SNAKE_SPEED);
  x--;
  gotoxy(p->x,p->y);
  printf(" ");
  gotoxy(x,y);
  printf("@");
  suicide(p,y);
  p = p->next;
  p->pre->x = x;
  p->pre->y = y;
  food();
  eat_food(p,y);
  hit_wall(x);
  if(kbhit()) break;
 }
 return p;
}

struct snake *down(struct snake *p) //向下移動
{
 int x;
 int y;
 x = p->pre->x;
 y = p->pre->y;
 while(p)
 {

  Sleep(SNAKE_SPEED);
  y++;
  gotoxy(p->x,y);
  hit_wall(y);
  if(kbhit()) break;
 }
 return p;
}

struct snake *right(struct snake *p) //向右移動
{
 int x;
 int y;
 x = p->pre->x;
 y = p->pre->y;
 while(p)
 {

  Sleep(SNAKE_SPEED);
  x++;
  gotoxy(p->x,y);
  hit_wall(x);
  if(kbhit()) break;
 }
 return p;


}
void move(struct snake *p) //蛇的移動函式
{
 while(1)
 {
  ch = getch();
  switch(ch)
  {
  case 'W':p = up(p);break;
  case 'A':p = left(p);break;
  case 'D':p = right(p);break;
  case 'S':p = down(p);break;
  }
 }
}
int main()
{
 struct snake *p;
 map();  //產生地圖
 p = createSnake(); // 初始化蛇
 printSnake(p); // 列印蛇
 move(p);  //移動蛇

 return 0;
}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。