C语言贪吃蛇小游戏简化版(windows)

1.确定游戏大体内容

              我设置的贪吃蛇小游戏基本规则:

               用↑,↓,←,→来控制蛇的移动,f3加速(能量>=3),f4减速,不能撞墙,不能咬到自己,能量大于等于3即可加速;

               空格暂停游戏,再按空格继续游戏,Esc键正常退出游戏;

              一共有两种食物,蛇吃到一种食物就蛇身就增加一个节点,更新分数能量。

              记录获得分数,能量多少。

2.游戏初始化界面

             1.设置窗口大小:我设置的窗口行数30,列数100:
system("mode con cols=100 lines=30");
            2.设置更改窗口名:
system("title 贪吃蛇"); 
           3:初始化界面前,我先进行了隐藏控制台的光标(不然一直闪影响体验);

              然后弄一个将控制台光标弄到指定位置的函数,方便打印(可以将光标跳到控制台任意位置),

              然后再弄一个宽字符的打印(蛇身,墙体等)(普通字符占一个字节,而有些字符占两个字节)(所以需要)

               用到的头文件及一些定义:

#include<stdio.h>
#include<stdlib.h>
#include<Windows.h>
#include<stdbool.h>
#include<locale.h>
#include<time.h>
#define KEY_PRESS(VK) ((GetAsyncKeyState(VK)&1)==1?1:0)
#define POS_X 24  //初始位置
#define POS_Y 5
#define WALL  L'□'  //墙
#define BODY  L'●'    //蛇的身体
#define FOOD  L'★'    // 蛇的食物1
#define  FOOD2  L'$'     //蛇的食物2

           3.1:隐藏控制台光标: 

​
HANDLE houtput=GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO CursorInfo;
GetConsoleCursorInfo(houtput, &CursorInfo);//获取控制台光标
CursorInfo.bVisible = false;
SetConsoleCursorInfo(houtput, &CursorInfo);

​

               3.2:将控制台光标弄到指定位置的函数:

void set_pos(short x, short y) {
	HANDLE houtput = NULL;
	houtput = GetStdHandle(STD_OUTPUT_HANDLE);                   //获取标准输出色被的句柄
	COORD pos = { x,y };                                          //定位光标位置
	SetConsoleCursorPosition(houtput, pos);
}

           3.3宽字符的打印

         需要在开头有:

setlocale(LC_ALL, "");    //切换到本地环境

然后就可以直接使用wprintf打印宽字符了;egg:   wprintf(L"lc",●);别忘了加L;

      4.初始化界面:

     欢迎界面函数:system("cls")用来清理屏幕;system("pause")可以定格,按任意键继续。

WelcomeToGame() {
	set_pos(40, 17); wprintf(L"欢迎来到贪吃蛇小游戏"); 
	set_pos(42, 20); system("pause");
	system("cls");
	set_pos(40, 17); wprintf(L"用↑,↓,←,→来控制蛇的移动,f3加速,f4减速");
	set_pos(40, 18); wprintf(L"加速能更快的得到分数");
	set_pos(42, 20); system("pause");
	system("cls");
}

     5.打印地图

打印蛇能活动的范围地图;这里我打印了58*26的大小;一个蛇的节点宽2字节   高1字节;我在开头定义了  #define    WALL    L'□' 

#define WALL  L'□'  //墙
void  CreatMap() {
	int i; 
	 //up
	set_pos(0, 1); for (i = 0; i < 58; i++)wprintf(L"%lc",WALL);
	 //down
	set_pos(0, 26); for (i = 0; i < 58; i++)wprintf(L"%lc",WALL);
	 //left
	for (i = 1; i <= 26; i++) { set_pos(0, i); wprintf(L"%lc",WALL); }
	 //right
	for (i = 1; i <= 26; i++) { set_pos(58, i); wprintf(L"%lc",WALL); }

}

      6.创建并初始化我们的蛇

#define WALL  L'□'  //墙
#define BODY  L'●'    //蛇的身体
#define FOOD  L'★'    // 蛇的食物1
#define  FOOD2  L'$'     //蛇的食物2
enum DIRECTION {
	UP = 1,
    DOWN ,
   LEFT ,
   RIGHT 
};                                      //枚举蛇的方向
enum GAME_STATUS{
	OK,    
	KILL_BY_WALL,
	KILL_BY_SELE,//正常,撞墙,撞到自己,正常退出//蛇的状态
	END_NORMAL
};                                      //枚举蛇的状态(游戏状态)
typedef struct SnackNode {
	int x; int y;
	struct SnackNode* next;   
}SnackNode,*pSnackNode;                //蛇的单节点,节点位置,和下一节点地址

typedef struct Snack {
	pSnackNode PSnack;              //蛇头
	pSnackNode fFood;               //存放蛇食物1的节点
	pSnackNode  fFOOD2;             //存放蛇食物2的节点
	enum DIRECTION dir;             //蛇的方向
	enum GAME_STATUS status;         //游戏状态                
		int energe;                   //蛇的neng能量
		int sum;                       //吃掉的食物个数存储
		int score;                     //总成绩
		int sleep_time;                //休息时间,小速度大,反比;蛇的速度
}Snack,*pSnack;

      蛇的初始化函数:(在开头定义了             #define POS_X 24  #define POS_Y 5)(方便修改初始位置)

#define POS_X 24  //初始位置
#define POS_Y 5
void InitSnake(pSnack ps) {
	int i = 0; pSnackNode cur = NULL;
	for (i = 0; i < 5; i++) {
		cur = (pSnackNode)malloc(sizeof(SnackNode));
		if (cur == NULL) {
			perror("InitSnack()::malloc()");
			return;
		}
		cur->next = NULL;
		cur->x = POS_X + i;                   
		cur->y = POS_Y ;                     //头插法插入节点,默认初始蛇的节点有五个
		if (ps->PSnack == NULL) {
			ps->PSnack = cur;
		}
		else {
			cur->next = ps->PSnack;
			ps->PSnack = cur;
		}
	}
	cur = ps->PSnack;
	while (cur) {
		set_pos(cur->x, cur->y);
		wprintf(L"%lc",BODY);
		cur = cur->next;
	}
	//设置贪吃蛇的属性
	ps->dir = RIGHT;             //默认初始方向向右
	ps->sum=0;                       
	ps->energe = 6;
	ps->score = 0;
	ps->status = OK;
	ps->sleep_time = 200;         
}

7.蛇的移动函数实现(逐帧)

int NextIsFood(pSnackNode pn,pSnack ps) {
	if (pn->x == ps->fFood->x && pn->y == ps->fFood->y)return 1;
	if (pn->x == ps->fFOOD2->x && pn->y == ps->fFOOD2->y)return 2;
	return 0;   
        //判断下一步即将到达的节点是否是蛇存储的食物节点1或2的位置,还是无食物节点
}





///

void Food_Creat(pSnack ps) {                
	int x=0, y=0;                      //食物节点1的创建
again:                                        
	do {
		x = rand() % 53 + 2;
		y = rand() % 24 + 2; 
	} while (x % 2 != 0 );             //蛇的宽度为2;位置x轴必须偶数
		                                       
	pSnackNode cur; cur = ps->PSnack;    //判断食物节点是否与蛇重合;且蛇食物2节点存在,生成 
                                         //食物节点一不能与之重合
	while (cur) {
		if (ps->fFOOD2 == NULL) { if (cur->x ==x && cur->y == y) goto again; } 
		else {
			if((cur->x == x && cur->y == y) || (cur->next == ps->fFOOD2->x && cur->y == ps->fFOOD2->y))goto again;
		}cur = cur->next;
	}
	pSnackNode Food_snack = (pSnackNode)malloc(sizeof(SnackNode));  //创建食物1节点
	if (Food_snack == NULL) {
		perror("Food_Creat()::malloc()");
	}
	Food_snack->x = x;  
	Food_snack->y = y;                       // 赋予蛇的蛇的食物1新节点位置
	set_pos(x, y);
	wprintf(L"%Lc", FOOD);                       //并打印食物
	ps->fFood = Food_snack;                     //更新蛇的食物节点
}
///


void Food_creat2(pSnack ps) {              //食物节点2的创建
	int x1=0, y1=0;
once:
	do {
		x1 = rand() % 53 + 2;
		y1 = rand() % 24 + 2;            //上同食物一的创建,创建食物二的时候食物一一定存在
	} while (x1 % 2 ==1);
	pSnackNode cur2; cur2 = ps->PSnack;
	while (cur2) {
		if ((cur2->x == x1 && cur2->y == y1) || (cur2->x == ps->fFood->x && cur2->y == ps->fFood->y))goto once;
		cur2 = cur2->next;
	}
	pSnackNode foo = (pSnackNode)malloc(sizeof(SnackNode));
	if (foo == NULL) {
		perror("Food_creat2::malloc()");
	}
	foo->x = x1; foo->y = y1;
	set_pos(x1, y1);
	wprintf(L"%Lc", FOOD2);
	ps->fFOOD2 = foo;
}



//

void EatFood(pSnackNode pn, pSnack ps) {         //吃掉食物1
	ps->fFood->next = ps->PSnack;
	ps->PSnack = ps->fFood;               //下一个节点是蛇存储的食物1节点位置
	free(pn);                       //头插法插入节点,释放多余的pn所指向,(两个要删除一个)
	Food_Creat(ps);                //食物1被吃掉, 重新创建蛇的食物新节点    
	pn = NULL;                     
	pSnackNode cur;                    
	cur = ps->PSnack;                 
	while (cur) {                       
		set_pos(cur->x, cur->y);          //打印蛇 
		wprintf(L"%Lc", BODY);    
		cur = cur->next;
	}
	ps->score += 5; ps->sum++; ps->energe++;    //更新蛇的分数,能量,食食物个数
}
///

void EatFood2(pSnackNode pn, pSnack ps) {
	ps->fFOOD2->next = ps->PSnack;               //吃掉食物2,上同
	ps->PSnack=ps->fFOOD2;
	free(pn);
	Food_creat2(ps);
	pn = NULL;
	pSnackNode cur= ps->PSnack;
	while (cur) {
		set_pos(cur->x, cur->y);                 
		wprintf(L"%Lc", BODY);
		cur = cur->next;
	}
	ps->score += 10; ps->sum++; ps->energe=ps->energe+2;
}

/
void NoFood(pSnackNode pn, pSnack ps) {     //蛇即将到达的位置不是蛇的食物节点位置的移动
	pn->next = ps->PSnack;
	ps->PSnack = pn;
	pSnackNode cur = ps->PSnack;          //头插法插入即将到达的节点位置,将末尾节点释放掉
	while (cur->next->next != NULL) {      //并将原来倒数第二个节点的next变为NULL
		set_pos(cur->x, cur->y);           //打印蛇,将原来末尾节点位置打印空格
		wprintf(L"%Lc", BODY);                  
		cur = cur->next;
	}
	set_pos(cur->next->x, cur->next->y);
	printf("  ");
	free(cur->next);
	cur->next = NULL;
	set_pos(cur->x, cur->y); wprintf(L"%Lc", BODY);
}



void KillByWall(pSnack ps) {
	if (ps->PSnack->x == 0 || ps->PSnack->x == 58 || ps->PSnack->y == 1 || ps->PSnack->y == 26) {
		ps->status = KILL_BY_WALL;     //判断蛇头是否撞墙
	}
}


void KillBySelf(pSnack ps) {
	pSnackNode cur = ps->PSnack->next;      //判断蛇头是否撞到自己
	while (cur) {
		if (cur->x == ps->PSnack->x && cur->y == ps->PSnack->y) {
			ps->status = KILL_BY_SELE;
		}
		cur = cur->next;
	}
}

/

void SnackMove(pSnack ps) {
	pSnackNode psnode = (pSnackNode)malloc(sizeof(SnackNode));       
                                    //蛇即将到的下一个节点的位置
	if (psnode == NULL) {
		perror("malloc()::malloc()");
		return;
	}
	switch (ps->dir) {         //格局蛇的方向和头节点判断下一个即将到的节点位置并存储起来
	case UP:
		psnode->x = ps->PSnack->x; psnode->y = ps->PSnack->y - 1;
		break;
	case DOWN:
		psnode->x = ps->PSnack->x; psnode->y = ps->PSnack->y + 1;
		break;
	case LEFT:
		psnode->x = ps->PSnack->x - 2; psnode->y = ps->PSnack->y;
		break;
	case RIGHT:
		psnode->x = ps->PSnack->x + 2; psnode->y = ps->PSnack->y;
		break;
	}
	if (NextIsFood(psnode,ps)==1) {
		EatFood(psnode, ps);              //判断即将到达的位置是否是食物一节点的位置
	}
	else if (NextIsFood(psnode, ps) == 2) {
		EatFood2(psnode, ps);              //判断即将到达的位置是否是食物2节点的位置
	}
	else {
		NoFood(psnode, ps);                 //没有食物蛇的移动
	}
	KillByWall(ps);         //判断蛇的状态      //检查蛇是否撞墙
	KillBySelf(ps);                          //检查蛇是否撞到自己
}

8.蛇的移动运行,检测按键输入

需要的虚拟按键的罗列:
• 上:VK_UP
• 下:VK_DOWN
• 左:VK_LEFT
• 右:VK_RIGHT
• 空格:VK_SPACE
• ESC:VK_ESCAPE
• F3:VK_F3

如下:检测按键情况,if逐个判断,如果按下的按键与虚拟按键一致,就返回一,按键按下后改对应的状态;

#define KEY_PRESS(VK) ((GetAsyncKeyState(VK)&1)==1?1:0)
//
void Pause() {
	while (1) {
		Sleep(200);                    //暂停,按下空格结束
		if (KEY_PRESS(VK_SPACE)) {
			break;
		}
	}
}
/
void Game_Run(pSnack ps) {
	Print_Help(ps); 
	do {
		PrintM(ps); set_pos(70, 6); printf("                          ");
		if ( KEY_PRESS(VK_RIGHT) && ps->dir != LEFT) {
			ps->dir = RIGHT;                              
		}
		else if (KEY_PRESS(VK_LEFT) && ps->dir != RIGHT) {  //确定按下的是什么按键,改变蛇 
                                                             //的方向
			ps->dir = LEFT;                               
		}
		else if (KEY_PRESS(VK_UP) && ps->dir != DOWN) {
			ps->dir = UP;                                  
		}
		else if (KEY_PRESS(VK_DOWN) && ps->dir != UP) {
			ps->dir = DOWN;                                
		}    
		else if (KEY_PRESS(VK_SPACE)) {
			Pause();                                  //按下空格暂停
		}
		else if (KEY_PRESS(VK_ESCAPE) ){
			ps->status = END_NORMAL;                    //正常退出
		}
		else if (KEY_PRESS(VK_F3) ) {
			    
			if (ps->energe >= 3 && ps->sleep_time>80) {
				ps->sleep_time -= 30;
				ps->energe -= 3;// 加速     
				set_pos(59, 5); u1++; printf("成功加速%d次",u1); 
			}
			else {
				set_pos(80, 5); fail_up++; printf("加速失败%d次", fail_up);
			}         按下F3加速,减少蛇的sleep_time,每一次移动时暂停时间减少
		}

		else if (KEY_PRESS(VK_F4)) {
			if (ps->sleep_time >= 300) { set_pos(70, 6); printf("无法在减速!速度已经超低了"); }
			else {
	     		ps->sleep_time += 30;
				set_pos(59, 7); s1++; printf("成功减速%d次", s1);    //减速
				
			}   按下F4加速,增加蛇的sleep_time,每一次移动时暂停时间增加
		}
		
		if (ps->sleep_time <= 80) {
			set_pos(70, 6);  printf("已无法加速,速度已最高");
		}
		SnackMove(ps);                         //蛇的移动函数,上一步
		Sleep(ps->sleep_time);              //每一帧动画暂停多少秒
	} while (ps->status ==OK);
}

9.一场游戏的结束函数

判断蛇的状态,确定结束原因并打印相关信息,删除释放蛇的节点

void GameEnd(pSnack ps) {pSnackNode cur=ps->PSnack;
	switch (ps->status) {
	case KILL_BY_SELE:
		set_pos(24, 14); printf("你撞到了自己,游戏结束\n");
		break;
	case KILL_BY_WALL: 
		set_pos(24, 14); printf("你撞到了墙,游戏结束\n");
		break;
	case END_NORMAL:
		set_pos(24, 14); printf("你已正常退出游戏成功\n");
		break;
	}
	
	
	while (cur) {
		pSnackNode del;
		del = cur;
		cur = cur->next;
		free(del);
	}
}

10.设置主体运行函数,框架

void test() {
	int f = 1;
	//创建贪吃蛇(链表)
	do {
		f = 1;
		system("cls");
		u1 = 0; s1 = 0; fail_up = 0; fail_low = 0;
		Snack snack = { 0 };
		//初始化游戏
		GAMESTART(&snack);
		Food_Creat(&snack);
		Food_creat2(&snack);
		//运行游戏
		Game_Run(&snack);
		//结束游戏
		GameEnd(&snack);
		set_pos(10,22); printf("再来一局吗?(按下空格再来一局,按下Esc退出游戏)");
		while (1) {
			Sleep(200);
			if (KEY_PRESS(VK_SPACE))break;
			if (KEY_PRESS(VK_ESCAPE)) { 
				f = 0; break;
			}
		}
	} while (f);
	set_pos(0, 28);
}

我的主函数的内容很少

int main() {
	srand((unsigned)time(NULL));
	setlocale(LC_ALL, "");
	test();

	return 0;
}

然后大体就结束了。

11.我的全部代码

我的全部代码,很乱,写成一团的。有两个文件分别是snack.h和snack.c

snack.h的文件内容:

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<Windows.h>
#include<stdbool.h>
#include<locale.h>
#include<time.h>
#define KEY_PRESS(VK) ((GetAsyncKeyState(VK)&1)==1?1:0)
#define POS_X 24  //初始位置
#define POS_Y 5
#define WALL  L'□'  //墙
#define BODY  L'●'    //蛇的身体
#define FOOD  L'★'    // 蛇的食物1
#define  FOOD2  L'$'     //蛇的食物2
//类型声明
int u1 = 0, s1 = 0, fail_up; int fail_low;
enum DIRECTION {
	UP = 1,
    DOWN ,
   LEFT ,
   RIGHT 
};



enum GAME_STATUS{
	OK,    
	KILL_BY_WALL,
	KILL_BY_SELE,//正常,撞墙,撞到自己,正常退出//蛇的状态
	END_NORMAL
};
typedef struct SnackNode {
	int x; int y;
	struct SnackNode* next;   //蛇的坐标
}SnackNode,*pSnackNode;

typedef struct Snack {
	pSnackNode PSnack;//蛇头
	pSnackNode fFood;//食物
	pSnackNode  fFOOD2;
	enum DIRECTION dir;//蛇的方向
	enum GAME_STATUS status;//游戏状态                
		int energe;//neng能量
		int sum;//吃掉了多少食物
		int score; //总成绩
		int sleep_time;//休息时间,小速度大,反比;
}Snack,*pSnack;

//函数声明
void set_pos(short x, short y) {
	HANDLE houtput = NULL;
	houtput = GetStdHandle(STD_OUTPUT_HANDLE);                   //获取标准输出色被的句柄
	COORD pos = { x,y };                                          //定位光标位置
	SetConsoleCursorPosition(houtput, pos);
}
WelcomeToGame() {
	set_pos(40, 17); wprintf(L"欢迎来到贪吃蛇小游戏"); 
	set_pos(42, 20); system("pause");
	system("cls");
	set_pos(40, 17); wprintf(L"用↑,↓,←,→来控制蛇的移动,f3加速,f4减速");
	set_pos(40, 18); wprintf(L"加速能更快的得到分数");
	set_pos(42, 20); system("pause");
	system("cls");
}

void InitSnake(pSnack ps) {
	int i = 0; pSnackNode cur = NULL;
	for (i = 0; i < 5; i++) {
		cur = (pSnackNode)malloc(sizeof(SnackNode));
		if (cur == NULL) {
			perror("InitSnack()::malloc()");
			return;
		}
		cur->next = NULL;
		cur->x = POS_X + i;
		cur->y = POS_Y ;//头插法
		if (ps->PSnack == NULL) {
			ps->PSnack = cur;
		}
		else {
			cur->next = ps->PSnack;
			ps->PSnack = cur;
		}
	}
	cur = ps->PSnack;
	while (cur) {
		set_pos(cur->x, cur->y);
		wprintf(L"%lc",BODY);
		cur = cur->next;
	}
	//设置贪吃蛇的属性
	ps->dir = RIGHT;
	ps->sum=0;
	ps->energe = 6;
	ps->score = 0;
	ps->status = OK;
	ps->sleep_time = 200;
	
}

void  CreatMap() {
	int i; 
	 //up
	set_pos(0, 1); for (i = 0; i < 58; i++)wprintf(L"%lc",WALL);
	 //down
	set_pos(0, 26); for (i = 0; i < 58; i++)wprintf(L"%lc",WALL);
	 //left
	for (i = 1; i <= 26; i++) { set_pos(0, i); wprintf(L"%lc",WALL); }
	 //right
	for (i = 1; i <= 26; i++) { set_pos(58, i); wprintf(L"%lc",WALL); }

}
void Food_Creat(pSnack ps) {
	int x=0, y=0; 
again:
	do {
		x = rand() % 53 + 2;
		y = rand() % 24 + 2; 
	} while (x % 2 != 0 );
		//判断是否与蛇重合;
		pSnackNode cur; cur = ps->PSnack;
	while (cur) {
		if (ps->fFOOD2 == NULL) { if (cur->x ==x && cur->y == y) goto again; } 
		else {
			if((cur->x == x && cur->y == y) || (cur->next == ps->fFOOD2->x && cur->y == ps->fFOOD2->y))goto again;
		}cur = cur->next;
	}
	//创建食物节点
	pSnackNode Food_snack = (pSnackNode)malloc(sizeof(SnackNode));
	if (Food_snack == NULL) {
		perror("Food_Creat()::malloc()");
	}
	Food_snack->x = x; 
	Food_snack->y = y; 
	set_pos(x, y);
	wprintf(L"%Lc", FOOD);
	ps->fFood = Food_snack;
}
void Food_creat2(pSnack ps) {
	int x1=0, y1=0;
once:
	do {
		x1 = rand() % 53 + 2;
		y1 = rand() % 24 + 2;
	} while (x1 % 2 ==1);
	pSnackNode cur2; cur2 = ps->PSnack;
	while (cur2) {
		if ((cur2->x == x1 && cur2->y == y1) || (cur2->x == ps->fFood->x && cur2->y == ps->fFood->y))goto once;
		cur2 = cur2->next;
	}
	pSnackNode foo = (pSnackNode)malloc(sizeof(SnackNode));
	if (foo == NULL) {
		perror("Food_creat2::malloc()");
	}
	foo->x = x1; foo->y = y1;
	set_pos(x1, y1);
	wprintf(L"%Lc", FOOD2);
	ps->fFOOD2 = foo;
}
//1.   //窗口大小,光标隐藏,打印环境界面,功能介绍,绘制地图,创建蛇,创建食物,设置游戏相关信息
void GAMESTART(pSnack ps){
	system("mode con cols=100 lines=30");
	system("title 贪吃蛇");                                    
	HANDLE houtput=GetStdHandle(STD_OUTPUT_HANDLE);
	CONSOLE_CURSOR_INFO CursorInfo;
	GetConsoleCursorInfo(houtput, &CursorInfo);//获取控制台光标
	CursorInfo.bVisible = false;
	SetConsoleCursorInfo(houtput, &CursorInfo);

	WelcomeToGame();//●↑→●●界面
	CreatMap();                                        //27.58  地图
	InitSnake(ps);
	
}

void Print_Help(pSnack ps) {
	set_pos(66, 2);
	wprintf(L"你的分数:%d", ps->score);
	
	set_pos(60, 10);
	wprintf(L"%ls", L"不能撞墙,不能咬到自己");
	set_pos(60, 11);
	wprintf(L"%ls", L"用↑,↓,←,→来控制蛇的移动,f3加速,f4减速");
	set_pos(60, 12);
	wprintf(L"%ls", L"能量大于等于3即可加速");
	set_pos(60, 14);
	wprintf(L"%ls", L"Esc退出游戏,空格暂停游戏");

}
void PrintM(pSnack ps) {
	set_pos(66,2 );
	wprintf(L"你的分数:%d", ps->score);
	set_pos(66, 3);
	wprintf(L"已食食物个数:%d",ps->sum );
	set_pos(66, 4);
	if (ps->energe >= 10)wprintf(L"你的能量:%d", ps->energe); else {
		wprintf(L"你的能量: %d", ps->energe);
	}
	
}
void Pause() {
	while (1) {
		Sleep(200);
		if (KEY_PRESS(VK_SPACE)) {
			break;
		}
	}
}
int NextIsFood(pSnackNode pn,pSnack ps) {
	if (pn->x == ps->fFood->x && pn->y == ps->fFood->y)return 1;
	if (pn->x == ps->fFOOD2->x && pn->y == ps->fFOOD2->y)return 2;
	return 0;
}
void EatFood(pSnackNode pn, pSnack ps) {
	ps->fFood->next = ps->PSnack;
	ps->PSnack = ps->fFood;
	free(pn);
	Food_Creat(ps);
	pn = NULL;
	pSnackNode cur;
	cur = ps->PSnack;
	while (cur) {
		set_pos(cur->x, cur->y);
		wprintf(L"%Lc", BODY);
		cur = cur->next;
	}
	ps->score += 5; ps->sum++; ps->energe++;
}
void EatFood2(pSnackNode pn, pSnack ps) {
	ps->fFOOD2->next = ps->PSnack;
	ps->PSnack=ps->fFOOD2;
	free(pn);
	Food_creat2(ps);
	pn = NULL;
	pSnackNode cur= ps->PSnack;
	while (cur) {
		set_pos(cur->x, cur->y);
		wprintf(L"%Lc", BODY);
		cur = cur->next;
	}
	ps->score += 10; ps->sum++; ps->energe=ps->energe+2;
}
void NoFood(pSnackNode pn, pSnack ps) {
	pn->next = ps->PSnack;
	ps->PSnack = pn;
	pSnackNode cur = ps->PSnack;
	while (cur->next->next != NULL) {
		set_pos(cur->x, cur->y);
		wprintf(L"%Lc", BODY);
		cur = cur->next;
	}
	set_pos(cur->next->x, cur->next->y);
	printf("  ");
	free(cur->next);
	cur->next = NULL;
	set_pos(cur->x, cur->y); wprintf(L"%Lc", BODY);
}
void KillByWall(pSnack ps) {
	if (ps->PSnack->x == 0 || ps->PSnack->x == 58 || ps->PSnack->y == 1 || ps->PSnack->y == 26) {
		ps->status = KILL_BY_WALL;
	}
}
void KillBySelf(pSnack ps) {
	pSnackNode cur = ps->PSnack->next;
	while (cur) {
		if (cur->x == ps->PSnack->x && cur->y == ps->PSnack->y) {
			ps->status = KILL_BY_SELE;
		}
		cur = cur->next;
	}
}
void SnackMove(pSnack ps) {
	pSnackNode psnode = (pSnackNode)malloc(sizeof(SnackNode));       //蛇即将到的下一个节点
	if (psnode == NULL) {
		perror("malloc()::malloc()");
		return;
	}
	switch (ps->dir) {
	case UP:
		psnode->x = ps->PSnack->x; psnode->y = ps->PSnack->y - 1;
		break;
	case DOWN:
		psnode->x = ps->PSnack->x; psnode->y = ps->PSnack->y + 1;
		break;
	case LEFT:
		psnode->x = ps->PSnack->x - 2; psnode->y = ps->PSnack->y;
		break;
	case RIGHT:
		psnode->x = ps->PSnack->x + 2; psnode->y = ps->PSnack->y;
		break;
	}
	if (NextIsFood(psnode,ps)==1) {
		EatFood(psnode, ps);
	}
	else if (NextIsFood(psnode, ps) == 2) {
		EatFood2(psnode, ps);
	}
	else {
		NoFood(psnode, ps);
	}
	KillByWall(ps);
	KillBySelf(ps);
}
void GameEnd(pSnack ps) {pSnackNode cur=ps->PSnack;
	switch (ps->status) {
	case KILL_BY_SELE:
		set_pos(24, 14); printf("你撞到了自己,游戏结束\n");
		break;
	case KILL_BY_WALL: 
		set_pos(24, 14); printf("你撞到了墙,游戏结束\n");
		break;
	case END_NORMAL:
		set_pos(24, 14); printf("你已正常退出游戏成功\n");
		break;
	}
	
	
	while (cur) {
		pSnackNode del;
		del = cur;
		cur = cur->next;
		free(del);
	}
}
void Game_Run(pSnack ps) {
	Print_Help(ps); 
	do {
		PrintM(ps); set_pos(70, 6); printf("                          ");
		if ( KEY_PRESS(VK_RIGHT) && ps->dir != LEFT) {
			ps->dir = RIGHT;                        //向右
		}
		else if (KEY_PRESS(VK_LEFT) && ps->dir != RIGHT) {
			ps->dir = LEFT;                       //向左
		}
		else if (KEY_PRESS(VK_UP) && ps->dir != DOWN) {
			ps->dir = UP;                              //向上
		}
		else if (KEY_PRESS(VK_DOWN) && ps->dir != UP) {
			ps->dir = DOWN;                   //向下
		}
		else if (KEY_PRESS(VK_SPACE)) {
			 Pause();                       //暂停
		}
		else if (KEY_PRESS(VK_ESCAPE) ){
			ps->status = END_NORMAL;            //正常退出
		}
		else if (KEY_PRESS(VK_F3) ) {
			    
			if (ps->energe >= 3 && ps->sleep_time>80) {
				ps->sleep_time -= 30;
				ps->energe -= 3;// 加速     
				set_pos(59, 5); u1++; printf("成功加速%d次",u1); 
			}
			else {
				set_pos(80, 5); fail_up++; printf("加速失败%d次", fail_up);
			}
		}
		else if (KEY_PRESS(VK_F4)) {
			if (ps->sleep_time >= 300) { set_pos(70, 6); printf("无法在减速!速度已经超低了"); }
			else {
	     		ps->sleep_time += 30;
				set_pos(59, 7); s1++; printf("成功减速%d次", s1);    //减速
				
			}
		}
		
		if (ps->sleep_time <= 80) {
			set_pos(70, 6);  printf("已无法加速,速度已最高");
		}
		SnackMove(ps);//过程
		Sleep(ps->sleep_time);
	} while (ps->status ==OK);
}







//蛇的头、速度、方向。食物。食物分数、总分,蛇的状态
void test() {
	int f = 1;
	//创建贪吃蛇(链表)
	do {
		f = 1;
		system("cls");
		u1 = 0; s1 = 0; fail_up = 0; fail_low = 0;
		Snack snack = { 0 };
		//初始化游戏
		GAMESTART(&snack);
		Food_Creat(&snack);
		Food_creat2(&snack);
		//运行游戏
		Game_Run(&snack);
		//结束游戏
		GameEnd(&snack);
		set_pos(10,22); printf("再来一局吗?(按下空格再来一局,按下Esc退出游戏)");
		while (1) {
			Sleep(200);
			if (KEY_PRESS(VK_SPACE))break;
			if (KEY_PRESS(VK_ESCAPE)) { 
				f = 0; break;
			}
		}
	} while (f);
	set_pos(0, 28);
}

snack.c的内容:

#include"snake.h"
int main() {
	srand((unsigned)time(NULL));
	setlocale(LC_ALL, "");
	test();

	return 0;
}

到这里就结束了,感谢观看。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值