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.hqwc.cn/news/529727.html

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

相关文章

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

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

【DH法】——机器人运动学正逆解

描述关节姿态 串联机器人的关节由电机连杆组成&#xff0c;如下图所示&#xff1a; 图1 PUMA560机器人结构模型 图2 PUMA560机器人实物 PUMA 560 robot in the experiment. | Download Scientific Diagram (researchgate.net)

车载诊断协议DoIP系列 —— AL IPv6地址分配通用DoIP报头结构

车载诊断协议DoIP系列 —— AL IPv6地址分配&通用DoIP报头结构 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师(Wechat:gongkenan2013)。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 本就是小人物,输了就是输了,不要在意别人怎么看自…

题目:珠宝的最大交替和(蓝桥OJ 3791)

问题描述&#xff1a; 解题思路&#xff1a;&#xff08;思路样例从0开始赋值&#xff09; 注意点&#xff1a;1.S需要开long long 2.需要考虑如果交换的差值&#xff08;即Aj - Ai)为负数的情况。 题解&#xff1a;&#xff08;实例代码为从1开始赋值&#xff0c;因此奇偶要与…

来,我们把LangChain了解一下

目录 LangChain简介 LangChain Experssion Language 常见API key申请 LangChain简介 最近要学的东西可太多了&#xff0c;好的&#xff0c;我们先来看看LangChain是什么东西&#xff0c;咱就是说开干吧&#xff1a; pip install langchain Get started吧&#xff1a;Get …

C语言——递归题

对于递归问题&#xff0c;我们一定要想清楚递归的结束条件&#xff0c;每个递归的结束条件&#xff0c;就是思考这个问题的起始点。 题目1&#xff1a; 思路&#xff1a;当k1时&#xff0c;任何数的1次方都是原数&#xff0c;此时返回n&#xff0c;这就是递归的结束条件&#…

Vue3 + antv/x6 实现流程图

新建流程图 // AddDag.vue <template><div class"content-main"><div class"tool-container"><div click"undo" class"command" title"后退"><Icon icon"ant-design:undo-outlined" /…

深耕版本控制、代码质量与安全等领域,龙智荣获“Perforce 2023年度合作伙伴”奖项

在近日举行的Perforce 2024合作伙伴峰会上&#xff0c;龙智被评选为“Perforce 2023年度合作伙伴”。这一奖项不仅是对龙智在中国市场开拓中的进取精神与丰硕成果的高度认可&#xff0c;也是Perforce公司对于龙智持续创新精神及专业技术与服务的表彰。 自2012年成为Perforce中…

PyCharm无代码提示解决

PyCharm无代码提示解决方法 在使用PyCharm工具时&#xff0c;调用方法却无法进行提示&#xff0c;针对PyCharm无代码提示整理下解决方案 1、Python内置语法无智能提示 复现&#xff1a;我这里以urllib库读取网页内容为例&#xff0c;在通过urlopen(&#xff09;之后调用getur…

强烈推荐—GpuMall智算云实例网盘操作详解

实例网盘为实例的 /gm-fs 目录&#xff0c;该目录为实例同一个数据中心的分布式存储&#xff0c;对于较大的文件或者压缩文件有着出色的读写性能&#xff0c;实例网盘不受实例删除/释放影响&#xff0c;采用分布式冗余存储&#xff0c;数据安全性较高&#xff0c;强烈建议使用网…

jvm八股

文章目录 运行时数据区域Java堆对象创建对象的内存布局对象的访问定位句柄直接指针 GC判断对象是否已死引用计数算法可达性分析算法 引用的类别垃圾收集算法分代收集理论标记清除算法标记复制算法标记整理算法 实现细节并发的可达性分析 垃圾收集器serial收集器ParNew收集器Par…

go语言基础 -- 文件操作

基础的文件操作方法 go里面的文件操作封装在os包里面的File结构体中&#xff0c;要用的时候最好去查下官方文档&#xff0c;这里介绍下基本的文件操作。 打开关闭文件 import("os" ) func main() {// Open返回*File指针&#xff0c;后续的操作都通过*File对象操作…