c语言链表贪吃蛇(BUG版本)

前言:贪吃蛇是第一个大作业,给自己学完c语言程序设计来练练手,在此分享思路,也请求大佬能帮忙找出BUG。 使用工具DEVEc++
bug为 蛇有一定几率吃不到果实。

一 所需要的函数(除程序设计基础外的)

①

while(kbhit())  //判断键盘有输入
    {
        ch=getch();}//使得持续等于上一个

②

#include <windows.h>
void gotoxy(int x,int y){//设置 windows函数,使得蛇可以光标移动 
	COORD pos={x,y};
	HANDLE hOut=GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleCursorPosition(hOut ,pos);
}

③

#include <time.h>
srand(time(NULL));
while(foodx<6)foodx=rand()%(115);
		while(foody<8)foody=rand()%(36);

④

   Sleep(100); //设置刷新率即蛇的移动速度

⑤

	system("pause");//暂停
	system("cls"); //清屏

在这里插入图片描述
在这里插入图片描述

二 思路

①先设置界面

 void Start(){
	
	system("mode con cols=150 Lines=50");//设置界面大小 
	int i;                               //输出初始界面 
	for(i=1;i<=20;i++) printf("\n");
	printf("%*sWell com Snake game%*s",60," ",60," ");
	for(i=1;i<=20;i++) printf("\n");
	system("pause");
	system("cls"); 
}

②初始化地图

void Map(){ //创建地图 
	int i; 
	gotoxy(125,5) ;printf("制作人:最爱舔雪糕") ;
	gotoxy(125,6) ; printf("操作 w 上") ; 
	gotoxy(125,7) ;printf("操作 s 下") ; 
	gotoxy(125,8) ; printf("操作 a 左") ; 
	gotoxy(125,9) ;printf("操作 d 右") ;
	for(i=1;i<=120;i++) { gotoxy(i,5)   ;printf("%s","█");} //上界 
	for(i=5;i<=40;i++)  { gotoxy(0,i)   ;printf("%s","█");}//左界 
    for(i=5;i<=40;i++)  { gotoxy(120,i) ;printf("%s","█");}//右界 
	for(i=1;i<=120;i++) { gotoxy(i,40)  ;printf("%s","█");}//下界 
 
}

③初始化蛇

typedef struct  Snake{
	int x;
	int y;
	struct Snake* next; 
}snake;
void newsnake(){
	int i;
	snake *temp=(snake*)malloc(sizeof(snake));
	temp->x=20;
	temp->y=30;
	temp->next=NULL;
	head=temp;//用临时变量保存头,使得头永远第一个 
	for(i=1;i<=3;i++){
		snake *p=(snake*)malloc(sizeof(snake));
		p->x=20+2*i;
		p->y=30;
		p->next=NULL;
		temp->next=p;
		temp=p;
	}
	temp=head; 

	while(temp!=NULL){ //遍历输出蛇身体 
		gotoxy(temp->x,temp->y); printf("%s","●"); 
		temp=temp->next;
	}
	
}

//链表头是蛇的尾巴,蛇的尾巴是链表头 
//使用尾插队列法 

④蛇的移动

void movesnake( ){
	while(kbhit())//键盘有输入
    {
        ch=getch();
        fflush(stdin);  //避免其他键扰乱蛇的移动 
			if (ch != 'w'  && ch != 's' &&  ch != 'a' && ch != 'd' )
				ch = direction;   
			else {               //避免蛇直接就自己吃自己 
				if (direction == 'w'&& ch == 's' )
						ch = direction;
				if (direction == 's'&&ch == 'w' )                                       
						ch = direction;
				if (direction == 'a'&& ch == 'd')
						ch = direction;
				if ( direction == 'd'&&ch == 'a')
						ch = direction;
				direction = ch;
			}
			
    }
    snake *k=NULL;
    snake *temp=(snake*)malloc(sizeof(snake));
    temp->next=NULL;
    k=head->next;
    if(grow==0){ 
        gotoxy(head->x,head->y);//没有长大就把尾巴清除
        printf("  ");   
        free(head);
       head=NULL;
        head=k; //保证链表的头是蛇的尾巴 
    } 
    
    snake *p= head;//加一个节点 ,贪吃蛇的头==链表尾巴
    while(p!=NULL&&p->next!=NULL){
        p=p->next;
    }
    
    switch(direction){//变化蛇头的位置 
    case 'w':
        temp->x=p->x;
        temp->y=p->y-1;
        break;
    case 's':
        temp->x=p->x;
        temp->y=p->y+1;
        break;
    case 'd':
        temp->x=p->x+2;
        temp->y=p->y;
        break;
    case 'a':
        temp->x=p->x-2;
        temp->y=p->y;
        break;
        }
        
        p->next=temp;
     
        gotoxy(temp->x,temp->y);//输出蛇头 
         printf("%s","●") ;
  
         grow=0;//成长归零,否则无限成长 
}

⑤设置食物

typedef struct  Foot{
	int x;
	int y;
}foot;
void updatefood(){
	
	int foody,foodx;
	snake *cry=head;
	food = (snake*)malloc(sizeof(snake));
	srand(time(NULL));
    int flagh=0;//可以使用goto或设置while循环,避免成的新食物点和蛇的位置一样 
	do{
	while(foodx<6)foodx=rand()%(115);
		while(foody<8)foody=rand()%(36);
		food->x=foodx;
		food->y=foody;
		while(cry->next!=NULL){
			if(cry->x==food->x&&cry->y==food->y){
			flagh=1;
			}
			cry=cry->next;
		               }
		           }while(flagh);
    gotoxy(food->x,food->y);
	printf("%s","●");   
	grow=1; //当grow==1时候 
}

⑥蛇吃食物的时候刷新食物

void eatfood(){
	snake *cry=head;
	while(cry->next!=NULL)
	cry=cry->next;
	if(cry->x==food->x&&cry->y==food->y){ //如果头碰到食物就再生成一个食物 
	free(food);
	updatefood();}
}

⑦判断蛇的存活

int alive(){ //判断蛇是否活着 
	snake *cry=head;
	snake *p=head;//如果碰到墙直接结束返回0 
	if(cry->x<=2||cry->y<=5||cry->y>=40||cry->x>=120) return 0;
	while(cry->next!=NULL){
	cry=cry->next;   //遍历到蛇的头 
	}
	while(p->next!=NULL){ //如果蛇的头碰到身体就 直接结束返回0 
		if(p->x==cry->x&&p->y==cry->y) return 0;
		p=p->next;
	}
	return 1;// 如果都没碰到,证明或者返回1 
}

以下为源代码

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

void Start();
void Map();
void gotoxy(int x,int y);
void newsnake();
void run();
void eatfood();
void movesnake();
void updatefood();
 char direction='d';
 char ch='d';
 int grow=0;
 int alive();

typedef struct  Snake{
	int x;
	int y;
	struct Snake* next; 
}snake;

snake *head=NULL; 
snake *food=NULL;//头 
//enum {UP=72,DOWN=80,LEFT=75,RIGHT=77};

typedef struct  Foot{
	int x;
	int y;
}foot;


int main(){
	Start();//初始化界面 
    Map();//打印地图 
    newsnake();
    updatefood();
    while(1){
       eatfood();
       movesnake();
       Sleep(100);
       if(!alive()) break;//判断蛇的存活 
             }
    printf("别玩了太菜了\n");
   	system("pause");
	return 0;
}
void Start(){
	
	system("mode con cols=150 Lines=50");//设置界面大小 
	int i;                               //输出初始界面 
	for(i=1;i<=20;i++) printf("\n");
	printf("%*sWell com Snake game%*s",60," ",60," ");
	for(i=1;i<=20;i++) printf("\n");
	system("pause");
	system("cls"); 
}
void Map(){ //创建地图 
	int i; 
	gotoxy(125,5) ;printf("制作人:最爱舔雪糕") ;
	gotoxy(125,6) ; printf("操作 w 上") ; 
	gotoxy(125,7) ;printf("操作 s 下") ; 
	gotoxy(125,8) ; printf("操作 a 左") ; 
	gotoxy(125,9) ;printf("操作 d 右") ;
	for(i=1;i<=120;i++) { gotoxy(i,5)   ;printf("%s","█");} //上界 
	for(i=5;i<=40;i++)  { gotoxy(0,i)   ;printf("%s","█");}//左界 
    for(i=5;i<=40;i++)  { gotoxy(120,i) ;printf("%s","█");}//右界 
	for(i=1;i<=120;i++) { gotoxy(i,40)  ;printf("%s","█");}//下界 
 
}
void gotoxy(int x,int y){//设置 windows函数,使得蛇可以光标移动 
	COORD pos={x,y};
	HANDLE hOut=GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleCursorPosition(hOut ,pos);
}
void newsnake(){
	int i;
	snake *temp=(snake*)malloc(sizeof(snake));
	temp->x=20;
	temp->y=30;
	temp->next=NULL;
	head=temp;//用临时变量保存头,使得头永远第一个 
	for(i=1;i<=3;i++){
		snake *p=(snake*)malloc(sizeof(snake));
		p->x=20+2*i;
		p->y=30;
		p->next=NULL;
		temp->next=p;
		temp=p;
	}
	temp=head; 
	while(temp!=NULL){ //遍历输出蛇身体 
		gotoxy(temp->x,temp->y); 
		printf("%s","●"); 
		temp=temp->next;
	}
	
}

//链表头是蛇的尾巴,蛇的尾巴是链表头 
//使用尾插队列法 
void movesnake( ){
	while(kbhit())//键盘有输入
    {
        ch=getch();
        fflush(stdin);  //避免其他键扰乱蛇的移动 
			if (ch != 'w'  && ch != 's' &&  ch != 'a' && ch != 'd' )
				ch = direction;   
			else {               //避免蛇直接就自己吃自己 
				if (direction == 'w'&& ch == 's' )
						ch = direction;
				if (direction == 's'&&ch == 'w' )                                       
						ch = direction;
				if (direction == 'a'&& ch == 'd')
						ch = direction;
				if ( direction == 'd'&&ch == 'a')
						ch = direction;
				direction = ch;
			}
			
    }
    snake *k=NULL;
    snake *temp=(snake*)malloc(sizeof(snake));
    temp->next=NULL;
    k=head->next;
    if(grow==0){ 
        gotoxy(head->x,head->y);//没有长大就把尾巴清除
        printf("  ");   
        free(head);
        head=NULL;
        head=k; //保证链表的头是蛇的尾巴 
    } 
    
    snake *p= head;//加一个节点 ,贪吃蛇的头==链表尾巴
    while(p!=NULL&&p->next!=NULL){
        p=p->next;
    }
    
    switch(direction){//变化蛇头的位置 
    case 'w':
        temp->x=p->x;
        temp->y=p->y-1;
        break;
    case 's':
        temp->x=p->x;
        temp->y=p->y+1;
        break;
    case 'd':
        temp->x=p->x+2;
        temp->y=p->y;
        break;
    case 'a':
        temp->x=p->x-2;
        temp->y=p->y;
        break;
        }
        
        p->next=temp;
     
        gotoxy(temp->x,temp->y);//输出蛇头 
        printf("%s","●") ;
  
        grow=0;//成长归零,否则无限成长 
}
void updatefood(){
	
	int foody,foodx;
	snake *cry=head;
	food = (snake*)malloc(sizeof(snake));
	srand(time(NULL));
    int flagh=0;//可以使用goto或设置while循环,避免成的新食物点和蛇的位置一样 
	do{
	while(foodx<6)foodx=rand()%(115);
		while(foody<8)foody=rand()%(36);
		food->x=foodx;
		food->y=foody;
		while(cry->next!=NULL){
			if(cry->x==food->x&&cry->y==food->y){
			flagh=1;
			}
			cry=cry->next;
		               }
		           }while(flagh);
    gotoxy(food->x,food->y);
	printf("%s","●");   
	grow=1; //当grow==1时候 
}
void eatfood(){
	snake *cry=head;
	while(cry->next!=NULL)
	cry=cry->next;
	if(cry->x==food->x&&cry->y==food->y){ //如果头碰到食物就再生成一个食物 
	free(food);
	updatefood();}
}
int alive(){ //判断蛇是否活着 
	snake *cry=head;
	snake *p=head;//如果碰到墙直接结束返回0 
	if(cry->x<=2||cry->y<=5||cry->y>=40||cry->x>=120) return 0;
	while(cry->next!=NULL){
	cry=cry->next;   //遍历到蛇的头 
	}
	while(p->next!=NULL){ //如果蛇的头碰到身体就 直接结束返回0 
		if(p->x==cry->x&&p->y==cry->y) return 0;
		p=p->next;
	}
	return 1;// 如果都没碰到,证明或者返回1 
}

更多推荐