贪吃蛇(c语言)

贪吃蛇

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

#define U 1
#define D 2
#define L 3
#define R 4

void file_out(); 
void tips();
void printscore();
void createfood();

/***********************
@func: 蛇的每个节点 
***********************/
typedef struct snake{
    
    
	int x;
	int y;
	struct snake * next;
}snake;

/***********************
@func: 食物的位置信息
***********************/ 
typedef struct foodtype{
    
    
	int x;
	int y;
}foodtype;


int       score = 0;      // 总得分 
int       add   = 10;     // 每次增加的分数
int       HighScore = 0;  // 最高分
int       status=R;       // 蛇前进的状态
int       sleeptime = 150;// 每次运行的时间间隔,控制速度 
snake     * head;         // 蛇头
foodtype  * food;         // 食物
snake     * q;            // 遍历蛇时使用的指针
int       gameover=0;  // 游戏结束的状态, 撞墙, 咬到自己,主动退出游戏
HANDLE    hOut;           // 控制台句柄 



/* 黑色 0   深蓝 1   深绿 2    深蓝绿 3   深红 4    紫 5     暗绿 6     
   白 7     灰 8     亮蓝 9    亮绿 10    亮蓝绿 11  红12    粉   13
   黄 14    亮白 15 
*/

/*******************
@func:设置控制台的颜色 
@param bg: 背景色
@param fg: 前景色 
*******************/
void color(unsigned char bg, unsigned char fg){
    
    
	WORD wColor = ((bg & 0x0F)<<4 + (fg & 0x0F)); 
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),wColor);
} 

/************************
@func: 设置文字颜色 
************************/
void textcolor(char fg){
    
    
	// 恢复原有颜色 
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED |
									FOREGROUND_GREEN |
									FOREGROUND_BLUE);   
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),fg);
} 

/*******************
@func:设置光标的位置 
@param x
@param y
*******************/
void gotoxy(int x,int y){
    
    
	COORD c;
	c.X = x;
	c.Y = y;
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),c);
}

/*******************
@func:不显示控制台光标 
*******************/
void close_cur(){
    
    
	hOut=GetStdHandle(STD_OUTPUT_HANDLE);  //获得输出句柄 
	CONSOLE_CURSOR_INFO CursorInfo;
	GetConsoleCursorInfo(hOut,&CursorInfo);//获取控制台光标信息
	CursorInfo.bVisible=0;                 //隐藏控制台光标
	SetConsoleCursorInfo(hOut,&CursorInfo);//设置控制台光标状态
}

/*******************
@func: 创建游戏地图 
0 2            56 (58 59)  // 每个块的w: 2个字符,h: 一个字符 
1


25
(26) 
*******************/
void createmap(){
    
    
	int i,j;
	color(5,0);// 深紫色边框 
	gotoxy(0,0);
	for(i =0;i<60;i++) printf(" "); //绘制上边框
	gotoxy(0,26);
	for(i =0;i<60;i++) printf(" "); //绘制下边框

	for(i = 1;i<26;i++) {
    
               //绘制左右边框 
		gotoxy(0,i);
		printf("  ");
		gotoxy(58,i);
		printf("  ");
	}
	color(3,0);
	for(i=2;i<57;i+=2){
    
         //x : 2 4 6 ... 56 
		for(j=1;j<26;j++){
    
      //y : 1 2 3 ... 25
			gotoxy(i,j);
			printf("  ");
		} 
	}
	tips();
} 

/**************************
@func: 游戏界面右侧的得分和小提示 
**************************/ 
void tips(){
    
    
	gotoxy(70,4);
	textcolor(11);
	printf("最高记录: %d", HighScore);
	textcolor(13);
	gotoxy(75,11);
	printf("小提示");
	gotoxy(62,13);
	textcolor(6);
	printf("++------------------------------++");
	gotoxy(62,25);
	printf("++------------------------------++");
	textcolor(3);
	gotoxy(66,14);
	printf("每个食物的得分: %d分",add);
	gotoxy(66,16);
	printf("不能撞墙,不能咬到自己");
	gotoxy(66,18);
	printf("用 ↑↓← →分别控制移动");
	gotoxy(66,20);
	printf("F1: 加速   F2: 减速");
	gotoxy(66,22);
	printf("space: 暂停游戏");
	gotoxy(66,24);
	printf("esc:   退出游戏"); 
	printscore();
} 

/*******************
@func: 绘制得分
*******************/
void printscore(){
    
    
	gotoxy(72,6);
	textcolor(14);
	printf("得分: %d",score);
}

/********************
@func: 从save.txt中读取最高分 
********************/
void file_out(){
    
    
	FILE*fp;
	fp = fopen("save.txt","a+");
	fscanf(fp,"%d",&HighScore);
	fclose(fp);  
} 

/****************************
@func: 初始化蛇, 蛇的尾部坐标为: 24,5 
****************************/ 
void initsnake(){
    
    
	snake * tail;
	int i;
	tail = (snake*)malloc(sizeof(snake)); // 动态内存分配
	tail->x = 24;
	tail->y = 5;
	tail->next = NULL; 
	for(i = 1;i<=4;i++){
    
    
		head = (snake*)malloc(sizeof(snake));
		head->next = tail;
		head->x = 24+2*i;
		head->y = 5;
		tail = head;
	} 
	while(tail!=NULL){
    
    
		gotoxy(tail->x, tail->y);
		color(14,0);
		printf("  ");
		tail=tail->next;
	}
	createfood();
}

/***************
@func: 随机出现食物
1. 食物不能和蛇身重合 
2. 食物的x值坐标要为 偶数
3. 食物要在边界内 
***************/
void createfood(){
    
    
	int ifok=0,x=0,y=0;
	while(!ifok){
    
    
		x= (rand()%28+1)*2;  // 为偶数 
		y= rand()%25 + 1  ; 
		q= head;
		while(q->next!=NULL){
    
    
			if(q->x==x && q->y ==y) break;// 判断蛇身是否和食物重合
			q = q->next;
		}
		if(q->next==NULL) ifok=1;
	}
	gotoxy(x,y);
	food->x = x;
	food->y = y;
	color(12,0);
	printf("  ");
} 

/*****************
@func: 判断是否咬到自己  
蛇头的坐标值和蛇身上的任意坐标值重合 
*****************/ 
int biteself(){
    
    
	q = head->next; 
	while(q!=NULL){
    
    
		if(q->x==head->x && q->y==head->y){
    
    
			return 1;
		}
		q= q->next;
	}
	return 0;
}

/**********************
@func: 撞墙的情况 
**********************/
int cantcrosswall(){
    
    
	if(head->x <2||head->x>56|| head->y<1||head->y>25){
    
    
		return 1;  
	}
	return 0;
} 

/**************
@func: 蛇加速前进
两种情况蛇会加速前进: 蛇吃到食物 和按<F1>键
加速时时 间间隔减少10 得分加2 
***************/
void speedup(){
    
    
	if(sleeptime>=50){
    
    
		sleeptime= sleeptime-10;
		add = add+2;
	}
} 

/*****************
@func: <F2> 蛇减速前进
时间间隔 加 10 , 得分值 比之间减少 2分
得分值 最少为 1
*****************/ 
void speeddown(){
    
    
	if(sleeptime<200){
    
    
		sleeptime += 10;
		add -= 2;
		if(add<1)  add = 1;
	}
}

/***********************
@func: 吃到了食物,移动后最后一块不擦除 
***********************/
void eatfood(snake*head){
    
    
	while(head!=NULL){
    
    
		gotoxy(head->x, head->y);
		color(14,0);
		printf("  ");
		head= head->next;
	}
	score += add;
	speedup();
	createfood();
}

/**************************
@func: 没有吃到食物,移动后最后一块要擦除 
**************************/ 
void donteatfood(snake*head){
    
    
	while(head->next->next!=NULL){
    
     
		gotoxy(head->x,head->y);
		color(14,0);
		printf("  ");
		head= head->next;
	}
	//擦除最后一块 
	gotoxy(head->next->x, head->next->y);
	color(3,0);
	printf("  ");
	free(head->next); // 释放原本最后一位的指针
	head->next = NULL; 
} 

/*********************
@func: 控制移动 
**********************/
void snakemove(){
    
    
	snake* nexthead;
	nexthead = (snake*)malloc(sizeof(snake));
	nexthead->next = head;
	if(status==U){
    
    
		nexthead->x = head->x;
		nexthead->y = head->y-1;
	}else if(status==D){
    
    
		nexthead->x = head->x;
		nexthead->y = head->y+1;
	}else if(status==R){
    
    
		nexthead->x = head->x+2;
		nexthead->y = head->y;
	}else if(status==L){
    
    
		nexthead->x = head->x-2;
		nexthead->y = head->y;
	}
	
    if(nexthead->x == food->x && nexthead->y == food->y){
    
    // 下一个位置上有食物 
		eatfood(nexthead);
		printscore(); 
	}
	else{
    
    
		donteatfood(nexthead);
	}
	
	head = nexthead;
	
	if(cantcrosswall()){
    
    
		gameover = 1;
	}
	
	if(biteself()==1){
    
      // 判断是否咬到自己 
		gameover = 2; 
	}
}
/*********************
@func:键盘按键控制,蛇头不能转向与前进方向相反的方向 
*********************/
void keyboardControl(){
    
     
	while(!gameover){
    
    
		if(GetAsyncKeyState(VK_UP)&0x8000 &&status!=D){
    
    
			status = U;
		}
		if(GetAsyncKeyState(VK_DOWN)&0x8000&&status!=U){
    
    
			status = D;
		}
		if(GetAsyncKeyState(VK_LEFT)&0x8000&&status!=R){
    
    
			status = L;
		}
		if(GetAsyncKeyState(VK_RIGHT)&0x8000&&status!=L){
    
    
			status = R;
		}
		if(GetAsyncKeyState(VK_SPACE)&0x8000){
    
    
			while(1){
    
    
				Sleep(300);
				if(GetAsyncKeyState(VK_SPACE)&0x8000){
    
    
					break;
				}
			}
		}
		if(GetAsyncKeyState(VK_ESCAPE)&0x8000){
    
    
			gameover = 3;
		}
		if(GetAsyncKeyState(VK_F1)&0x8000){
    
    
			speedup();
		}
		if(GetAsyncKeyState(VK_F2)&0x8000){
    
    
			speeddown();
		} 
		
		Sleep(sleeptime);

		snakemove();
		
	}
} 

/******************
@func: 存储最高分 
*******************/ 
void file_in(){
    
    
	FILE*fp;
	fp = fopen("save.txt","w+");
	fprintf(fp,"%d",score);
	fclose(fp);
}

/**********************
@func: 游戏结束 
**********************/
void endgame(){
    
    
	int i,j;
	textcolor(4);
	system("cls");
	gotoxy(30,5);
	for(i=0;i<40;i++) printf("+");
	gotoxy(30,20);	
	for(i=0;i<40;i++) printf("+");
	for(i=6;i<20;i++){
    
    
		gotoxy(30,i);
		printf("+");
		gotoxy(69,i);
		printf("+");
	}
	textcolor(15);
	gotoxy(45,8);
	printf("游戏结束!");			
	if(gameover==1){
    
    
		gotoxy(43,10);
		printf("您因撞墙而死!!");
	}else{
    
    
		gotoxy(41,10);
		printf("您因咬到自己而死!!");
	}
	gotoxy(45,12);
	printf("得分: %d",score); 
	if(score>HighScore){
    
    
		gotoxy(42,14);
		printf("您已创新的记录!");
		file_in();
	}else{
    
    
		gotoxy(40,14);
		printf("您距离最高记录还差:%d分",HighScore-score);
	}
}


int main(){
    
    
	close_cur();
	srand((unsigned int)time(NULL));
	food = (foodtype*)malloc(sizeof(foodtype));
	system("mode con cols=98 lines=27");
	file_out();
	createmap();
	initsnake();
	keyboardControl();
	endgame();
	system("pause >nul");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/first_bug/article/details/122750028