项目实战-贪吃蛇大作战【补档】

这其实算是一个补档,因为这个项目是我在大一完成的,但是当时没有存档的习惯,今天翻以前代码的时候翻到了,于是乎补个档,以此怀念和志同道合的网友一起做项目的日子 ₍ᐢ ›̥̥̥ ༝ ‹̥̥̥ ᐢ₎♡

这里面我主要负责service层,网友负责view层

目录

1.需求文档

2.流程图

设计一

设计二

3.产品构思图

4.可行性分析

5.源代码

6.实战效果

​7.心得


1.需求文档

2.流程图

processon是一个很好的流程图、思维导图等等的制作网站

设计一

设计二

权衡之后我们使用了第二种方案

3.产品构思图

这里我记得我们用的是墨刀

4.可行性分析

我找不到了ฅ(꒪˙꒳˙꒪ )ฅ ,不过肯定是可行性更大的doge

5.源代码

python 复制代码
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<windows.h>
#pragma warning(disable: 4996)
#define YH_W 20
#define YH_H 20
// 传入坐标, 将光标移动到指定坐标
int zhuozi;//自动生成食物参数
int score;//得分
char dir;//蛇的当前方向
int len;//蛇长(不计蛇头)
void gotoXY(int x, int y)
{
	COORD c;
	c.X = x - 1;
	c.Y = y - 1;
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);
}
void clear(int x, int y, int w, int h)
{
	for (int i = 0; i < h; i++) {
		gotoXY(x, y + i);
		for (int j = 0; j < w; j++) putchar(' ');
	}
}
void setPrintColor(int color) {
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color);
}
/*
	贪吃蛇:
		菜单界面:
			展示选项: 进入游戏 排行榜 设置 退出
			用户ws移动光标
			回车确认选项
				进入游戏: 进入游戏界面
				排行榜: 敬请期待
				设置: 敬请期待
				退出: 结束游戏
		游戏界面:
			展示地图: 展示蛇 地图
			用户wasd移动
			蛇定时移动
				移动后:
					撞墙/撞自己: 死亡 结束游戏
					吃到食物: 长度+1 食物消失 生成新的食物 移动一格
					空地: 移动一格
*/
//-----------------数据设计------------------
/*
				-1表示横墙
				-2表示竖墙
				-3 -4 -5 -6分别代表四个角落
				0表示空地
				1表示蛇
				2表示食物
				map[3][5] = 2// 坐标(3,5)是食物
*/
int map[YH_H][YH_W];
/*
	s[i][j]
		i表示第i节身体
		j表示坐标  0表示x坐标  1表示y坐标
	s[2][0] = 5;  	第[2]节身体x坐标 = 5
	s[2][1] = 3;	第[2]节身体y坐标 = 3
		蛇的第[2]节身体  坐标是(5,3)
*/
int s[YH_H * YH_W][2];//s[0][0]  s[0][1]
//-----------------数据设计------------------
//---------------view-------------------
/*
	功能:
		while(1)}{
			1. 展示界面
			2. 接收玩家输入
				如果是ws  移动光标
				如果是回车 执行对应选项
					进入游戏: 进入游戏界面
					排行榜: 敬请期待
					设置: 敬请期待
					退出: 结束游戏
		}
	参数: void
	返回值: void
*/
void menuView();
/*
	功能:打印暂停界面
	参数:void
	返回值:void
*/
void zt();
/*
	功能:
		1. 初始化游戏数据: 蛇(蛇身, 长度, 方向), 地图(墙,食物) service提供初始化函数
		while(1){
			2.    调用map_view函数        打印/绘制界面: 蛇, 地图	   view
			3. 判断用户有没有输入{ view
				kbhit()
				如果有:
					判断用户输入的类型  view
						方向: 修改方向:     service提供修改方向函数
							判断这个方向 能不能修改
							如果能修改 蛇的方向=输入方向

						//空格: 暂停游戏: 展示暂停界面
			}
			4. 移动{
				判断:
					判断蛇头 前面的位置 是什么东西   service提供判断函数 判断移动后的情况
					可能是墙/蛇身, 食物, 空地,
					打印失败界面,退到主菜单或者退出程序

				执行:
					如果是墙/蛇身: 游戏结束
					如果是空地/食物: 游戏继续		service提供修改函数  修改移动后的数据情况
						空地: 正常移动一格
						食物: 蛇长度+1, 正常移动一格, 去掉食物,生成一个新的食物
			}
		}
	参数: void
	返回值: void
*/
void gameView();
/*
功能:打印/绘制界面: 蛇, 地图
参数:void
返回值:void
*/
void map_view();
//---------------view-------------------
//---------------service-------------------
//service提供初始化函数
/*
		地图 蛇长度 蛇位置
		地图:
			地图周围一圈墙(1)
			地图中间初始化为空地(0)

		蛇位置:
			地图下方左边
			朝右走
		蛇方向: d

		食物:
			在地图中随机生成一个食物
			注意 食物不能和蛇身重叠
	参数: void
	返回值: void

*/
void init(void);
//service提供修改方向函数
/*
	注意: service不接收输入 不打印界面
	功能:
		1. 判断用户输入的方向 和蛇的方向  是否冲突
			如果冲突: 返回0
		2. 蛇的方向 = 用户输入方向
			返回1
	参数:
		userInput: 用户输入的方向
	返回值:
		0表示方向修改失败
		1表示方向修改成功
*/
int updateDir(char userInput);
//service提供判断函数 判断蛇头前面是什么
/*
	功能:
		1. 根据蛇头坐标 和蛇的方向  获取蛇头前一格的坐标
		2. 判断 地图中 这个坐标是什么内容
			如果是墙: 返回0
			如果是食物: 返回1

		3. (如果是空地)
			遍历蛇身 判断这个坐标 是否和蛇身重复
				如果是: 返回0
				如果不是 返回2

	参数: void
	返回值:
		0表示前面是蛇身/墙
		1表示前面是食物
		2表示前面是空地
*/
int before();
//service提供修改函数 蛇移动后的数据情况
/*
	功能:
		1. 判断是吃到食物的情况 还是空地的情况
		2. 如果是食物:
			1. 蛇长度+1
			2. 去掉地图上的食物
			3. 随机生成新的食物
			4. 蛇移动一格
		3. 如果是空地:
			1. 蛇移动一格

	参数:
		result:
			1 表示吃到食物的数据修改
			2: 表示空地的数据修改
	返回值: void

*/
void move(int result);
void food();
/*
	功能:
		打印设置 排行榜界面(拓展功能 暂未实现)
	参数:void
	返回值:void

*/
void more();
/*
	功能:
		打印结束界面及得分 跳回主界面
	参数:void
	返回值:void
*/
void end();
//---------------service-------------------
int main() {
	menuView();
}
void more() {
	system("cls");
	gotoXY(60, 5);
	printf("敬请期待!");
	gotoXY(58, 8);
	system("pause");
	system("cls");
	menuView();
}
void menuView() {
	int userChoose = 0;
	while (1) {
		// ----------------- 打印界面 -----------------
		gotoXY(64, 3);
		printf("贪吃蛇");
		if (userChoose == 0) setPrintColor(0x6f);
		gotoXY(64, 6);
		printf("开始游戏");
		if (userChoose == 0) setPrintColor(0x0f);
		if (userChoose == 1) setPrintColor(0x6f);
		gotoXY(65, 9);
		printf("排行榜");
		if (userChoose == 1) setPrintColor(0x0f);
		if (userChoose == 2) setPrintColor(0x6f);
		gotoXY(64, 12);
		printf("游戏设置");
		if (userChoose == 2) setPrintColor(0x0f);
		if (userChoose == 3) setPrintColor(0x6f);
		gotoXY(64, 15);
		printf("退出游戏");
		if (userChoose == 3) setPrintColor(0x0f);
		gotoXY(56, 19);
		printf("制作团队:发际线与我作队");
		gotoXY(54, 23);
		printf("提示:1.WASD进行上下左右移动\n                                                           2.长按WASD或者Esc可加速\n                                                           3.游戏中按空格可以暂停\n                                                           ?.请自行眨眼补帧(狗头)");
		gotoXY(58, 21);
		printf("特别鸣谢:启动小学长");
		// ---------------- 接收用户输入 --------------
		char input = _getch();
		// -------------判断是方向上下还是回车------------
		switch (input) {
		case 'w':
			userChoose -= 1;
			if (userChoose == -1) userChoose = 3;
			break;
		case 's':
			userChoose = (userChoose + 1) % 4;
			break;
		case '\r':
			clear(3, 2, 80, 20);
			switch (userChoose) {
			case 0:
				gameView();
				break;
			case 1:
				more();
				break;
			case 2:
				more();
				break;
			case 3:
				exit(0);
				break;
			}
			clear(3, 2, 36, 20);
			break;
		}
	}
}
void gameView()
{
	score = 0;
	int k = 0;
	init();//初始化地图
	system("cls");
	gotoXY(0, 0);
	while (1)
	{
		map_view();//打印地图
		k = 10000;

		while (k--)
		{
			if (kbhit())
			{
				break;
			}
		}
		if (k > 0)
		{
			char input = getch();
			if (input == 's' || input == 'w' || input == 'a' || input == 'd')
			{
				if (updateDir(input)) dir = input;//若输入有效,则更新方向
			}
			else if (input == ' ') zt();
		}
		//判断前面
		if (before() == 1 || before() == -1 || before() == -2) end();//前面是墙或蛇身,结束游戏
		else if (before() == 0) move(0);//前面是空地,蛇尾往前,蛇头往前
		else if (before() == 2)//前面是食物,吃掉食物
		{
			move(2);//蛇尾不变,蛇头往前
		}
	}
}
int updateDir(char userInput)
{
	int cha[2];
	if (len != 1)
	{
		cha[0] = s[0][0] - s[1][0];
		cha[1] = s[0][1] - s[1][1];//蛇头反方向
		if (userInput == 'w' && cha[0] == 1 || userInput == 's' && cha[0] == -1 || userInput == 'a' && cha[1] == 1 || userInput == 'd' && cha[1] == -1)
		{
			return 0;//枚举失败的情况
		}
	}
	return 1;
}
void map_view()
{
	system("cls");
	gotoXY(0, 0);
	for (int i = 0; i <= 19; i++)
	{
		for (int j = 0; j <= 19; j++)
		{
			if (i == s[0][0] && j == s[0][1]) {
				setPrintColor(6);//黄色
				printf(" ● ");
			}
			else {
				switch (map[i][j]) {
				case -1:
					setPrintColor(9);//浅蓝色
					printf("═══");
					break;
				case -2:
					setPrintColor(9);//浅蓝色
					printf(" ║ ");
					break;
				case -3:
					setPrintColor(9);//浅蓝色
					printf(" ╔═");
					break;
				case -4:
					setPrintColor(9);//浅蓝色
					printf("═╗ ");
					break;
				case -5:
					setPrintColor(9);//浅蓝色
					printf("═╝ ");
					break;
				case -6:
					setPrintColor(9);//浅蓝色
					printf(" ╚═");
					break;
				case 0:
					setPrintColor(7);//白色
					printf(" □ ");
					break;
				case 2:
					setPrintColor(2);//绿色
					printf(" ● ");
					break;
				case 1:
					setPrintColor(7);//白色
					printf(" ● ");
					break;
				}
			}
		}
		printf("\n");
	}
	gotoXY(0, 0);
	setPrintColor(7);
	printf("分数:%2d", score);
}
int before()
{
	switch (dir)
	{
	case'w':
		return map[s[0][0] - 1][s[0][1]];
	case's':
		return map[s[0][0] + 1][s[0][1]];
	case'a':
		return map[s[0][0]][s[0][1] - 1];
	case'd':
		return map[s[0][0]][s[0][1] + 1];
	}
}
void food() {
	int food_x, food_y;
	while (1) {
		food_x = rand() % 18 + 1;
		food_y = rand() % 18 + 1;
		if (map[food_x][food_y] == 0) {
			map[food_x][food_y] = 2;
			break;
		}
	}
}
void end()
{
	system("cls");
	gotoXY(10, 10);
	printf("游戏结束,你的得分为%d分。         ", score);
	system("pause");
	system("cls");
	menuView();
}
void init() {
	len = 2;//蛇头不计入长度
	dir = 'd';//初始方向为右
	for (int i = 0; i <= 19; ++i)
	{
		map[i][0] = -2;
		map[0][i] = -1;
		map[19][i] = -1;
		map[i][19] = -2;
	}
	map[0][0] = -3;
	map[0][19] = -4;
	map[19][19] = -5;
	map[19][0] = -6;
	for (int i = 1; i <= 18; ++i)
	{
		for (int t = 1; t <= 18; ++t)
			map[i][t] = 0;
	}
	s[0][0] = 10;
	s[0][1] = 11;
	s[1][0] = 10;
	s[1][1] = 10;
	map[10][10] = 1;
	map[10][11] = 1;
	food();
}
void move(int result) {
	zhuozi %= 10;
	zhuozi++;
	if (zhuozi == 1) food();//每过一会刷出食物
	int xx = s[0][0], yy = s[0][1];
	switch (dir) {
	case 'w':
		xx = s[0][0] - 1;
		yy = s[0][1];
		break;
	case 'a':
		xx = s[0][0];
		yy = s[0][1] - 1;
		break;
	case 's':
		xx = s[0][0] + 1;
		yy = s[0][1];
		break;
	case 'd':
		xx = s[0][0];
		yy = s[0][1] + 1;
		break;
	}
	if (result == 2)
	{
		++len;
		for (int i = len - 1; i >= 1; i--)
		{
			s[i][0] = s[i - 1][0];
			s[i][1] = s[i - 1][1];
		}
		food();
		score += 20;
	}
	else
	{
		map[s[len - 1][0]][s[len - 1][1]] = 0;
		for (int i = len - 1; i >= 1; i--)
		{
			s[i][0] = s[i - 1][0];
			s[i][1] = s[i - 1][1];
		}
	}
	s[0][0] = xx;
	s[0][1] = yy;
	map[xx][yy] = 1;
}
void zt()
{
	system("cls");
	gotoXY(10, 10);
	printf("游戏已暂停,按下空格解除暂停");
	while (1)
	{
		char input_z = getch();
		if (input_z == ' ') break;
	}
	map_view();
}

6.实战效果

7.心得

虽然过去有段时间了,但是我还是想得起和有同样目标方向的网友做项目的开心,大一刚进入大学不久一切还不是很适应,但是和网友一起做项目让我不再那么紧张,也慢慢开始适应大学生活,虽然现在不经常联系了,但是人生每个阶段都有各个阶段你会遇到的人,重要的是一起变得更好,一起向远方

相关推荐
YuforiaCode2 分钟前
第十二届蓝桥杯 2021 C/C++组 空间
c语言·c++·蓝桥杯
YuforiaCode10 分钟前
第十二届蓝桥杯 2021 C/C++组 卡片
c语言·c++·蓝桥杯
努力努力再努力wz2 小时前
【Linux实践系列】:进程间通信:万字详解命名管道实现通信
android·linux·运维·服务器·c++·c
阿方.9182 小时前
C语言----操作符详解(万字详解)
c语言·开发语言
夜晚中的人海3 小时前
【C语言】初阶算法相关习题(二)
c语言·开发语言·算法
炯哈哈3 小时前
【上位机——MFC】文档
开发语言·c++·mfc·上位机
神一样的老师3 小时前
使用 MQTT - C 访问 IoTDA 平台:一个完整的嵌入式示例
c语言·开发语言·物联网
水饺编程3 小时前
Visual Studio 技能:调整软件界面布局
ide·visual studio
愚润求学3 小时前
【C++11】可变参数模板
开发语言·c++·笔记·c++11·模板
WW_千谷山4_sch3 小时前
MYOJ_1349:(洛谷P3951)[NOIP 2017 提高组] 小凯的疑惑(数学公式套用,两步搞定代码)
c++·算法