總體思想
利用回圈鏈表將一條蛇的坐標進行存盤,然后利用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,x,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()函式
蛇的變長,當蛇吃到食物的時候,此時我們將食物的坐標變成蛇頭,然后進行重新的列印蛇,即可以有蛇變成的效果產生,實質為對回圈鏈表進行元素的插入,

即通過這樣將食物的坐標插進去回圈鏈表,達到蛇變成的效果
代碼如下
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,26);
printf("游戲結束!");
printf("你的得分:%d",score);
exit(0);
}
}
自殺suicide()即蛇頭是否有撞到了蛇身,做法是把蛇頭的坐標拿出來,與蛇身的坐標進行對比如果相等,說明蛇頭撞到了蛇身,本質上是回圈鏈表的值進行匹配,遍歷
代碼如下
void suicide(struct snake *p, int x, int y) //自殺,即撞到自己本身的時候游戲結束
{
struct snake *q; //把蛇頭坐標傳遞進來,然后與其自己身體坐標做對比若有相等則表明,蛇頭撞到了蛇身
q = p;
while(q != p->next) //即對回圈鏈表的遍歷匹配
{
if(p->x == x && p->y == y)
{
gotoxy(0,26);
printf("游戲結束!");
printf("你的得分:%d",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,int x, int y) //蛇吃到食物,即主要是對蛇頭的x,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) //判斷蛇是否撞墻,即對蛇的單一坐標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,26);
printf("游戲結束!");
printf("你的得分:%d",score);
exit(0);
}
}
void suicide(struct snake *p, int x, int y) //自殺,即撞到自己本身的時候游戲結束
{
struct snake *q; //把蛇頭坐標傳遞進來,然后與其自己身體坐標做對比若有相等則表明,蛇頭撞到了蛇身
q = p;
while(q != p->next) //即對回圈鏈表的遍歷匹配
{
if(p->x == x && p->y == y)
{
gotoxy(0,26);
printf("游戲結束!");
printf("你的得分:%d",score);
exit(0);
}
else
p = p->next;
}
}
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,x,y); //判斷是否吃到食物
hit_wall(y); //判斷是否撞墻
if(kbhit()) break; //判斷是否有按鍵輸入,有就進行蛇移動方向的改變
}
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,x,y);
p = p->next;
p->pre->x = x;
p->pre->y = y;
food();
eat_food(p,x,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,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,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,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,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;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/206312.html
標籤:其他
上一篇:Java學習筆記_06 回圈結構
下一篇:SDL嵌入qt視窗繪制圖片
