贪吃蛇小游戏——我的第一篇博客

C语言入门者可制作的小游戏

欢迎来到我的博客

我是大一的新生,这是我的第一篇博客,我也是在最近学完了C语言基础,想在这里分享我制作的第一个小游戏——贪吃蛇。在制作贪吃蛇的过程中,我相当于复习了一遍C语言基础,又学习了一些关于C/C++的内容。希望大家能指正我的代码,我将会虚心接受大家的建议。
我的github:https://github.com/YYYYYYYYZ/game_by_yxf

游戏效果

可自定义边框大小、目标、速度。
效果1
在这里插入图片描述

思路

在最初制作贪吃蛇的时候我将其分为了

  • 界面部分
int main()                                                             //界面部分
{
   printf("输入'o'开始游戏,其他键结束游戏\n");
   while (_getch() == 'o')
   {
   	eat = 0, gameover_eat = 0;
   	system("cls");
   	printf("游戏以wsad操作,按'p'键可结束游戏\n请输入边界大小(长,宽)、速度、目标\n");
   	system("pause");
   	system("cls");
   	printf("长(建议50左右):");
   	scanf_s("%d", &lo);
   	printf("宽(建议30左右):");
   	scanf_s("%d", &wi);
   	printf("请输入速度(应为整数2左右):");
   	scanf_s("%d", &speed);
   	printf("请输入目标(自然数):");
   	scanf_s("%d", &goal);
   	system("cls");
   	printf("按任意键开始游戏");
   	switch (control())
   	{
   	case -1:system("cls");
   		printf("游戏结束-失败qwq\n目标为:%d\n最终成绩为:%d\n", goal, gameover_eat);
   		break;
   	default:system("cls");
   		printf("游戏结束-胜利ovo\n目标为:%d\n最终成绩为:%d\n", goal, eat);
   		break;
   	}
   	printf("输入'o'重新开始游戏,其他键结束游戏\n");
   }
}
  • 命令指令行光标移动部分
void move(int x, int y)                                                 //命令指令行光标移动部分
{
   COORD  point = { (SHORT)x ,  (SHORT)y };                             //光标要设置的位置x,y
   HANDLE  HOutput = GetStdHandle(STD_OUTPUT_HANDLE);                   //使用GetStdHandle(STD_OUTPUT_HANDLE)来获取标准输出的句柄
   SetConsoleCursorPosition(HOutput, point);                            //设置光标位置
}
  • wsad的控制及蛇的生成部分
int control()                                                            //wsad的控制及蛇的生成部分
{
   Coordinate* c = (struct Coordinate*)calloc(goal + 3, 2 * sizeof(int));//动态生成结构体数组,为蛇的身躯
   (*c).x = lo / 2 + rand() % 3 + 1;
   (*c).y = wi / 2 + rand() % 3 + 1;
   (*(c + 1)).x = (*(c + 2)).x = 0;
   (*(c + 1)).y = (*(c + 2)).y = 0;
   char temp = 'w', temp_ch = _getch();
   char* ch = &temp_ch;
   int eat_1 = 0;
   while (1)                                                            //前后左右操作
   {
   	if (eat == -1 || eat_1 == -1)
   	{
   		return -1;
   	}
   	if (eat == goal)
   	{
   		return 0;
   	}
   	switch (*ch)
   	{
   	case 'w': temp = 'w';
   		edging_title();                                              //边界输出和计分板输出
   		check((*c).x, (*c).y);                                       //吃的数量赋值和食物生成及检测和边界检测
   		eat_1 = snack_move(0, -1, ch, c);
   		break;
   	case 's': temp = 's';
   		edging_title();
   		check((*c).x, (*c).y);
   		eat_1 = snack_move(0, 1, ch, c);
   		break;
   	case 'a':  temp = 'a';
   		edging_title();
   		check((*c).x, (*c).y);
   		eat_1 = snack_move(-1, 0, ch, c);
   		break;
   	case 'd': temp = 'd';
   		edging_title();
   		check((*c).x, (*c).y);
   		eat_1 = snack_move(1, 0, ch, c);
   		break;
   	case 'p':gameover_eat = eat;
   		return -1;
   	default:
   		*ch = temp;
   		break;
   	}
   }
   free(c);
}
  • 边框输出及计分板输出部分
void edging_title()                                                      //边界输出和计分板输出
{
   int l, w;
   for (w = 0; w < wi; w++)
   {
   	if (w == 0 || w == wi - 1)
   	{
   		for (l = 0; l < lo; l++)
   		{
   			printf("*");
   		}
   		printf("\n");
   	}
   	else
   	{
   		printf("*");
   		for (l = 0; l < lo - 2; l++)
   		{
   			printf(" ");
   		}
   		printf("*\n");
   	}
   }
   move(lo + 1, 0);
   printf("goal:%d", goal);
   move(lo + 1, 1);
   printf("score:%d", eat);
}
  • 食物生成和检测及边界检测部分
void check(int x, int y)                                                //食物生成及检测和边界检测
{
   static int x_food, y_food;                                           //防止被释放
   if (x >= lo - 1 || x <= 0 || y >= wi - 1 || y <= 0)                  //边缘检测
   {
   	gameover_eat = eat;
   	eat = -1;
   }
   if (eat == 0)
   {
   	x_food = lo / 2;
   	y_food = wi / 2;
   	if (x == x_food && y == y_food)
   	{
   		srand((unsigned)time(NULL));                                 //设种子
   		x_food = rand() % (lo - 3) + 2;
   		y_food = rand() % (wi - 3) + 2;
   		eat++;
   	}
   }
   else  if (x == x_food && y == y_food)
   {
   	srand((unsigned)time(NULL));                                     //设种子
   	x_food = rand() % (lo - 3) + 2;
   	y_food = rand() % (wi - 3) + 2;
   	eat++;
   }
   move(x_food, y_food);
   printf("x");
}
  • 蛇的移动部分
int snack_move(int temp_x, int temp_y, char* ch, struct Coordinate* c)   //蛇移动
{
   for (int z = eat + 2; z > 0; z--)                                    //检测蛇有没有撞自己
   {
   	if ((*c).x == (*(c + z)).x && (*c).y == (*(c + z)).y)
   	{
   		gameover_eat = eat;
   		return -1;
   	}
   }
   for (int i = eat + 2; i > 0; i--)
   {
   	(*(c + i)).x = (*(c + i - 1)).x;
   	(*(c + i)).y = (*(c + i - 1)).y;
   }
   (*c).x += temp_x;
   (*c).y += temp_y;
   for (int j = eat + 2; j >= 0; j--)
   {
   	move((*(c + j)).x, (*(c + j)).y);
   	printf("o");
   }
   move(0, 0);
   if (_kbhit())
   {
   	*ch = _getch();
   }
   Sleep(speed * 50);
   system("cls");
   return 0;
}

总代码

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

int control();
int snack_move(int temp_x, int temp_y, char* ch, struct Coordinate* c);
void edging_title();
void move(int x, int y);
void check(int x, int y);

int  goal, speed, lo, wi, eat, gameover_eat;
struct Coordinate                                                      //存储x,y
{
	int x;
	int y;
}*c;

int main()                                                             //界面部分
{
	printf("输入'o'开始游戏,其他键结束游戏\n");
	while (_getch() == 'o')
	{
		eat = 0, gameover_eat = 0;
		system("cls");
		printf("游戏以wsad操作,按'p'键可结束游戏\n请输入边界大小(长,宽)、速度、目标\n");
		system("pause");
		system("cls");
		printf("长(建议50左右):");
		scanf_s("%d", &lo);
		printf("宽(建议30左右):");
		scanf_s("%d", &wi);
		printf("请输入速度(应为整数2左右):");
		scanf_s("%d", &speed);
		printf("请输入目标(自然数):");
		scanf_s("%d", &goal);
		system("cls");
		printf("按任意键开始游戏");
		switch (control())
		{
		case -1:system("cls");
			printf("游戏结束-失败qwq\n目标为:%d\n最终成绩为:%d\n", goal, gameover_eat);
			break;
		default:system("cls");
			printf("游戏结束-胜利ovo\n目标为:%d\n最终成绩为:%d\n", goal, eat);
			break;
		}
		printf("输入'o'重新开始游戏,其他键结束游戏\n");
	}
}

void move(int x, int y)                                                  //命令指令行光标移动部分
{
	COORD  point = { (SHORT)x ,  (SHORT)y };                             //光标要设置的位置x,y
	HANDLE  HOutput = GetStdHandle(STD_OUTPUT_HANDLE);                   //使用GetStdHandle(STD_OUTPUT_HANDLE)来获取标准输出的句柄
	SetConsoleCursorPosition(HOutput, point);                            //设置光标位置
}

int control()                                                            //wsad的控制及蛇的生成部分
{
	Coordinate* c = (struct Coordinate*)calloc(goal + 3, 2 * sizeof(int));//动态生成结构体数组,为蛇的身躯
	(*c).x = lo / 2 + rand() % 3 + 1;
	(*c).y = wi / 2 + rand() % 3 + 1;
	(*(c + 1)).x = (*(c + 2)).x = 0;
	(*(c + 1)).y = (*(c + 2)).y = 0;
	char temp = 'w', temp_ch = _getch();
	char* ch = &temp_ch;
	int eat_1 = 0;
	while (1)                                                            //前后左右操作
	{
		if (eat == -1 || eat_1 == -1)
		{
			return -1;
		}
		if (eat == goal)
		{
			return 0;
		}
		switch (*ch)
		{
		case 'w': temp = 'w';
			edging_title();                                              //边界输出和计分板输出
			check((*c).x, (*c).y);                                       //吃的数量赋值和食物生成及检测和边界检测
			eat_1 = snack_move(0, -1, ch, c);
			break;
		case 's': temp = 's';
			edging_title();
			check((*c).x, (*c).y);
			eat_1 = snack_move(0, 1, ch, c);
			break;
		case 'a':  temp = 'a';
			edging_title();
			check((*c).x, (*c).y);
			eat_1 = snack_move(-1, 0, ch, c);
			break;
		case 'd': temp = 'd';
			edging_title();
			check((*c).x, (*c).y);
			eat_1 = snack_move(1, 0, ch, c);
			break;
		case 'p':gameover_eat = eat;
			return -1;
		default:
			*ch = temp;
			break;
		}
	}
	free(c);
}

void edging_title()                                                      //边界输出和计分板输出部分
{
	int l, w;
	for (w = 0; w < wi; w++)
	{
		if (w == 0 || w == wi - 1)
		{
			for (l = 0; l < lo; l++)
			{
				printf("*");
			}
			printf("\n");
		}
		else
		{
			printf("*");
			for (l = 0; l < lo - 2; l++)
			{
				printf(" ");
			}
			printf("*\n");
		}
	}
	move(lo + 1, 0);
	printf("goal:%d", goal);
	move(lo + 1, 1);
	printf("score:%d", eat);
}

void check(int x, int y)                                                 //食物生成及检测和边界检测部分
{
	static int x_food, y_food;                                           //防止被释放
	if (x >= lo - 1 || x <= 0 || y >= wi - 1 || y <= 0)                  //边缘检测
	{
		gameover_eat = eat;
		eat = -1;
	}
	if (eat == 0)
	{
		x_food = lo / 2;
		y_food = wi / 2;
		if (x == x_food && y == y_food)
		{
			srand((unsigned)time(NULL));                                 //设种子
			x_food = rand() % (lo - 3) + 2;
			y_food = rand() % (wi - 3) + 2;
			eat++;
		}
	}
	else  if (x == x_food && y == y_food)
	{
		srand((unsigned)time(NULL));                                     //设种子
		x_food = rand() % (lo - 3) + 2;
		y_food = rand() % (wi - 3) + 2;
		eat++;
	}
	move(x_food, y_food);
	printf("x");
}

int snack_move(int temp_x, int temp_y, char* ch, struct Coordinate* c)   //蛇移动
{
	for (int z = eat + 2; z > 0; z--)                                    //检测蛇有没有撞自己
	{
		if ((*c).x == (*(c + z)).x && (*c).y == (*(c + z)).y)
		{
			gameover_eat = eat;
			return -1;
		}
	}
	for (int i = eat + 2; i > 0; i--)
	{
		(*(c + i)).x = (*(c + i - 1)).x;
		(*(c + i)).y = (*(c + i - 1)).y;
	}
	(*c).x += temp_x;
	(*c).y += temp_y;
	for (int j = eat + 2; j >= 0; j--)
	{
		move((*(c + j)).x, (*(c + j)).y);
		printf("o");
	}
	move(0, 0);
	if (_kbhit())
	{
		*ch = _getch();
	}
	Sleep(speed * 50);
	system("cls");
	return 0;
}

心得

C语言一本书是完全不够用的,在制作的过程中,我查询了许多资料比如:C语言光标移动到指定位置、rand()的使用、非阻塞的输入函数kbhit()等等。

  • 14
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值