c_贪吃蛇(含小蛇移动和吃到食物增长的算法原理)

关于贪吃蛇我认为最难实现的部分是如何控制小蛇的移动,还有吃到食物后小蛇变长的问题。
这个图可以解释:
在这里插入图片描述
小蛇移动:
第一步用12345个数字记录小蛇的位置,然后使所有的小蛇位置数字加一。
第二步使小蛇的最大值位置处变为0,就相当于那个位置消失了。
第三步使最小值的上/下/左/右位置(根据按键判断)的元素变为1。

小蛇吃到食物后变长:
上面的第二步是使最大值变为0,我们可以试想一下 如果吃到食物,最大值就不变为0了,那么这不就相当于小蛇变长了吗?这时,我们只需要加一个if else判断是否吃到食物即可。

头文件以及全局变量

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

#define high 26
#define width 46

int num[high][width] = {0}; //边框
int movesnake; //小蛇移动
int food_x, food_y;//食物
int score;//计分

防闪屏

void gotoxy(int x, int y) {//光标移动到 x,y位置防闪屏
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
	COORD pos;
	pos.X = x;
	pos.Y = y;
	SetConsoleCursorPosition(handle, pos);
}

隐藏光标

void HideCursor() {//隐藏光标防止闪烁
	CONSOLE_CURSOR_INFO cursor_info = { 1, 0 };
	SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}

初始化界面

void startup() {
	//边框初始化
	for (int i = 0; i < high; i++) {
		num[i][0] = -1;
		num[i][width - 1] = -1;
	}
	for (int j = 0; j < width; j++) {
		num[0][j] = -3;
		num[high - 1][j] = -3;
	}
	//小蛇初始化
	num[high / 2][width / 2] = 1;
	for (int i = 1; i <= 4; i++) {
		num[high / 2][width / 2 - i] = i + 1;
	}
	movesnake = 4;//初始化蛇的移动方向
	HideCursor();
	//初始化食物
	food_x = rand() % (high - 5) + 2;
	food_y = rand() % (width - 5) + 2;
	num[food_x][food_y] = -2;
}

主界面显示

void show() {
	gotoxy(0, 0);
	Sleep(150);
	int i, j;
	for (i = 0; i < high; i++) {
		for (j = 0; j < width; j++) {
			if (num[i][j] == -1) {
				printf("|");
			}
			else if (num[i][j] == -3) {
				printf("_");
			}
			else if (num[i][j] == 0) {
				printf(" ");
			}
			else if (num[i][j] == 1) {
				printf("@");
			}
			else if (num[i][j] > 1) {
				printf("o");
			}
			else if (num[i][j] == -2) {
				printf("$");
			}
		}
		printf("\n");
	}
	printf("得分为:%d\n",score);
}

后台操作

void MoveSnakePostion() {
	int max = 0;
	int snakeback_i=0, snakeback_j=0;//用于记录旧的蛇尾的位置
	int snakefront_i=0, snakefront_j=0;//用于记录旧的蛇头位置
	int newhead_i=0, newhead_j=0;//记录新蛇头位置

	for (int i = 1; i < high - 1; i++) {
		for(int j=1;j<width-1;j++)
			if (num[i][j] > 0) {
				//大于零的部分就是贪吃蛇
				num[i][j]++;//蛇身全部加1
				if (max < num[i][j]) {//取到蛇的最大值部分也就是蛇的尾部
					max = num[i][j];
					snakeback_i = i;//记录蛇尾
					snakeback_j = j;
				}
				if (num[i][j] == 2) {//记录旧的蛇头
					snakefront_i = i;
					snakefront_j = j;
				}
			}
	}

	if (movesnake == 1)//向上
	{
		newhead_i = snakefront_i - 1;
		newhead_j = snakefront_j;
	}
	if (movesnake == 2)//向下
	{
		newhead_i = snakefront_i + 1;
		newhead_j = snakefront_j;
	}
	if (movesnake == 3)//向左
	{
		newhead_i = snakefront_i;
		newhead_j = snakefront_j - 1;
	}
	if (movesnake == 4)//向右
	{
		newhead_i = snakefront_i;
		newhead_j = snakefront_j + 1;
	}
	if (num[newhead_i][newhead_j] == -2)
	{       
		//当小蛇碰到食物 蛇的尾部就不需要变为零就相当于长度加1了
		num[food_x][food_y] = 0;//食物原始位置归零 产生新食物
		food_x = rand() % (high - 5) + 2;
		food_y = rand() % (width - 5) + 2;
		num[food_x][food_y] = -2;
		score++;
	}
	//当小蛇没吃到食物  
	else  num[snakeback_i][snakeback_j] = 0;//蛇身最大值的元素也就是蛇尾蛇尾变为0,蛇身就相当于长度不变

	if (num[newhead_i][newhead_j] > 0 || num[newhead_i][newhead_j] == -1 || num[newhead_i][newhead_j] == -3 ) {
		printf("Game Over\n\n");
		exit(0);
	}
	else num[newhead_i][newhead_j]= 1;
}
void back() {
	MoveSnakePostion();
			
}

人机交互

void front(){
	char input;
	if (kbhit()) {
		input = getch();
		if (input == 'a')
			movesnake = 3;
		if (input == 's')
			movesnake = 2;
		if (input == 'w')
			movesnake = 1;
		if (input == 'd')
			movesnake = 4;
	}
}

主界面

int main() {
	startup();
	while (1) {
		show();
		front();
		back();
	}
}

实现:
在这里插入图片描述

CJds_snakeView类 Struct list { int x; int y; }; 点结构,x表示横坐标,y表示纵坐标。 成员变量: int start;start=1开始游戏,start=0停止游戏。 int difficulty;表示游戏难度,等于10表示容易,等于6表示普通,等于3表示困难,等于2表示特困。 int last_aspect;表示蛇之前前进的方向,用于判断防止蛇逆行的。 int can_new;表示是否添加新食物。等于1表示产生新的食物,等于0表示产生之后不不要再产生食物。 int count;表示蛇的节数; CRect rct;表示矩形方格; list a[100];保存蛇的长度; list b;用来保存蛇头的坐标位置; int aspect;表示蛇前进的方向 等于0表示蛇向右前进; 等于1表示蛇向下前进; 等于2表示蛇向左前进; 等于3表示蛇向上前进; int xx;表示食物的x坐标; int yy;表示食物的y坐标; 成员函数: void Init();初始化蛇的节数,并确定了节数的坐标位置。首先初始化蛇的前进方向aspect=0是向右前进的,last_aspect=0用来保存蛇当前前进的方向。并且初始化蛇的节数为4节,并指明了它们的坐标位置。can_new=1表示产生一个新的食物。 void aliveordie();判断蛇是死还是活着。有两种情况,一种是蛇自己撞到自己,表示死了,start=0从新开始游戏,另一种是超出了界面(20,20,420,420)撞到了墙start=0也从新开始游戏。 double random(double start,double end);在start和end坐标之间产生随即数; 消息处理事件: (1)void onTimer(UINT nIDEvent);在OnCreate()创建计时器SetTimer(),来触发OnTimer事件,所以要首先销毁时间计时器,然后调用aliveordie()函数判断蛇的生死情况,CString str_count; str_count.Format("分数:%d",count-4)显示蛇的节数,TextOut()指出坐标输出文本,创建设备上下文,和创建位图。然后把位图选择到设备上下文上,填充颜色为白色。 在位图上绘制两个矩形线框: Rectangle(CRect(10,10,440,440)); Rectangle(CRect(20,20,430,430)); 显示位图(BitBlt(0,0,1000,1000,&MenDC,0,0,SRCCOPY)); 判断如果游戏开始(start==1),b.x=a[0].x用b.x来保存蛇头的横坐标;b.y=a[0].y用b.y来保存蛇头的纵坐标。如果aspect==0表示蛇向右前进,aspect=1表示蛇向下前进,aspect==2表示蛇向左前进,aspect==3表示蛇向上前进,a[1].x=b.x;a[1].y=b.y;把蛇头的坐标付给了a[1],说明蛇头改变了前进的方向。绘制蛇头矩形方格,并且设置蛇头的颜色为红色,蛇身是三个黄色的矩形方格。if (a[0].x==xx && a[0].y==yy)判断蛇头的位置与食物的关系,现在的情况说明蛇食物,蛇的节数加一,各个节数的坐标向前进一位。调用random()函数产生随即的食物,然后判断食物随即产生的位置与蛇的位置,如果产生的食物在蛇身体上,要从新调用random()函数随即再产生食物。产生的食物颜色为绿色。int m_timer=SetTimer(1,difficulty*30,NULL);计时间隔,计时间隔的快慢是根据难易程度的不而确定的。销毁位图、销毁设备上下文。 (2)OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);判断蛇当前前进的方向,当aspect返回0,表示蛇前进的方向是向右,当aspect返回1,表示蛇前进的方向是下,当aspect返回2,表示蛇前进的方向是向左,当aspect返回3,表示蛇前进的方向是向上。 (3)点击菜单按钮调用以下函数: OnDifficultyEasy();OnDifficultyHard();OnDifficultyNormal();OnDifficultyVeryhard();OnButtonStart();
### 回答1: 在C语言编写的贪吃蛇游戏中,当贪吃蛇到一定分数的食物时,游戏会出现如下的加速效果。 贪吃蛇是一种经典的游戏,玩家需要控制蛇的移动方向,使其食物并不断变长。一开始,贪吃蛇移动速度较慢,但随着贪吃蛇到越来越多的食物,分数也会逐渐增加。当分数达到一定阈值时,游戏会出现加速效果,使得贪吃蛇移动速度变快。 实现这个功能,首先需要获得游戏中的贪吃蛇得分。在C语言中,可以使用一个整数变量来代表分数。每当贪吃蛇食物时,分数加一,并将新的分数显示在游戏界面上。 接下来,需要设置一个阈值来判断何时触发加速效果。当分数达到设定的阈值时,加速效果就会被触发。可以使用一个if语句来比较当前分数和阈值的大小,如果大于等于阈值,则加速。 在C语言中,加速效果可以通过两种方式实现。一种是改变贪吃蛇移动速度,可以通过调整移动的时间间隔来实现加速。另一种是改变贪吃蛇移动步长,可以通过增加每次移动的格子数来实现加速。 在游戏的循环中,需要不断检测当前分数是否达到了阈值,如果达到了,则将移动速度或步长进行调整,以实现加速效果。可以使用条件语句或循环控制语句来实现这个逻辑。 总之,通过适当设置阈值,并在达到一定分数时实现贪吃蛇的加速效果,可以增加游戏的难度和挑战性,让游戏更加有趣。 ### 回答2: 在C语言编写贪吃蛇游戏时,可以通过设置一定的分数目标来触发食物加速的功能。当贪吃蛇到的食物数量达到一定的分数时,游戏可以加速。 在游戏开始时,可以设定一个初始的游戏速度。当贪吃蛇食物时,可以通过判断当前得分是否达到设定的分数目标来确定是否进行加速操作。当得分达到目标时,可以通过减小时间延迟来加快游戏的速度。这样,在每次移动时,贪吃蛇移动就会更加迅速。 在程序编码上,可以使用一个变量来记录当前的得分,并与设定的分数目标进行比较。当得分超过或等于设定的目标分数时,通过相应的代码来修改时间延迟的数值,从而实现加速的效果。 比如,可以使用一个if语句判断当前得分和目标分数的关系,当达到目标分数时,修改一个控制时间延迟的变量的数值,从而实现加速,具体代码如下: ``` int score = 0; // 记录得分 int targetScore = 100; // 分数目标 int delay = 100; // 初始时间延迟 // 游戏循环 while (1) { // 贪吃蛇移动逻辑 // ... // 判断是否达到分数目标 if (score >= targetScore) { // 达到目标分数,加速 delay -= 10; targetScore += 100; // 更新目标分数,为下一次加速做准备 } // 控制移动的速度 sleep(delay); } ``` 在以上代码中,通过不断地比较得分和目标分数的大小关系,可以在达到目标分数时不断地减小时间延迟的值,从而实现游戏的加速效果。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值