說明 上個學期暑假心血來潮,查了比較多的資料,寫了一個星期寫的貪吃蛇代碼,bug還有,開始游戲不能按空格,你按啥鍵開始都行,就是不能按空格,參考了C語言網的貪吃蛇,所以很像,裡面的代碼有參考,但是全是重新寫的,沒有直接照抄,不然也不會有bug了對不對 代碼裡面有我寫的註釋,應該可以看懂 貪吃蛇通過鏈 ...
說明
上個學期暑假心血來潮,查了比較多的資料,寫了一個星期寫的貪吃蛇代碼,bug還有,開始游戲不能按空格,你按啥鍵開始都行,就是不能按空格,參考了C語言網的貪吃蛇,所以很像,裡面的代碼有參考,但是全是重新寫的,沒有直接照抄,不然也不會有bug了對不對
代碼裡面有我寫的註釋,應該可以看懂
貪吃蛇通過鏈表實現你可以前往我的github下載此代碼,VC++6.0和VS2017均可通過編譯
效果圖
代碼
#include "stdio.h"
#include "stdlib.h"
#include "windows.h"//包含Sleep函數,來控制運行速度
#include "conio.h"//測試時用到了getch()來獲取按鍵,最後完成改了獲取方式沒用到,不過還是放著吧
#include "time.h"//設置食物時隨機生成坐標用到time做種子
typedef struct SNAKE//包含坐標及尾指針,為什麼用typedef因為可以直接snake定義指針,方便
{
int x;
int y;
struct SNAKE *next;
}snake;//typedef的用法http://blog.csdn.net/wangqiulin123456/article/details/8284939
void POS();//移動游標函數
void StayAwayFromWall();//判斷撞牆函數
void DonnotBiteYouself();//判斷咬到自己的函數
void drawmap();//畫地圖函數
void initsnake();//初始化蛇函數
void createfood();//創建食物函數
void gamecircle();//游戲移動迴圈函數
void move();//移動函數
void pause();//暫停函數
void welcome();//歡迎界面
void game();//游戲界面
snake *head,*end;//定義蛇頭、蛇尾
snake *p;//移動時用到的遍歷蛇的指針
int i,speed=300;//迴圈變數i、速度
int levelup,score=0;//達到一定分數變快、分數
int foodx,foody;//食物的(x,y)坐標
char key;//定義按鍵獲取
int main()
{
welcome();
game();
getch();
return 0;
}
void POS(int x,int y)//設置游標位置,參考網址https://baike.so.com/doc/1283395-1357065.html
{
COORD pos;
HANDLE output;
pos.X=x;
pos.Y=y;
output=GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(output,pos);
}
void StayAwayFromWall()
{
if (head->x==0||head->x==58||head->y==0||head->y==29)
{
POS(28,14);
printf("游戲結束你撞牆了\n");
POS(28,15);
system("pause");
exit(0);
}
}
void DonnotBiteYouself()
{
while(p->next!=NULL)
{
p=p->next;
if (head->x==p->x&&head->y==p->y)
{
POS(28,14);
printf("游戲結束你咬到自己了\n");
POS(28,15);
system("pause");
exit(0);
}
}
}
void drawmap()//畫棋盤
{
for(i=0;i<60;i+=2)//列印上下邊框
{
POS(i,0);
printf("■");
POS(i,28);
printf("■");
}
for(i=1;i<28;i++)//列印左右邊框
{
POS(0,i);
printf("■");
POS(58,i);
printf("■");
}
}
void initsnake()//初始化蛇身
{
end=(snake*)malloc(sizeof(snake));
end->x=28;
end->y=14;
end->next=NULL;
for (i=1;i<=3;i++)
{
head=(snake*)malloc(sizeof(snake));
head->next=end;
head->x=28+2*i;
head->y=15;
end=head;
}
while (end->next!=NULL)
{
POS(end->x,end->y);
printf("■");
end=end->next;
}
}
void createfood()
{
srand(time(0));//配合rand使用
flag:
while(1)//由於food的x坐標必須為偶數,所以設置迴圈判斷是否為偶數
{
foody=rand()%27+1;//先生成y坐標,不能先生成x,x有判斷,先生成x會退出while不生成y
foodx=rand()%55+2;//rand產生範圍數公式rand()%(m-n+1)+n……其中n<=要生成數的範圍<=m
if (foodx%2==0)
{
break;
}
}
p=head;
while(1)
{
if(p->x==foodx&&p->y==foody)//若生成坐標和蛇重疊了,回到生成坐標迴圈
{
goto flag;
}
if(p->next==NULL)
{
break;
}
p=p->next;
}
POS(foodx,foody);
printf("■");
}
void gamecircle()//游戲迴圈,包含移動,暫停功能
{
key='d';
while (1)
{
if (GetAsyncKeyState(VK_UP)&&key!='s')
{
key='w';
}
else if (GetAsyncKeyState(VK_DOWN)&&key!='w')
{
key='s';
}
else if (GetAsyncKeyState(VK_RIGHT)&&key!='a')
{
key='d';
}
else if (GetAsyncKeyState(VK_LEFT)&&key!='d')
{
key='a';
}
else if (GetAsyncKeyState(VK_SPACE))
{
pause();
}
if (score==levelup&&speed>=10)//判斷成績,每累積30分速度變快
{
speed-=10;
levelup+=30;
POS(75,12);
printf("當前速度:每隔%d毫秒移動向前移動",speed);
}
move();
}
}
void move()//移動函數,上下左右箭頭操作,w前s後a左d右(符號說明),函數包含吃食物計分功能
{
StayAwayFromWall();
DonnotBiteYouself();
p=(snake*)malloc(sizeof(snake));
switch(key)
{
case 'd':
{
p->next=head;
p->x=head->x+2;
p->y=head->y;
POS(p->x,p->y);
printf("■");
head=p;
Sleep(speed);
if (p->x==foodx&&p->y==foody)
{
createfood();
score+=10;
POS(75,11);
printf("得分:%d",score);
break;
}
while(p->next->next!=NULL)
{
p=p->next;
if(p->next->next==NULL)
{
POS(p->x,p->y);
printf(" ");
free(p->next);
p->next=NULL;
p=head;
break;
}
}
break;
}
case 'w':
{
p->next=head;
p->x=head->x;
p->y=head->y-1;
POS(p->x,p->y);
printf("■");
head=p;
Sleep(speed);
if (p->x==foodx&&p->y==foody)
{
createfood();
score+=10;
POS(75,11);
printf("得分:%d",score);
break;
}
while(p->next->next!=NULL)
{
p=p->next;
if(p->next->next==NULL)
{
POS(p->x,p->y);
printf(" ");
free(p->next);
p->next=NULL;
p=head;
break;
}
}
break;
}
case 's':
{
p->next=head;
p->x=head->x;
p->y=head->y+1;
POS(p->x,p->y);
printf("■");
head=p;
Sleep(speed);
if (p->x==foodx&&p->y==foody)
{
createfood();
score+=10;
POS(75,11);
printf("得分:%d",score);
break;
}
while(p->next->next!=NULL)
{
p=p->next;
if(p->next->next==NULL)
{
POS(p->x,p->y);
printf(" ");
free(p->next);
p->next=NULL;
p=head;
break;
}
}
break;
}
case 'a':
{
p->next=head;
p->x=head->x-2;
p->y=head->y;
POS(p->x,p->y);
printf("■");
head=p;
Sleep(speed);
if (p->x==foodx&&p->y==foody)
{
createfood();
score+=10;
POS(75,11);
printf("得分:%d",score);
break;
}
while(p->next->next!=NULL)
{
p=p->next;
if(p->next->next==NULL)
{
POS(p->x,p->y);
printf(" ");
free(p->next);
p->next=NULL;
p=head;
break;
}
}
break;
}
}
}
void pause()//暫停函數,bug:暫停之後會出現蛇短一格。。繼續蛇身恢復正常,不會解決
{
do//額外增加的語句,解決上面說的bug,不知道暫停次數多了會不會崩潰,錶面上問題是解決了的
{
p=p->next;
}while(p->next!=NULL);
POS(p->x,p->y);
printf("■");
while(1)//暫停語句
{
Sleep(100);
if (GetAsyncKeyState(VK_SPACE))
{
break;
}
}//不能用system("pause");會出現按任意鍵繼續字樣
POS(p->x,p->y);
printf(" ");
}
void welcome()
{
POS(28,10);
printf("歡迎來到貪吃蛇");
POS(28,11);
printf("游戲規則:");
POS(28,12);
printf("1、不能撞牆");
POS(28,13);
printf("2、不能撞自己");
POS(28,14);
printf("3、空格可以暫停,再次按下繼續游戲");
POS(28,15);
printf("4、要玩的開心");
POS(28,16);
printf("5、別按空格開始游戲!!!你按別的鍵都可以繼續,就是別按空格");
POS(28,17);
printf("作者:屈振宇");
POS(28,18);
printf("別問我為什麼和c語言網上的貪吃蛇那麼像");
POS(28,19);
printf("因為結構體和地圖包括坐標的使用都是參照他做的");
POS(28,20);
system("pause");
system("cls");
}
void game()
{
drawmap();
initsnake();
createfood();
POS(75,11);
printf("得分:%d",score);
POS(75,12);
printf("當前移動速度:每隔%d毫秒移動向前移動",speed);
POS(75,13);
printf("每獲得30分速度會加快");
POS(75,14);
printf("不能撞牆不能撞自己");
POS(75,15);
printf("按空格可以暫停……");
gamecircle();
}