贪吃蛇小游戏——C语言编写

1.效果展示

在这里插入图片描述

2.设计思路

2.1图案显示

利用二维数组构建图案,总共有墙壁,蛇头,蛇身,食物,空白五种元素,因此只需要二维数组中的元素有五种不同的值即可;
在这里插入图片描述

在这里插入图片描述

2.2蛇头的移动

贪吃蛇是会自动移动的,我们首先让蛇头能自动移动。由于我们用数组来表示元素在地图中的位置,让元素移动就是让元素的坐标改变。
因此我们需要构建函数来完成蛇头坐标的自动移动,同时需要对我们输入的方向键做出判断,改变移动的方向。
在这里插入图片描述

2.3食物的生成

食物的生成很简单,只要种下一个随机数种子,然后给一个变量用来判断是否生成食物即可,需要注意的是食物的坐标别越界
在这里插入图片描述

2.4蛇身体的生成与移动

蛇身体的计算:
首先,蛇身体的移动前必须产生身体即是否吃到食物,可以给一个变量当计数器来判断有多少截身体;

蛇身体坐标的保存:
我们需要一个结构体数组,结构体数组的每个元素有两个成员x和y值,这两个值就代表我们的身体在二维数组中的坐标,
即一个数组成员就代表一截身体;

蛇身体坐标的获得:
通过计数器来判断是否有身体,当计数器不为0时,蛇就有了身体,第一截身体的坐标来源就是蛇头吃到食物前的坐标;
同理,后面吃到的食物增加,计数器的数值变大,就代表我们的结构体数组有多少个有效元素,然后给结构体数组里面的成员进行赋值;
最后一截身体的数组下标=计数器-1,后面的身体坐标就是前面的身体移动前的坐标,由于我们的头是不断移动的,并且可以直接获得其坐标,所以从最后一截身体开始往前进行拷贝赋值;
由于我们的赋值特点,数组(蛇身)从后往前进行覆盖式拷贝赋值,即完成了蛇身体的移动

没有吃到食物时的细节:
没有吃到食物时,蛇的身体长度是不变的,我们的身体坐标进行改变之后,在二维数组中留下了一个隐患;
在这里插入图片描述
在这里插入图片描述

2.5判断是否撞墙和打印得分

打印得分:得分即身体的长度即计数器的数值

判断是否撞墙:判断蛇头的下一个位置在二维数组中是不是1即是不是墙壁即可
在这里插入图片描述

3.完整代码

#ifndef _SNAKE_H_
#define _SNAKE_H_

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


#define MAX 500 //蛇身个数
#define ROW 20  
#define LINE 20

typedef struct Body
{
	int x;
	int y;
}body;

void MapPrint(char arr[][LINE], int count);//地图打印

void Move(int *row, int *line, char *move);//蛇头移动函数,通过读取输入的键盘方向键来改变蛇头方向

void GetCoordinate(int *row, int *line, char *move);//蛇头自动移动,通过获取的方向信息,决定蛇头往哪个方向自动移

void food(char arr[][LINE], int *x, int *y);//随机生成一个食物

void JudgeFood(int food_x, int food_y, int row, int line, int *count);//判断是否吃到食物

void GetBody(char arr[][LINE], body body[], int count, int temp_x, int temp_y);//蛇体坐标更新

int  Judge(char arr[][LINE], int row, int line);//判断是否撞墙

void Game();


#endif
#include "snake.h"

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 MapPrint(char arr[][LINE],int count)
{	
	gotoxy(0, 0);
	for (int i = 0; i < ROW; i++)
	{
		for (int j = 0; j < LINE; j++)
		{
			//第一行,最后一行,第一列,最后一列都是墙壁
			if (arr[i][j]==1)
				printf("■");

			else if (arr[i][j] == 2)
				printf("⊙");//蛇头

			else if (arr[i][j] == 3)
				printf("¤");//打印食物¤

			else if (arr[i][j] == 4)
				printf("●");//打印身体●

			else
				printf("  ");//一个墙体占两个空格
		}
		printf("\n");
	}
	printf("				\n");
	printf("             当前得分:%d\n", count);
	printf("				\n");
}
void Move(int *row, int *line,char *move)//蛇头移动函数,通过读取输入的键盘方向键来改变蛇头方向
{
		if (GetAsyncKeyState(VK_UP))//上
		{
			*move = 'w';
		}
		else if (GetAsyncKeyState(VK_DOWN))//下
		{
			*move = 's';
		}
		else if (GetAsyncKeyState(VK_LEFT))//左
		{
			*move = 'a';
		}
		else if (GetAsyncKeyState(VK_RIGHT))//右
		{
			*move = 'd';
		}
		GetCoordinate(row, line, move);//将获得的方向键信息传输过去
}

void GetCoordinate(int *row, int *line, char *move)//蛇头自动移动,通过获取的方向信息,决定蛇头往哪个方向自动移
{
	if (*move == 'w')
		(*row)--;
	else if (*move == 's')
		(*row)++;
	else if (*move == 'a')
		(*line)--;
	else if (*move == 'd')
		(*line)++;
}

void food(char arr[][LINE],int *x,int *y)//随机生成一个食物
{
	int flag = 0;
	for (int i = 0; i < ROW; i++)
	{
		for (int j = 0; j < ROW; j++)
		{
			if (arr[i][j] == 3)//食物为3
				flag = 1;
		}
	}
	if (!flag)//没有食物就生成食物
	{
		//食物不能在边框上
		*x = rand() % (ROW-2)+1;
		*y = rand() % (LINE-2)+1;
	}
}

void JudgeFood(int food_x,int food_y,int row,int line,int *count)//判断是否吃到食物
{
	if (food_x == row&&food_y == line)//吃到食物
	{
		(*count)++;//吃到食物身体个数+1
	}
}

void GetBody(char arr[][LINE], body body[], int count, int temp_x, int temp_y)//蛇体坐标更新
{
	//保留前一个蛇体的坐标
	int befor_x = 0;
	int befor_y = 0;
	if (count > 0)//最少有一个蛇身
	{
		//记录下最后一个蛇身的位置
		befor_x = body[count - 1].x;
		befor_y = body[count - 1].y;
	}
	
	
	int keep = count;//保存一份蛇体个数

	while (count)//蛇体坐标覆盖,后面的覆盖前面的
	{
		if (count == 1)//只有一个蛇体时,为原来蛇头位置
		{
			body[count - 1].x = temp_x;
			body[count - 1].y = temp_y;
		}
		else
		{
			body[count - 1].x = body[count - 2].x;
			body[count - 1].y = body[count - 2].y;
		}
		count--;
	}

	while (keep)//将对应的蛇体坐标赋值
	{
		arr[body[keep-1].x][body[keep-1].y] = 4;
		keep--;
	}

	if (befor_x!=0)//最后一个蛇身的上一次所在位置清空
	{
		arr[befor_x][befor_y] = 0;
	}
	
}

int  Judge(char arr[][LINE],int row,int line)//判断是否撞墙
{
	if (arr[row][line] == 1)
	{
		printf("	 --------------\n");
		printf("	|   撞到墙壁   |\n");
		printf("	|   游戏结束   |\n");
		printf("	 --------------\n");
		system("pause");
		return 0;
	}
	return 1;
}

void Game()
{
	char arr[ROW][LINE]=
	{
		{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ,1 },
		{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
		{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
		{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
		{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
		{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
		{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
		{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
		{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
		{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
		{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
		{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
		{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
		{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
		{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
		{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
		{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
		{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
		{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
		{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },

	};//地图

	int row = 10, line = 10;//蛇头起始位置
	arr[row][10] = 2;

	char move = 'w';//蛇头开始往上移动

	int food_x = 0, food_y = 0;//食物的x,y坐标
	srand((unsigned)time(NULL));//随机数种子

	//保留一份蛇头移动前坐标
	int temp_x = row;
	int temp_y = line;

	int count = 0;//蛇身体个数

	body body[MAX] = { 0 };//蛇身坐标记录结构体数组

	while (1)
	{	
		//生成食物
		food(arr, &food_x, &food_y);
		arr[food_x][food_y] = 3;

		MapPrint(arr,count);//打印图形

		if (count==0)
		arr[row][line] = 0;//没有身体的时候,蛇头原来位置变为空白
		
		//保留蛇头移动前的位置
		temp_x = row;
		temp_y = line;

		Move(&row, &line,&move);//蛇头移动

		if (Judge(arr, line, row) == 0)//判断是否撞墙
		{
			break;
		}

		JudgeFood(food_x,food_y,row, line, &count);//判断是否吃到食物
		GetBody(arr, body, count, temp_x, temp_y);//蛇身构造
		arr[row][line] = 2;//新位置变成蛇头

		Sleep(200);//通过控制休眠时间来控制蛇头移动速度
	}
}



#include "snake.h"

int main()
{
	
	Game();
	printf("游戏结束\n");

	system("pause");
	return 0;
}
  • 115
    点赞
  • 418
    收藏
    觉得还不错? 一键收藏
  • 49
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 49
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值