C语言实现贪吃蛇

前言:今天给大家详细介绍一下小游戏贪吃蛇的代码。

目录

一 .贪吃蛇实现的功能 

二.贪吃蛇游戏设计与分析 

1.贪吃蛇以及贪吃蛇所需要维护的数据

(1)贪吃蛇蛇体

(2)数据维护 

2.地图设计

(1)标题以及行高和列宽的修改。

​编辑 (2)光标的隐藏以及光标位置的定位

(2)游戏开始第一界面 

(3)游戏开始第二界面

(4)游戏开始第三界面 

 3.蛇身以及食物的生成

(1)蛇身 

 (2)食物的生成

三.游戏运行

1.游戏的规则分数以及食物权重的打印

2.检测按键是否被按过

3.贪吃蛇的移动

(1)下一步移动位置是食物

(2)下一步移动位置不是食物 

4.检测是否撞墙或咬到自己

四.游戏结束后的善后

五.完整代码的实现

1.snake.h

2.snake.c

3.tets.c


一 .贪吃蛇实现的功能 

使⽤C语⾔在Windows环境的控制台中模拟实现经典⼩游戏贪吃蛇
实现基本的功能:
贪吃蛇地图绘制
蛇吃⻝物的功能 (上、下、左、右⽅向键控制蛇的动作)
蛇撞墙死亡
蛇撞⾃⾝死亡
计算得分
蛇⾝加速、减速
暂停游戏

我们贪吃蛇所需要用到的知识有:

C语⾔函数、枚举、结构体、动态内存管理、预处理指令、链表、Win32 API等。

二.贪吃蛇游戏设计与分析 

1.贪吃蛇以及贪吃蛇所需要维护的数据

(1)贪吃蛇蛇体

蛇体我们使用链表的方式来操作

搜先我们定义一个结构体通过光标信息的x,y操作来定位蛇的位置以及后续的移动

typedef struct SnakeNode {int x;int y;struct SnakeNode* next;
}SnakeNode,*pSnakeNode;

(2)数据维护 

在玩游戏的过程中我们需要将游戏的运行状态,蛇身的状态,方向,分数,食物,食物权重,速度(休眠时间),游戏运行状态进行维护起来,那么这时我们就需要创建一个存放各个数据的结构体:

//贪吃蛇各个数据维护
typedef struct Snake
{pSnakeNode pSnake;//蛇的信息pSnakeNode pFood;//食物信息enum DIR dir;//蛇运动的方向enum STATUE statue;//游戏运行的状态int Score;//分数int FoodWeight;//食物权重int SleepTime;//速度(休眠时间)
}Snake,*pSnake;

同样为了方便起见我们对蛇运动方向以及游戏状态用枚举来更简单的表达出来:

//贪吃蛇移动方向
enum DIR {UP=1,DOWN,LEFT,RIGHT,
};
//游戏进行的状态
enum STATUE {OK=1,ESC,KILL_BY_WALL,KILL_BY_SELF,
};

2.地图设计

首先这是我们刚进入游戏所需要的准备工作:

我们可以看到控制台的标题以及光标输入文字的定位信息都有一定的不一样,并且可以看到这边并没有光标的闪烁。

这些就是我们上一篇文章所写的内容我们可以使用cmd控制台来改变行号和列宽并且标题也与我们平常编译不一样。

(1)标题以及行高和列宽的修改。

//设置控制台的行和列system("mode con cols=100 lines=30");//设置控制台额名称system("title 贪吃蛇");

 (2)光标的隐藏以及光标位置的定位

	//隐藏光标//获取设备句柄HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);//获取光标信息CONSOLE_CURSOR_INFO CurInfor;GetConsoleCursorInfo(handle, &CurInfor);//修改光标信息CurInfor.bVisible = false;SetConsoleCursorInfo(handle, &CurInfor);//游戏开始界面的设计

 我们可以看到在加上getchar()的情况下控制台界面上仍然没有光标的显示。

(2)游戏开始第一界面 

平常注意点我们可以发现每次打印信息都是在输入框的左上角的起点开始,但是我们的第一界面的输入信息并没有在左上角的起点而是在控制台的中间。这时我们就可以用到上篇用到我们的COORD的坐标信息来定位。我们可以将其包装成一个函数:

void Setpos(int x, int y)
{HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);COORD pos = { x, y };SetConsoleCursorPosition(handle, pos);
}

这时我吗们就可以开始对页面信息的编写:

	//第一界面Setpos(40, 12);printf("欢迎来到贪吃蛇小游戏!");Setpos(40, 25);system("pause");system("cls");

 效果就是这样的。

(3)游戏开始第二界面

第二界面也就是游戏的操作方式以及得分规则(与第一界面方式相同)

	//第二界面Setpos(30, 12);printf("请使用↑ ↓← →来控制蛇的方向。");Setpos(30, 13);printf("使用F3,F4来实现加速和减速,加速能得到更高的分数。");Setpos(30, 25);system("pause");system("cls");

使用同样的方式来进行编写。

(4)游戏开始第三界面 

我们这第三界面也就是我们地图的打印以及分数和一些规则提示,我们先将地图打印剩下分数由于涉及到分数的变化以及食物权重的问题在游戏开始界面时另行设计。

我们假设实现⼀个棋盘27⾏,58列的棋盘(⾏和列可以根据⾃⼰的情况修改),再围绕地图画出墙, 如下:

 地图我们也是可以用到我们的循环以及光标位置的设计,实现出来也不是特别的困难。

值得注意的是我们需要将地图的大小来设计清楚。搜先我们墙体是中文符号'□',也就是我们所说的宽字符,占x坐标上的2个单元格也就是一个'□'会占x轴的两个坐标。

为了方便我们使用宏的方法来定义墙体符号,可以便于后期的更改:

#define WALL L'□'

下面是具体实现过程

	//打印地图int i = 0;// 上for (i = 0; i < 57; i += 2){Setpos(i, 0);wprintf(L"%lc", WALL);}// 下for (i = 0; i < 57; i += 2){Setpos(i, 25);wprintf(L"%lc", WALL);}//左for (i = 0; i < 25; i += 1){Setpos(0, i);wprintf(L"%lc", WALL);}//右for (i = 0; i < 25; i += 1){Setpos(56, i);wprintf(L"%lc", WALL);}

 3.蛇身以及食物的生成

(1)蛇身 

初始化状态,假设蛇的⻓度是5,蛇⾝的每个节点是●,在固定的⼀个坐标处,⽐如(24, 5)处开始出现 蛇,连续5个节点。注意:蛇的每个节点的x坐标必须是2个倍数,否则可能会出现蛇的⼀个节点有⼀半 ⼉出现在墙体中,另外⼀般在墙外的现象,坐标不好对⻬。
	int i = 0;pSnakeNode pcur = NULL;for (i = 0; i < 5; i++){pcur = (pSnakeNode)malloc(sizeof(SnakeNode));if (pcur == NULL){perror("InitSnake():malloc()");return;}pcur->x = POS_X + 2 * i;pcur->y = POS_Y;pcur->next = NULL;}

首先我们先完成蛇身的创建,接下来就是我们如何将蛇身去链接起来。

为了方便起见我们可以将蛇头设定为链表的头将蛇的尾巴设定为链表的尾 ,也就是说我们需要从蛇尾进行创建。那么当我们的Psnake为空时我们将pcur的信息赋予给我们的Psnake,我们在传参时将我们的蛇数据的维护为Psnake设定为ps。

并且运用头插的方式进行依次插入:

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

 以及将蛇的起始位置定位到自己像定位的位置进行打印(依自己的喜好来定):

	//打印蛇身pcur = ps->pSnake;while (pcur){Setpos(pcur->x, pcur->y);wprintf(L" % lc",BODY);pcur = pcur->next;}

 接下来就是将ps内容的其他数据进行初始化:

//设置贪吃蛇的其他内容ps->dir = RIGHT;ps->FoodWeight = 10;ps->pFood = NULL;ps->Score = 0;ps->SleepTime = 200;ps->statue = OK;

 (2)食物的生成

关于⻝物,就是在墙体内随机⽣成⼀个坐标(x坐标必须是2的倍数),坐标不能和蛇的⾝体重合,然 后打印★。

 先随机⽣成⻝物的坐标

x坐标必须是2的倍数
⻝物的坐标不能和蛇⾝每个节点的坐标重复
创建⻝物节点,打印⻝物

为了方便我们同样可以用宏来进行定义:

#define FOOD L'★'
	int x = 0;int y = 0;again:do{x = rand() % 53 + 2;y = rand() % 24 + 1;} while (x % 2 != 0);pSnakeNode pcur = ps->pSnake;while (pcur){if (x==pcur->x && y==pcur->y){goto again;}pcur = pcur->next;}pSnakeNode food = (pSnakeNode)malloc(sizeof(SnakeNode));if (food == NULL){perror("CreatFood::malloc");return;}food->x = x;food->y = y;ps->pFood = food;

创建好食物信息之后就是进行食物的打印:

	//打印食物Setpos(x,y );wprintf(L"%lc", FOOD);

三.游戏运行

1.游戏的规则分数以及食物权重的打印

在上面我们打印地图时没有对分数以及规则的打印,现在我们来进行对这一部分的打印。

在玩游戏时我们的分数以及食物的权重是会变化的,但是规则内容不会变则我们要将规则放到循环外面,分数以及食物权重放到循环内部。

循环我们可以设定一下什么情况下结束游戏什么情况下游戏正常运行,并且我们必须要进入函数一回才能正常运行游戏。所以我们可以使用do while函数。

首先完成对规则的打印:

	Setpos(62, 15);printf("1.使用↑ ↓← →来控制蛇的方向。");Setpos(62, 16);printf("2.F3,F4来实现加速和减速。");Setpos(62, 17);printf("3.加速会获得更高的分数。");Setpos(62, 18);printf("4.不能穿墙,不能碰到自己。");Setpos(62, 19);printf("版权来自@xxx");

将分数打印到循环的内部: 

    Setpos(62, 14);printf("得分:%05d   食物权重:%02d", ps->Score, ps->FoodWeight);

2.检测按键是否被按过

上一篇文章有讲到过按键的检测,为了方便使用我们用宏定义这个函数:

#define KEY_PRESS(VK) ((GetAsyncKeyState(VK)&0x1) ? 1 : 0)

并且我们可以根据每个按键的虚拟键码来检测是否按过。

我们需要用到的按键分别有↑ ,↓,←, →,F3 , F4, " ",ESC。 

当按下加速或者减速键时根据自己喜好调节速度加减,减速以及分数增加的多少与分数减少多少。

并且蛇转向的方向不能是蛇身移动的对立方向。

代码如下:

		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_LEFT) && ps->dir !=RIGHT){ps->dir = LEFT;}else if (KEY_PRESS(VK_RIGHT) && ps->dir != LEFT){ps->dir = RIGHT;}else if (KEY_PRESS(VK_ESCAPE)){ps->statue = ESC;break;}else if (KEY_PRESS(VK_SPACE)){GamePause();}else if (KEY_PRESS(VK_F3)){if (ps->SleepTime >= 80){ps->SleepTime -= 30;ps->FoodWeight += 2;}}else if (KEY_PRESS(VK_F4)){if (ps->FoodWeight > 2){ps->SleepTime += 30;ps->FoodWeight -= 2;}}

3.贪吃蛇的移动

我们在移动时无非也就是这4种情况。下面我们来分别对这几种情况进行编写:

switch (ps->dir){case UP:NEXT->x = ps->pSnake->x;NEXT->y = ps->pSnake->y - 1;break;case DOWN:NEXT->x = ps->pSnake->x;NEXT->y = ps->pSnake->y + 1;break;case LEFT:NEXT->x = ps->pSnake->x-2;NEXT->y = ps->pSnake->y;break;case RIGHT:NEXT->x = ps->pSnake->x + 2;NEXT->y = ps->pSnake->y;break;}

我们将可能发生的几种情况下一步位置的信息储存到一个NEXT指针中,方便后面进行的头插与打印:

	pSnakeNode NEXT = (pSnakeNode)malloc(sizeof(SnakeNode));if (NEXT == NULL){perror("SnakeMove::malloc");return;}NEXT->next = NULL;

我们贪吃在移动时可能会面临两种情况:

1.下一步移动位置是食物。

2.下一步移动位置不是食物。

(1)下一步移动位置是食物

如果下一步是食物那么我们就不用对尾部的链表进行删除,只需要将我们的NEXT插入到我们蛇的头部并且顺带将蛇身也进行打印以及分数的增加也就是这样:

NEXT->next = ps->pSnake;ps->pSnake = NEXT;pSnakeNode pcur = ps->pSnake;while (pcur){Setpos(pcur->x, pcur->y);wprintf(L"%lc", BODY);pcur = pcur->next;}ps->Score += ps->FoodWeight;

下面就是对食物的释放以及重新放置新的食物:

	//释放旧的食物free(ps->pFood);//创建新的食物CreadFood(ps);

(2)下一步移动位置不是食物 

 这个情况相当与上面的情况比较复杂一点,涉及到了尾部链表的释放,其他都与上面没有什么区别(注意:将释放掉的空间打印为空格):

NEXT->next = ps->pSnake;ps->pSnake = NEXT;pSnakeNode pcur = ps->pSnake;while (pcur->next->next){Setpos(pcur->x, pcur->y);wprintf(L"%lc", BODY);pcur = pcur->next;}Setpos(pcur->next->x, pcur->next->y);printf("  ");free(pcur->next);pcur->next = NULL;

4.检测是否撞墙或咬到自己

这两种就比较简单了只需要遍历并观察是否与墙的坐标重合,以及身体有没有与头部坐标重合即可。

检测是否撞墙:

	if (ps->pSnake->x == 0 ||ps->pSnake->x == 56 ||ps->pSnake->y == 0 ||ps->pSnake->y == 25){ps->statue = KILL_BY_WALL;}

检测是否咬到自己:

pSnakeNode pcur = ps->pSnake->next;while (pcur){if (pcur->x == ps->pSnake->x && pcur->y == ps->pSnake->y){ps->statue = KILL_BY_SELF;return;}pcur = pcur->next;}

四.游戏结束后的善后

无非也就是将空间回收,以及游戏状态的处理方式,以及一些提示语:

	Setpos(15, 22);switch (ps->statue){case OK:break;case ESC:printf("退出成功\n");break;case KILL_BY_SELF:printf("由于你的操作失误小蛇将自己咬死了\n");break;case KILL_BY_WALL:printf("由于你的操作失误小蛇被撞死了\n");break;}//释放贪吃蛇的资源pSnakeNode pcur = ps->pSnake;pSnakeNode del = NULL;while (pcur){del = pcur;pcur = pcur->next;free(del);del = NULL;}free(ps->pFood);ps->pFood = NULL;

五.完整代码的实现

1.snake.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
#include<locale.h>
#include<stdbool.h>
#include<time.h>#define WALL L'□'
#define BODY L'●' //★○●◇◆□■
#define FOOD L'★' //★○●◇◆□■#define KEY_PRESS(VK) ((GetAsyncKeyState(VK)&0x1) ? 1 : 0)
//初始蛇的位置
#define POS_X 24
#define POS_Y 5
//贪吃蛇移动方向
enum DIR {UP=1,DOWN,LEFT,RIGHT,
};
//游戏进行的状态
enum STATUE {OK=1,ESC,KILL_BY_WALL,KILL_BY_SELF,
};
//创建一个蛇的链表
typedef struct SnakeNode {int x;int y;struct SnakeNode* next;
}SnakeNode,*pSnakeNode;//贪吃蛇各个数据维护
typedef struct Snake
{pSnakeNode pSnake;//蛇的信息pSnakeNode pFood;//食物信息enum DIR dir;//蛇运动的方向enum STATUE statue;//游戏运行的状态int Score;//分数int FoodWeight;//食物权重int SleepTime;//速度(休眠时间)
}Snake,*pSnake;//游戏开始准备工作
void BeforeGame(pSnake ps);
//游戏开始时的界面打印
void GameShow();
//初始化蛇
void InitSnake(pSnake ps);
//创建食物
void CreadFood(pSnake ps);
//游戏中的内容
void Gameing(pSnake ps);
//游戏旁的操作内容
void GameWarn();
//游戏暂停
void GamePause();
//贪吃蛇的移动
void SnakeMove(pSnake ps);
//移动的目的地有食物
void EatFoof(pSnake ps,pSnakeNode NEXT);
//判断蛇头移动的位置是不是食物
int ISfoog(pSnake ps,pSnakeNode NEXT);
//移动的目的地不是食物
void NotEatFood(pSnake ps,pSnakeNode NEXT);
//检测是否撞墙
void IFWall(pSnake ps);
//检测是否咬到自己
void IFSelf(pSnake ps);
//游戏结束
void GameEnd(pSnake ps);
void Setpos(int x, int y);

2.snake.c

#include"snake.h"
//玩游戏前的准备
void Setpos(int x, int y)
{HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);COORD pos = { x, y };SetConsoleCursorPosition(handle, pos);
}
void GameShow()
{//第一界面Setpos(40, 12);printf("欢迎来到贪吃蛇小游戏!");Setpos(40, 25);system("pause");system("cls");//第二界面Setpos(30, 12);printf("请使用↑ ↓← →来控制蛇的方向。");Setpos(30, 13);printf("使用F3,F4来实现加速和减速,加速能得到更高的分数。");Setpos(30, 25);system("pause");system("cls");//打印地图int i = 0;// 上for (i = 0; i < 57; i += 2){Setpos(i, 0);wprintf(L"%lc", WALL);}// 下for (i = 0; i < 57; i += 2){Setpos(i, 25);wprintf(L"%lc", WALL);}//左for (i = 0; i < 25; i += 1){Setpos(0, i);wprintf(L"%lc", WALL);}//右for (i = 0; i < 25; i += 1){Setpos(56, i);wprintf(L"%lc", WALL);}}
//初始化蛇
void InitSnake(pSnake ps)
{int i = 0;pSnakeNode pcur = NULL;for (i = 0; i < 5; i++){pcur = (pSnakeNode)malloc(sizeof(SnakeNode));if (pcur == NULL){perror("InitSnake():malloc()");return;}pcur->x = POS_X + 2 * i;pcur->y = POS_Y;pcur->next = NULL;if (ps->pSnake == NULL){ps->pSnake = pcur;}else{pcur->next = ps->pSnake;ps->pSnake = pcur;}}//打印蛇身pcur = ps->pSnake;while (pcur){Setpos(pcur->x, pcur->y);wprintf(L" % lc",BODY);pcur = pcur->next;}//设置贪吃蛇的其他内容ps->dir = RIGHT;ps->FoodWeight = 10;ps->pFood = NULL;ps->Score = 0;ps->SleepTime = 200;ps->statue = OK;}
//创建食物void CreadFood(pSnake ps)
{int x = 0;int y = 0;again:do{x = rand() % 53 + 2;y = rand() % 24 + 1;} while (x % 2 != 0);pSnakeNode pcur = ps->pSnake;while (pcur){if (x==pcur->x && y==pcur->y){goto again;}pcur = pcur->next;}pSnakeNode food = (pSnakeNode)malloc(sizeof(SnakeNode));if (food == NULL){perror("CreatFood::malloc");return;}food->x = x;food->y = y;ps->pFood = food;//打印食物Setpos(x,y );wprintf(L"%lc", FOOD);}void BeforeGame(pSnake ps)
{//设置控制台的行和列system("mode con cols=100 lines=30");//设置控制台额名称system("title 贪吃蛇");//隐藏光标//获取设备句柄HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);//获取光标信息CONSOLE_CURSOR_INFO CurInfor;GetConsoleCursorInfo(handle, &CurInfor);//修改光标信息CurInfor.bVisible = false;SetConsoleCursorInfo(handle, &CurInfor);//游戏开始界面的设计GameShow();//初始化蛇InitSnake(ps);//创建食物CreadFood(ps);
}
//游戏旁的操作内容void GameWarn()
{Setpos(62, 15);printf("1.使用↑ ↓← →来控制蛇的方向。");Setpos(62, 16);printf("2.F3,F4来实现加速和减速。");Setpos(62, 17);printf("3.加速会获得更高的分数。");Setpos(62, 18);printf("4.不能穿墙,不能碰到自己。");Setpos(62, 19);printf("版权来自@xxx");}
//游戏暂停
void GamePause()
{while (1){Sleep(100);if (KEY_PRESS(VK_SPACE)){break;}}
}
//判断蛇头移动的位置是不是食物
int ISfoog(pSnake ps, pSnakeNode NEXT)
{if (ps->pFood->x == NEXT->x && ps->pFood->y == NEXT->y){return 1;}else{return 0;}
}
//移动的目的地有食物
void EatFoof(pSnake ps, pSnakeNode NEXT)
{NEXT->next = ps->pSnake;ps->pSnake = NEXT;pSnakeNode pcur = ps->pSnake;while (pcur){Setpos(pcur->x, pcur->y);wprintf(L"%lc", BODY);pcur = pcur->next;}ps->Score += ps->FoodWeight;//释放旧的食物free(ps->pFood);//创建新的食物CreadFood(ps);
}
void NotEatFood(pSnake ps, pSnakeNode NEXT)
{NEXT->next = ps->pSnake;ps->pSnake = NEXT;pSnakeNode pcur = ps->pSnake;while (pcur->next->next){Setpos(pcur->x, pcur->y);wprintf(L"%lc", BODY);pcur = pcur->next;}Setpos(pcur->next->x, pcur->next->y);printf("  ");free(pcur->next);pcur->next = NULL;
}
//检测是否撞墙
void IFWall(pSnake ps)
{if (ps->pSnake->x == 0 ||ps->pSnake->x == 56 ||ps->pSnake->y == 0 ||ps->pSnake->y == 25){ps->statue = KILL_BY_WALL;}}
//检测是否咬到自己
void IFSelf(pSnake ps)
{pSnakeNode pcur = ps->pSnake->next;while (pcur){if (pcur->x == ps->pSnake->x && pcur->y == ps->pSnake->y){ps->statue = KILL_BY_SELF;return;}pcur = pcur->next;}
}
//贪吃蛇的移动
void SnakeMove(pSnake ps)
{pSnakeNode NEXT = (pSnakeNode)malloc(sizeof(SnakeNode));if (NEXT == NULL){perror("SnakeMove::malloc");return;}NEXT->next = NULL;switch (ps->dir){case UP:NEXT->x = ps->pSnake->x;NEXT->y = ps->pSnake->y - 1;break;case DOWN:NEXT->x = ps->pSnake->x;NEXT->y = ps->pSnake->y + 1;break;case LEFT:NEXT->x = ps->pSnake->x-2;NEXT->y = ps->pSnake->y;break;case RIGHT:NEXT->x = ps->pSnake->x + 2;NEXT->y = ps->pSnake->y;break;}//判断蛇头移动的位置是不是食物if (ISfoog(ps, NEXT)){//移动的目的地有食物EatFoof(ps, NEXT);}else{//移动的目的地不是食物NotEatFood(ps, NEXT);}//检测是否撞墙IFWall(ps);//检测是否咬到自己IFSelf(ps);
}//游戏开始的内容
void Gameing(pSnake ps)
{//游戏旁的操作内容GameWarn();do {// 当前的得分以及食物的权重Setpos(62, 14);printf("得分:%05d   食物权重:%02d", ps->Score, 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_LEFT) && ps->dir !=RIGHT){ps->dir = LEFT;}else if (KEY_PRESS(VK_RIGHT) && ps->dir != LEFT){ps->dir = RIGHT;}else if (KEY_PRESS(VK_ESCAPE)){ps->statue = ESC;break;}else if (KEY_PRESS(VK_SPACE)){GamePause();}else if (KEY_PRESS(VK_F3)){if (ps->SleepTime >= 80){ps->SleepTime -= 30;ps->FoodWeight += 2;}}else if (KEY_PRESS(VK_F4)){if (ps->FoodWeight > 2){ps->SleepTime += 30;ps->FoodWeight -= 2;}}//贪吃蛇的移动SnakeMove(ps);//休眠一下Sleep(ps->SleepTime);} while (ps->statue==OK);}
//游戏结束
void GameEnd(pSnake ps)
{Setpos(15, 22);switch (ps->statue){case OK:break;case ESC:printf("退出成功\n");break;case KILL_BY_SELF:printf("由于你的操作失误小蛇将自己咬死了\n");break;case KILL_BY_WALL:printf("由于你的操作失误小蛇被撞死了\n");break;}//释放贪吃蛇的资源pSnakeNode pcur = ps->pSnake;pSnakeNode del = NULL;while (pcur){del = pcur;pcur = pcur->next;free(del);del = NULL;}free(ps->pFood);ps->pFood = NULL;
}

3.tets.c

#include"snake.h"void test1()
{srand((unsigned int)time(NULL));int ch=0;do {Snake snake = { 0 };//游戏的准备工作BeforeGame(&snake);//游戏内容Gameing(&snake);//游戏结束GameEnd(&snake);Setpos(20, 15);printf("是否再来一次(Y/N)");ch = getchar();getchar();} while (ch == 32 || ch == 32+32);}
int main()
{//将类项改为当前地区setlocale(LC_ALL, "");test1();return 0;
}

好了兄弟们这就是贪吃蛇的完整内容了,喜欢的朋友们一键三连支持一下。

毕竟你们的支持才是博主的动力嘛!也请大佬们指点。

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

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

相关文章

three.js 按键W前进、S退后、A左转、D右转运动

效果&#xff1a;W 键 前进&#xff1b;S 键后退&#xff1b;A 键左转&#xff1b;D 键右转&#xff1b;使用了 tween.js 动画库&#xff1b; 代码&#xff1a; <template><div><el-container><el-main><div class"box-card-left">&…

如何利用AWS CloudFront 自定义设置SSL

Amazon CloudFront 提供三种选项&#xff0c;可以加速整个网站并从 CloudFront 的边缘站点通过安全的 HTTPS 方式交付内容。除能够安全地从边缘站点交付内容外&#xff0c;您还可以配置 CDN 来使用针对源提取的 HTTPS 连接&#xff0c;这样您的数据就会实现从源到最终用户的端到…

仿牛客网项目---项目总结

本篇文章是对整个项目的一个总结。下面这张图要好好理解。 整个项目都是构建在SpringBoot之上的&#xff0c;所以把它画到最底下&#xff0c;其它技术依托在springboot之上。但是springboot并不是技术的核心&#xff0c;而只是起到了一个辅助的作用&#xff0c;它的作用仅仅是降…

vue之性能优化

1.路由懒加载 所谓路由懒加载&#xff0c;其实就是路由通过import动态引入&#xff0c;而不是在文件最上面一个个全部引入&#xff0c;因为JS执行的时候会优先执行引入的文件&#xff0c;如果一次性引入过多&#xff0c;则会增加处理时长。 2.图片懒加载 图片在网页加载过程…

svg简单教程

推荐查看这个视频 一小时讲完SVG 简介 scalable 英 /ˈskeɪləbl/ 美 /ˈskeɪləbl/ adj. &#xff08;计算机&#xff09; 可扩展的&#xff1b;可改变大小的&#xff0c;可缩放的&#xff1b;可攀登的&#xff1b;可称量的&#xff1b;可去鳞的 vector 英 /ˈvektə/ 美…

搭建prometheus、grafana监控平台

程序员的公众号&#xff1a;源1024&#xff0c;获取更多资料&#xff0c;无加密无套路&#xff01; 最近整理了一波电子书籍资料&#xff0c;包含《Effective Java中文版 第2版》《深入JAVA虚拟机》&#xff0c;《重构改善既有代码设计》&#xff0c;《MySQL高性能-第3版》&…

php调用guzzlehttp库时出现Segmentation fault的解决方案

先说结论&#xff0c;这个问题的原因是因为php7.4与openssl3不兼容产生的&#xff0c;解决方案如下&#xff1a; 输入openssl version -a查看openssl版本&#xff0c;如果是3以上的版本与php7.4不兼容&#xff0c;7.4以下的没测试过&#xff0c;估计也有问题。我最终是安装上了…

安装配置Spark集群

安装Spark集群主要包括以下步骤&#xff1a; 1、下载Spark安装包&#xff0c;在各节点中安装部署spark集群 2、配置整合 3、启动并测试 下载Spark 可以从官方网站下载合适的版本。当前环境已经提供了安装包&#xff0c;存放在 /opt/software目录下。 在node1节点上安装Sp…

SpringCloudAlibaba 网关gateway整合sentinel日志默认路径修改

SpringCloudAlibaba 网关gateway整合sentinel 实现网关限流熔断 问题提出 今天运维突然告诉我 在服务器上内存满了 原因是nacos日志高达3G,然后将日志文件发给我看了一下之后才发现是gateway整合sentinel使用了默认日志地址导致日志生成地址直接存在与根路径下而且一下存在多…

第16章——西瓜书强化学习

在强化学习中&#xff0c;智能体通过与环境的交互来学习如何做出决策。在每个时间步&#xff0c;智能体观察当前的环境状态&#xff0c;并根据其策略选择一个动作。环境会对智能体的动作做出响应&#xff0c;并给出一个奖励信号&#xff08;reward&#xff09;&#xff0c;该信…

安装zabbix

部署Zabbix监控平台 部署一台Zabbix监控服务器&#xff0c;一台被监控主机&#xff0c;为进一步执行具体的监控任务做准备&#xff1a; 安装LNMP环境源码安装Zabbix安装监控端主机&#xff0c;修改基本配置初始化Zabbix监控Web页面修改PHP配置文件&#xff0c;满足Zabbix需求…

zeta新增三个任务教程,即将刷新,速撸

这期是延续上期的教程&#xff0c;前面的任务不变&#xff0c;所以直接复制的前面的教程&#xff0c;多了三个任务更新在后面。 简单说一下&#xff0c;zeta是已经发币的公链项目&#xff0c;但是它社区还有6%的用户激励token份额没发完&#xff0c;做主网的几个简单任务可以获…

「CISP题库精讲」CISP题库习题解析精讲5道

前言 本节只要对CISP考试中的5道习题进行详细的讲解,时间比较少,敲多少道,就算多少道,反正全部也就1400多道。 习题部分 第一题 某企业内网中感染了一种依靠移动存储进行传播的特洛伊木马病毒,由于企业部署的杀毒软件,为了解决该病毒在企业内部传播,作为信息化负责人…

文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《含海上风电制氢的综合能源系统分布鲁棒低碳优化运行》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

U盘文件剪切丢失如何挽救?专家教你两招轻松恢复

一、遭遇U盘文件剪切丢失&#xff0c;你该怎么办&#xff1f; 在日常办公和生活中&#xff0c;U盘作为便捷的移动存储设备&#xff0c;常常承载着重要的文件和数据。然而&#xff0c;有时我们会遇到这样一个令人头疼的问题&#xff1a;明明在电脑上将U盘中的文件剪切到了某个位…

SQL 中: 索引的建立和删除

目录 实验过程创建索引修改索引删除索引查询索引查看索引信息分析索引待续、更新中 实验过程 1 在STUDENT表的sno列上创建一个非聚簇索引&#xff0c;索引名为“student_sno_idx”。 CREATE INDEX student_sno_idx ON STUDENT (sno);2.在STUDENT表上按sno的升序&#xff0c;…

【Java】:按位与、按位或

按位与运算符&#xff08; & &#xff09; 当且仅当两个操作数的二进制的某一位均非0时&#xff0c;该位的结果才为1。 int a 5; int b 3; int c a & b; //c 1// 0 1 0 1 a 5 // 0 0 1 1 b 3 // 0 0 0 1 c 1按位或操作符&#xff08; | &#xff09;&#xff…

【脚本玩漆黑的魅影】全自动对战宫殿

文章目录 原理主要代码全部代码 原理 对战宫殿是让宠物自己打&#xff0c;不需要我们选技能&#xff0c;所以用来刷对战点数很合适。 需要准备三个主力。 主要是根据屏幕截图进行各种操作。 1&#xff0c;外面的对话&#xff0c;除了选自由级以外&#xff0c;其他都是直接点…

Exception异常处理

1. 两种异常处理机制 1.1 使用 throw 关键字手动抛出异常 使用throw关键字抛出异常&#xff0c;代码会的显得简单明了 如下图所示 1.2 使用 try-catch 捕获异常 使用try-catch进行捕获异常&#xff0c;往往会使代码变得更加笼统&#xff0c;层层包裹 如下图所示 2. 自定义…

mybatisplus的条件构造器

条件构造器wrapper&#xff0c;主要用于构造sql语句的where条件&#xff0c;他更擅长这个&#xff0c;但也可以用于构造其他类型的条件&#xff0c;比如order by、group by等。 条件构造器的使用经验&#xff1a; 基于QueryWrapper的查询 练习1. void testQueryWrapper(){Q…