贪吃蛇(c语言)!!源码加解析

news2025/1/11 23:43:01

目录

1.建议先把源码拿去VS中测试一下了解这个贪吃蛇是什么样的 

1.头文件代码

2.源代码

3.测试代码

4.代码详解

1.头文件的解析

2.源代码的解析 

 1.光标的位置封装函数

 2.打印欢迎界面

3.打印整体的一个地图 

4.蛇的初始化 (重要)

 5.打印边栏信息

6.设置用来暂停的函数 

7.  3个函数,关于走的下一步是不是食物 

 8.关于蛇是怎么死的

 9.蛇的移动(重点)

 10.游戏的运行(游戏的逻辑)

11.关于整体游戏的测试代码


1.建议先把源码拿去VS中测试一下了解这个贪吃蛇是什么样的 

1.头文件代码

#pragma once
#include <stdio.h>
#include <Windows.h>
#include <time.h>
#include<locale.h>
#define KEY_PRESS(VK) ((GetAsyncKeyState(VK)&0x1) ? 1 : 0)//键盘按键的判断
#define WALL L'□'
#define BODY L'○' //★○●◇◆□■
#define FOOD L'★' //★○●◇◆□■
#define POS_X 24
#define POS_Y 5

typedef struct SnakeNode//蛇身
{
	int x;//蛇身的坐标
	int y;//蛇身的坐标
	struct SnakeNode* next;//下一个蛇身的节点
}SnakeNode ,* pSnakeNode;
typedef struct Snake//贪吃蛇整体
{
	pSnakeNode _pbody;//蛇身的指针
	pSnakeNode _pfood;//果实的指针
	enum DIRECTION _dir;//蛇的方向
	enum GAME_STATUS _status;//目前游戏的状态
	int _score;//当前的分数
	int _foodweight;//每个食物的得分
	int _sleeptime;//游戏的速度
}Snake,* pSnake;
enum DIRECTION//snake direction
{
	UP = 1,
	DOWN,
	LEFT,
	RIGHT
};
enum GAME_STATUS//the game.s status
{
	OK,
	KILL_BY_WALL,
	KILL_BY_SELF,
	END_NORMAL
};
//游戏的整体函数
void GameStart(pSnake ps);
void GameRun(pSnake ps);
void GameEnd(pSnake ps);
void SetPos(short x, short y);
void WelcomeToGame();
void PrintHelpInfo();//print some helpinfo
void CreatMap();
void InitSnake(pSnake ps);
void CreatFood(pSnake ps);
void pause();//game stop
int NextIsFood(pSnakeNode psn, pSnake ps);
void EatFood(pSnakeNode psn, pSnake ps);
void NotFood(pSnakeNode psn, pSnake ps);
int KillByWall(pSnake ps);
int KillBySelf(pSnake ps);
void SnakeMove(pSnake ps);

2.源代码


#include"tcs.h"
void SetPos(short x, short y)
{
	COORD pos = { x,y };
	HANDLE houtput = NULL;
	houtput = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleCursorPosition(houtput, pos);
}
void WelcomeToGame()
{
	SetPos(40, 15);
	printf("欢迎来到贪吃蛇\n");
	SetPos(40, 25);
	system("pause");
	system("cls");
	SetPos(25, 12);
	wprintf(L"⽤ ↑ . ↓ . ← . → 分别控制蛇的移动, F3为加速,F4为减速\n");
	SetPos(25, 13);
	printf("加速获得的分数更高\n");
	SetPos(40, 25);
	system("pause");
	system("cls");
}
void CreatMap()
{
	SetPos(0, 0);
	for (int i = 0; i < 58; i = i + 2)
	{
		wprintf(L"%c", WALL);
	}
	SetPos(0, 26);
	for (int i = 0; i < 58; i= i + 2)
	{
		wprintf(L"%c", WALL);
	}
	for (int i = 1; i < 26; i++)
	{
		SetPos(0, i);
		wprintf(L"%c", WALL);
	}
	for (int i = 1; i < 26; i++)
	{
		SetPos(56, i);
		wprintf(L"%c", WALL);
	}
}
void InitSnake(pSnake ps)
{
	pSnakeNode cur = NULL;
	for (int i = 0; i < 5; i++)
	{
		cur = (pSnakeNode)malloc(sizeof(SnakeNode));
		if (cur == NULL)
		{
			perror("snakenode don't get:");
			return;
		}
		cur->next = NULL;
		cur->x = POS_X + i * 2;
		cur->y = POS_Y;
		if (ps->_pbody == NULL)
		{
			ps->_pbody = cur;
		}
		else
		{
			cur->next = ps->_pbody;
			ps->_pbody = cur;
		}
	}

	//print snake
	cur = ps->_pbody;
	while (cur)
	{
		SetPos(cur->x, cur->y);
		wprintf(L"%c", BODY);
		cur = cur->next;
	}
	//init snake data
	ps->_dir = RIGHT;
	ps->_foodweight = 100;
	ps->_score = 0;
	ps->_sleeptime = 200;
	ps->_status = OK;
}
void CreatFood(pSnake ps)
{
	int x = 0;
	int y = 0;
	again:
	do
	{
		x = rand() % 53+2;
		y = rand() % 25+1;
	} while (x % 2 != 0);
	pSnakeNode cur = ps->_pbody;
	while (cur)
	{
		if (cur->x == x && cur->y == y)
		{
			goto again;
		}
		cur = cur->next;
	}
	pSnakeNode pFood = (pSnakeNode)malloc(sizeof(SnakeNode));
	if (pFood == NULL)
	{
		perror("creat pfood failed,fool!\n");
		return;
	}
	else
	{
		pFood->x = x;
		pFood->y = y;
		SetPos(pFood->x, pFood->y);
		wprintf(L"%c", FOOD);
		ps->_pfood = pFood;
	}
}
void PrintHelpInfo()
{
	SetPos(64, 15);
	printf("不能创墙,也不能创自己");
	SetPos(64, 16);
	printf("用↑.↓.←.→分别控制蛇的移动.");
	SetPos(64, 17);
	printf("F3 为加速,F4 为减速\n");
	SetPos(64, 18);
	printf("ESC :退出游戏.space:暂停游戏.");
	SetPos(64, 20);
	printf("江子龙@版权");
}
void pause()
{
	while (1)
	{
		Sleep(300);
		if (KEY_PRESS(VK_SPACE))
		{
			break;
		}
	}
}
int NextIsFood(pSnakeNode psn, pSnake ps)
{
	return(psn->x == ps->_pfood->x) && (psn->y == ps->_pfood->y);
}
void EatFood(pSnakeNode psn, pSnake ps)
{
	psn->next = ps->_pbody;
	ps->_pbody = psn;
	pSnakeNode cur = ps->_pbody;
	while (cur)
	{
		SetPos(cur->x, cur->y);
		wprintf(L"%c", BODY);
		cur = cur->next;
	}
	ps->_score += ps->_foodweight;
	free(ps->_pfood);
	CreatFood(ps);
}
void NotFood(pSnakeNode psn, pSnake ps)
{
	psn->next = ps->_pbody;
	ps->_pbody = psn;
	pSnakeNode cur = ps->_pbody;
	while (cur->next->next)
	{
		SetPos(cur->x, cur->y);
		wprintf(L"%c", BODY);
		cur = cur->next;
	}
	SetPos(cur->next->x, cur->next->y);
	printf("  ");
	free(cur->next);
	cur->next = NULL;
}
int KillByWall(pSnake ps)
{
	if ((ps->_pbody->x == 0) || (ps->_pbody->x == 56) || (ps->_pbody->y == 0) || (ps->_pbody->y == 26))
	{
		ps->_status = KILL_BY_WALL;
		return 1;
	}
	return 0;
}
int KillBySelf(pSnake ps)
{
	pSnakeNode cur = ps->_pbody->next;
	while (cur)
	{
		if ((ps->_pbody->x == cur->x) && (ps->_pbody->y == cur->y))
		{
			ps->_status = KILL_BY_SELF;
			return 1;
		}
		cur = cur->next;
	}
	return 0;
}
void SnakeMove(pSnake ps)
{
	pSnakeNode pNextNode = (pSnakeNode)malloc(sizeof(SnakeNode));
	if (pNextNode == NULL)
	{
		perror("snake move open falied");
		return;
	}

	switch (ps->_dir)
	{
	case UP:
	{
		pNextNode->y = ps->_pbody->y - 1;
		pNextNode->x = ps->_pbody->x;
	}
		break;
	case DOWN:
	{
		pNextNode->y = ps->_pbody->y + 1;
		pNextNode->x = ps->_pbody->x;
	}
		break;
	case LEFT:
	{
		pNextNode->y = ps->_pbody->y ;
		pNextNode->x = ps->_pbody->x - 2;
	}
		break;
	case RIGHT:
	{
		pNextNode->y = ps->_pbody->y;
		pNextNode->x = ps->_pbody->x + 2;
	}
		break;
	default:
		break;
	}
	if (NextIsFood(pNextNode, ps))
	{
		EatFood(pNextNode, ps);
	}
	else
	{
		NotFood(pNextNode, ps);
	}
	KillBySelf(ps);
	KillByWall(ps);
}
void GameStart(pSnake 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();
	InitSnake(ps);
	CreatFood(ps);
}
void GameRun(pSnake ps)
{
	PrintHelpInfo();
	do
	{
		SetPos(64, 10);
		printf("得分:%d ", ps->_score);
		printf("每个食物得分:%d", ps->_foodweight);
		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_RIGHT) && ps->_dir != LEFT)
		{
			ps->_dir = RIGHT;
		}
		else if (KEY_PRESS(VK_LEFT) && ps->_dir != RIGHT)
		{
			ps->_dir = LEFT;
		}
		else if (KEY_PRESS(VK_SPACE))
		{
			pause();
		}
		else if (KEY_PRESS(VK_ESCAPE))
		{
			ps->_status = END_NORMAL;
			break;
		}
		else if (KEY_PRESS(VK_F3))
		{
			if (ps->_sleeptime >= 50)
			{
				ps->_sleeptime -= 30;
				ps->_foodweight += 20;
			}
		}
		else if (KEY_PRESS(VK_F4))
		{
			if (ps->_sleeptime < 350)
			{
				ps->_sleeptime += 30;
				ps->_foodweight -= 20;
				if (ps->_sleeptime == 350)
				{
					ps->_foodweight = 1;
				}
			}
			
		}
		Sleep(ps->_sleeptime);
		SnakeMove(ps);

	} while (ps->_status == OK);
}
void GameEnd(pSnake ps)
{
	pSnakeNode cur = ps->_pbody;
	SetPos(24, 12);
	switch (ps->_status)
	{
	case KILL_BY_SELF:
		printf("你创了自己!,游戏结束\n");
		break;
	case KILL_BY_WALL:
		printf("你创了墙!game over\n");
		break;
	case END_NORMAL:
		printf("游戏正常结束!\n");
		break;
	}
	while (cur)
	{
		pSnakeNode del = cur;
		cur = cur->next;
		free(del);
	}
}

3.测试代码

#include<stdio.h>
#include"tcs.h"
void test()
{
	int ch = 0;
	srand((unsigned int)time(NULL));
	do
	{
		Snake snake = { 0 };
		GameStart(&snake);
		GameRun(&snake);
		GameEnd(&snake);
		SetPos(20, 15);
		printf("再来一局吗?(Y/N):");
		ch = getchar();
		getchar();
	} while (ch == 'Y'|| ch == 'y');
	SetPos(0, 27);
}
int main()
{
	setlocale(LC_ALL, "");
	test();
	return 0;
}

4.代码详解

1.头文件的解析

首先这一块是取库函数,和定义宏。

KEY_PRESS(VK)封装的是一个关于键盘是否被按下的函数。

这个函数的使用方法就是判断一个键盘按键是否被按下,如果按下它的返回值就是1不是就是0.所以用& 来判断是1还是0就能判断是否按下按键。 

 

这一块就是设置整体游戏函数的结构体,和定义一些参数。当然不习惯用enum定义,也可以用#define 来定义下面的方向以及游戏状态。 用typedef将 蛇身和整体的类型名缩写。

 

这一块就是等会需要实现的函数。 

2.源代码的解析 

 1.光标的位置封装函数

 

 

首先先说下COORD,他是一个结构体在WINDOWS API中定义的,里面存的变量是用来更改光标位置,为什么要改变光标的位置呢?改变光标位置你就可以在任何位置打印数据 。

第二个HANDLE就是一个变量,这个变量可以当做一个控制器,你可以给这个控制器变成任何一种工具,这里就获取了(GetStdHandle),标准输出(STD_OUTPUT_HANDLE),就是上面这个命令提示符。然后设置了此处的光标位置SetConsoleCursorPosition(houtput, pos)

GetStdHandle是获取一个控制器,下面的setconsolecursorposition根据字面意思就是设置光标位置。

 2.打印欢迎界面

void WelcomeToGame()
{
	SetPos(40, 15);
	printf("欢迎来到贪吃蛇\n");
	SetPos(40, 25);
	system("pause");
	system("cls");
	SetPos(25, 12);
	wprintf(L"⽤ ↑ . ↓ . ← . → 分别控制蛇的移动, F3为加速,F4为减速\n");
	SetPos(25, 13);
	printf("加速获得的分数更高\n");
	SetPos(40, 25);
	system("pause");
	system("cls");
}

 这一步就是用来打印欢迎界面以及介绍界面的

system("pause");这一步可以用来暂停,按一个键可以继续运行。
    system("cls");这一步是用来清屏的

3.打印整体的一个地图 

void CreatMap()
{
	SetPos(0, 0);
	for (int i = 0; i < 58; i = i + 2)
	{
		wprintf(L"%c", WALL);
	}
	SetPos(0, 26);
	for (int i = 0; i < 58; i= i + 2)
	{
		wprintf(L"%c", WALL);
	}
	for (int i = 1; i < 26; i++)
	{
		SetPos(0, i);
		wprintf(L"%c", WALL);
	}
	for (int i = 1; i < 26; i++)
	{
		SetPos(56, i);
		wprintf(L"%c", WALL);
	}
}

 首先游戏大小代码里设置的是58*26的就是58列26行。

然后setpos就是第一个函数,用来设定光标的位置,然后

关于wprintf因为在设计墙体蛇身这些图形时一个字符的空间是不够的,所以要用到wprintf,用来打印图形等双字符。且使用wprintf后面要在双引号前加上L表示打印宽字符。头文件是

#include<locale.h> 

4.蛇的初始化 (重要)

void InitSnake(pSnake ps)
{
	pSnakeNode cur = NULL;
	for (int i = 0; i < 5; i++)
	{
		cur = (pSnakeNode)malloc(sizeof(SnakeNode));
		if (cur == NULL)
		{
			perror("snakenode don't get:");
			return;
		}
		cur->next = NULL;
		cur->x = POS_X + i * 2;
		cur->y = POS_Y;
		if (ps->_pbody == NULL)
		{
			ps->_pbody = cur;
		}
		else
		{
			cur->next = ps->_pbody;
			ps->_pbody = cur;
		}
	}

	//print snake
	cur = ps->_pbody;
	while (cur)
	{
		SetPos(cur->x, cur->y);
		wprintf(L"%c", BODY);
		cur = cur->next;
	}
	//init snake data
	ps->_dir = RIGHT;
	ps->_foodweight = 100;
	ps->_score = 0;
	ps->_sleeptime = 200;
	ps->_status = OK;
}

关于初始化蛇,就是把snake 结构体的各项都初始化,还有把蛇身整体先打印出来。

关于蛇身的打印,可以根据你的想法打印出具体个数,for循环里更改就好。

首先关于这个蛇的实现我们用的是链表的知识,不知道的同学可以先去补一补链表。

对每个节点都设定好后,就是到while循环了,循环设定好的节点,把它打印在屏幕上。

这里用到setpos来找到需要打印的位置。

后面把snake结构体中的变量都初始化(根据自己喜欢调节就好)就可以进行下一步了。(这一步的蛇只是打印在屏幕上不能动。)

void CreatFood(pSnake ps)
{
	int x = 0;
	int y = 0;
	again:
	do
	{
		x = rand() % 53+2;
		y = rand() % 25+1;
	} while (x % 2 != 0);
	pSnakeNode cur = ps->_pbody;
	while (cur)
	{
		if (cur->x == x && cur->y == y)
		{
			goto again;
		}
		cur = cur->next;
	}
	pSnakeNode pFood = (pSnakeNode)malloc(sizeof(SnakeNode));
	if (pFood == NULL)
	{
		perror("creat pfood failed,fool!\n");
		return;
	}
	else
	{
		pFood->x = x;
		pFood->y = y;
		SetPos(pFood->x, pFood->y);
		wprintf(L"%c", FOOD);
		ps->_pfood = pFood;
	}
}

因为玩的是贪吃蛇,我们现在初始化好蛇了,那接下来就是蛇的食物了。

用到rand()随机数。随机生成食物。

goto语句就是找到后面的名称的位置,跳到那个位置执行,(可以做到如果结果错误,重新打印食物)。其他的一看就懂了。

 5.打印边栏信息

void PrintHelpInfo()
{
	SetPos(64, 15);
	printf("不能创墙,也不能创自己");
	SetPos(64, 16);
	printf("用↑.↓.←.→分别控制蛇的移动.");
	SetPos(64, 17);
	printf("F3 为加速,F4 为减速\n");
	SetPos(64, 18);
	printf("ESC :退出游戏.space:暂停游戏.");
	SetPos(64, 20);
	printf("江子龙@版权");
}

6.设置用来暂停的函数 

void pause()
{
	while (1)
	{
		Sleep(300);
		if (KEY_PRESS(VK_SPACE))
		{
			break;
		}
	}
}

 这个函数主要用来,当你按下space的时候,给计算机一个sleep的死循环。

7.  3个函数,关于走的下一步是不是食物 

int NextIsFood(pSnakeNode psn, pSnake ps)
{
	return(psn->x == ps->_pfood->x) && (psn->y == ps->_pfood->y);
}
void EatFood(pSnakeNode psn, pSnake ps)
{
	psn->next = ps->_pbody;
	ps->_pbody = psn;
	pSnakeNode cur = ps->_pbody;
	while (cur)
	{
		SetPos(cur->x, cur->y);
		wprintf(L"%c", BODY);
		cur = cur->next;
	}
	ps->_score += ps->_foodweight;
	free(ps->_pfood);
	CreatFood(ps);
}
void NotFood(pSnakeNode psn, pSnake ps)
{
	psn->next = ps->_pbody;
	ps->_pbody = psn;
	pSnakeNode cur = ps->_pbody;
	while (cur->next->next)
	{
		SetPos(cur->x, cur->y);
		wprintf(L"%c", BODY);
		cur = cur->next;
	}
	SetPos(cur->next->x, cur->next->y);
	printf("  ");
	free(cur->next);
	cur->next = NULL;
}

第一个返回的是int 是为了等会在主体函数中判断真假,如果为真为1则执行EatFood,为假为0则执行NotFood。 (贪吃蛇变长的条件)

第二个EatFood 如果下一个点是食物的话,贪吃蛇就变长一格,用的是头插。

第三个NotFood 如果下一点不是食物的话,贪吃蛇就整个向前走一格,就是头插下一个空白格,然后free掉尾巴最后一格。

 8.关于蛇是怎么死的

int KillByWall(pSnake ps)
{
	if ((ps->_pbody->x == 0) || (ps->_pbody->x == 56) || (ps->_pbody->y == 0) || (ps->_pbody->y == 26))
	{
		ps->_status = KILL_BY_WALL;
		return 1;
	}
	return 0;
}
int KillBySelf(pSnake ps)
{
	pSnakeNode cur = ps->_pbody->next;
	while (cur)
	{
		if ((ps->_pbody->x == cur->x) && (ps->_pbody->y == cur->y))
		{
			ps->_status = KILL_BY_SELF;
			return 1;
		}
		cur = cur->next;
	}
	return 0;
}

接下来的这两个代码就是用来判断,你的蛇是怎么死的。

第一个代码判断出来的就是如果 蛇的头与墙的位置出现在了一起,那就把状态改变蛇就死了

第二个代码判断的是如果蛇和自己的身体的某一个节点的位置相同,那蛇的状态就是死了。 

 9.蛇的移动(重点)

void SnakeMove(pSnake ps)
{
	pSnakeNode pNextNode = (pSnakeNode)malloc(sizeof(SnakeNode));
	if (pNextNode == NULL)
	{
		perror("snake move open falied");
		return;
	}

	switch (ps->_dir)
	{
	case UP:
	{
		pNextNode->y = ps->_pbody->y - 1;
		pNextNode->x = ps->_pbody->x;
	}
		break;
	case DOWN:
	{
		pNextNode->y = ps->_pbody->y + 1;
		pNextNode->x = ps->_pbody->x;
	}
		break;
	case LEFT:
	{
		pNextNode->y = ps->_pbody->y ;
		pNextNode->x = ps->_pbody->x - 2;
	}
		break;
	case RIGHT:
	{
		pNextNode->y = ps->_pbody->y;
		pNextNode->x = ps->_pbody->x + 2;
	}
		break;
	default:
		break;
	}
	if (NextIsFood(pNextNode, ps))
	{
		EatFood(pNextNode, ps);
	}
	else
	{
		NotFood(pNextNode, ps);
	}
	KillBySelf(ps);
	KillByWall(ps);
}

蛇的移动代码量偏长,首先定义好蛇的移动方向上下左右,是怎么改变的。

因为蛇的节点的宽字符,所以在横坐标改变时是两倍改变,而纵坐标为单倍改变即可。

然后在进行判断蛇移动的下一个位置是否是食物,是食物则执行前面的三个函数。

最后判断蛇是否死亡。

 10.游戏的运行(游戏的逻辑)

void GameStart(pSnake 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();
	InitSnake(ps);
	CreatFood(ps);
}
void GameRun(pSnake ps)
{
	PrintHelpInfo();
	do
	{
		SetPos(64, 10);
		printf("得分:%d ", ps->_score);
		printf("每个食物得分:%d", ps->_foodweight);
		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_RIGHT) && ps->_dir != LEFT)
		{
			ps->_dir = RIGHT;
		}
		else if (KEY_PRESS(VK_LEFT) && ps->_dir != RIGHT)
		{
			ps->_dir = LEFT;
		}
		else if (KEY_PRESS(VK_SPACE))
		{
			pause();
		}
		else if (KEY_PRESS(VK_ESCAPE))
		{
			ps->_status = END_NORMAL;
			break;
		}
		else if (KEY_PRESS(VK_F3))
		{
			if (ps->_sleeptime >= 50)
			{
				ps->_sleeptime -= 30;
				ps->_foodweight += 20;
			}
		}
		else if (KEY_PRESS(VK_F4))
		{
			if (ps->_sleeptime < 350)
			{
				ps->_sleeptime += 30;
				ps->_foodweight -= 20;
				if (ps->_sleeptime == 350)
				{
					ps->_foodweight = 1;
				}
			}
			
		}
		Sleep(ps->_sleeptime);
		SnakeMove(ps);

	} while (ps->_status == OK);
}
void GameEnd(pSnake ps)
{
	pSnakeNode cur = ps->_pbody;
	SetPos(24, 12);
	switch (ps->_status)
	{
	case KILL_BY_SELF:
		printf("你创了自己!,游戏结束\n");
		break;
	case KILL_BY_WALL:
		printf("你创了墙!game over\n");
		break;
	case END_NORMAL:
		printf("游戏正常结束!\n");
		break;
	}
	while (cur)
	{
		pSnakeNode del = cur;
		cur = cur->next;
		free(del);
	}
}

 每个游戏的运行都分为三步,开始,玩,结束。

这里也一样,游戏的开始就是用上面的函数进行游戏的初始化,菜单的打印,以及初始化蛇之类的开始函数。

第二步玩,这一步要用到之前封装的宏 KEY_PRESS( VK ),用来判断这个按键是否被按下,被按下就执行这个逻辑。同时贪吃蛇的一部分按键是不能重合的,像上和下是不能同时进行的,所以要进行判断。最后加上snakemove等函数,蛇就能动起来。

第三步结束,这一步就是判断你的游戏时因为什么结束的。然后再把蛇的节点全部free,以备开启下一把

11.关于整体游戏的测试代码

void test()
{
	int ch = 0;
	srand((unsigned int)time(NULL));
	do
	{
		Snake snake = { 0 };
		GameStart(&snake);
		GameRun(&snake);
		GameEnd(&snake);
		SetPos(20, 15);
		printf("再来一局吗?(Y/N):");
		ch = getchar();
		getchar();
	} while (ch == 'Y'|| ch == 'y');
	SetPos(0, 27);
}
int main()
{
	setlocale(LC_ALL, "");
	test();
	return 0;
}

setlocale 是用来适应当地环境的。(用来打印宽字符)

srand函数,是为了让rand 函数的值不是伪随机值,而是随着时间更改。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1198679.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

过去5年,Python生态有什么变化?

你好&#xff0c;我是 EarlGrey&#xff0c;一名双语学习者&#xff0c;会一点编程&#xff0c;目前已翻译出版《Python 无师自通》、《Python 并行编程手册》等书籍。 点击上方蓝字关注我&#xff0c;持续接收优质好书、高效工具和赚钱机会&#xff0c;一起提升认知和思维。 过…

《网络协议》04. 应用层(DNS DHCP HTTP)

title: 《网络协议》04. 应用层&#xff08;DNS & DHCP & HTTP&#xff09; date: 2022-09-05 14:28:22 updated: 2023-11-12 06:55:52 categories: 学习记录&#xff1a;网络协议 excerpt: 应用层、DNS、DHCP、HTTP&#xff08;URI & URL&#xff0c;ABNF&#xf…

2个器件,做1个恒流源

在项目中经常要用到恒流源&#xff0c;查找资料可以使用电压源芯片LM317构造一个电流源芯片。本文将电压源加上一个电阻改为电流源&#xff0c;这种设计思路可以扩展到其他类型的电源芯片上&#xff0c;如开关电源及其他类型的线性电源&#xff0c;关键点在于基准电压VREF的使用…

免费分享一套基于Springboot+Vue的在线考试系统,挺漂亮的

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的SpringbootVue的在线考试系统&#xff0c;分享下哈。 项目视频演示 【免费】springbootvue在线考试系统 Java毕业设计_哔哩哔哩_bilibili【免费】springbootvue在线考试系统 Java毕业设计项目来自互联网&a…

GPT 写作与改编

GPT 写作与改编 文商科GPT 写作收益 改编技巧【改编一段话】【改编评价】【意识预设】落差&#xff0c;让顾客看到就感性和冲动害怕&#xff0c;让顾客看到就想买和拥有画面&#xff0c;切换空间&#xff0c;瞬间代入&#xff0c;勾人魂魄对比&#xff0c;设置参考物&#xff0…

港科夜闻 | 香港科大(广州)知识转移办公室创业中心主办的INNOPITCH路演推介会成功举办...

关注并星标 每周阅读港科夜闻 建立新视野 开启新思维 1、11月7日&#xff0c;由香港科大&#xff08;广州&#xff09;知识转移办公室创业中心主办的“INNOPITCH路演推介会&#xff1a;新材料、能源环保、微电子技术专场”在香港科大&#xff08;广州&#xff09;校园内举办。十…

《网络协议》05. 网络通信安全 · 密码技术

title: 《网络协议》05. 网络通信安全 密码技术 date: 2022-09-10 15:16:15 updated: 2023-11-12 07:03:52 categories: 学习记录&#xff1a;网络协议 excerpt: 网络通信安全&#xff08;ARP 欺骗&#xff0c;DoS & DDoS&#xff0c;SYN 洪水攻击&#xff0c;LAND 攻击&a…

实验室(检验科)信息系统源码,医学检验LIS系统源码,云LIS源码

实验室&#xff08;检验科&#xff09;信息系统源码&#xff0c;LIS源码&#xff0c;基于云计算技术的LIS系统源码&#xff0c;云LIS源码 LIS系统(LaboratoryInformationSystem) 即 实验室&#xff08;检验科&#xff09;信息系统&#xff0c;它是医院信息管理的重要组成部分之…

利用OGG实现PostgreSQL实时同步

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&am…

任正非说:到现在我们终于可以说没有失败,但我们还不能说成功。

你好&#xff01;这是华研荟【任正非说】系列的第36篇文章&#xff0c;让我们聆听任正非先生的真知灼见&#xff0c;学习华为的管理思想和管理理念。 华研荟导语&#xff1a;今天的任正非先生讲话主要节选了他在2001-2004年的几个关于IPD、ISC的论述&#xff0c;可能大家会发现…

Linux shell编程学习笔记24:函数定义和使用

为了实现模块化设计和代码重用&#xff0c;很多编程语言支持函数或过程&#xff0c;Linux shell也支持函数定义和调用。 Linux shell中的函数与其它编程语言很多有相似之处&#xff0c;也有自己独特之处。 1 函数的定义 1.1 标准格式 function 函数名(){语句或命令1……语句…

操作系统 | proc文件系统

&#x1f308;个人主页&#xff1a;Sarapines Programmer&#x1f525; 系列专栏&#xff1a;《操作系统实验室》&#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 目录结构 1. 操作系统实验之proc文件系统 1.1 实验目的 1.2 实验内容 1.3 实验步骤 1.4 实验…

c++求三个数的最小公倍数

答案&#xff1a; #include <iostream> using namespace std; int main() {int n1, n2, n3, max;cin >> n1 >> n2 >> n3;max (n1 > n2 > n3) ? n1 : n2;do{if (max % n1 0 && max % n2 0 && max % n3 0){cout << ma…

如何关闭Windows Defender(亲测可行!!非常简单)

一、背景 Windows Defender&#xff08;简称WD&#xff09;真的太讨厌了&#xff0c;经常给你报你下载的文件是病毒&#xff0c;且不说真的是不是病毒&#xff0c;它都不询问直接删。 另外聚资料显示WD还会不合时宜地执行扫描导致系统变慢&#xff08;不会在合适的、空闲的时…

Pathways

信号通路signaling pathway-武汉华美生物 (cusabio.cn) 神经信号通路(Neuronal Signaling)--selleck.cn PI3K/Akt/mTOR信号通路 表观遗传 甲基化 免疫&炎症 酪氨酸蛋白激酶 血管生成 凋亡 自噬 内质网应激&UPR响应 JAK/STAT信号通路 MAPK信号通路 细胞骨架…

HTML使用lable将文字与控件进行关联以获取焦点

先养养眼再往下看 注释很详细&#xff0c;直接上代码 <form action""><!-- 第一种方法:用id的方式绑定账户(文字)和输入框 --><label for"zhanghu">账户</label><input "text" id"zhanghu" name"ac…

软件自动化测试平台

软件测试分类黑盒、白盒、功能、API、接口、压力测试和性能测试&#xff0c; 自动化测试平台是一种用于自动化执行软件测试过程的工具。 一、自动化测试平台-功能性 1. 接口自动化&#xff1a;对接软件的接口进行测试&#xff0c;验证接口的功能和性能。 2. Web 自动化&…

一步一步详细介绍如何使用 OpenCV 制作低成本立体相机

在这篇文章中,我们将学习如何创建定制的低成本立体相机(使用一对网络摄像头)并使用 OpenCV 捕获 3D 视频。我们提供 Python 和 C++ 代码。文末并附完整的免费代码下载链接 我们都喜欢观看上面所示的 3D 电影和视频。您需要如图 1 所示的红青色 3D 眼镜才能体验 3D 效果。它是…

网络运维Day11

文章目录 if语句if单分支应用案例 if双分支应用案例 if多分支应用案例 for循环while循环案例 正则表达式基本正则Perl兼容的正则 综合练习总结 if语句 if单分支 if单分支的语法组成&#xff1a; if 条件测试;then 命令序列 fiif 条件测试then 命令序列 fi应用案例 判断用…

要找事做,我真怕被闲死

要找事做&#xff0c;我真怕被闲死 | 昨晚睡足了5个多小时&#xff0c;元气开始恢复&#xff0c;今晨6点钟醒来&#xff0c;如厕后无睡意&#xff0c;便窝在被子里闭目养神&#xff0c;同时想心事。 7点钟翻身起床穿衣洗刷后&#xff0c;烧瓶开水泡杯浓茶&#xff0c;打开电脑…