贪吃蛇大作战 内涵生存模式

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

#define row 32 //游戏区行数
#define col 72 //游戏区列数

#define nothing 0 
#define wall 1 
#define food 2
#define head 3 
#define BODY 4 

#define up 72 
#define down 80
#define left 75 
#define right 77 
#define space 32 
#define esc 27 

//蛇头
struct Snake
{
	int len,x,y; 
}snake;
//蛇身
struct Body
{
	int x,y; 
}body[row*col]; 

int zhuangtai[row][col]; //标记游戏区各个位置的状态

//隐藏光标
void hidecursor();
//光标跳转
void cursorjump(int x, int y);
//初始化界面
void injm();
//颜色设置
void color(int c);
//从文件读取最高分
void rg();
//更新最高分到文件
void wg();
//初始化蛇
void insnake();
//随机生成食物
void randfood();
//判断得分与结束
void jgfun(int x, int y);
//打印蛇与覆盖蛇
void pfsnake(int flag);
//移动蛇
void movesnake(int x, int y);
//执行按键
void run(int x, int y);
//游戏主体逻辑函数
void game();
//
void in();
void exp();
void mod();
void mmod();
void scmod();
void mrun(int x, int y);
void mjgfun(int x, int y);
void minjm();

int maxlife, life; //全局变量
int main()
{
	while(1)
	{
		in();
		int n;scanf("%d",&n);
		switch (n) {
		case 2:
			scmod();
			break;
		case 3:
			exp();
			break;
		case 1:
			mmod();
			default:
				system("cls");
				cursorjump(2 * (col / 3), row / 2 );
				printf("请重新选择");
				Sleep(1000);
				system("cls");
				main();
		}
	}
	return 0;
}
void exp(){
	system("cls");
	cursorjump(2 * (col / 3), row / 2 - 15);
	printf("贪吃蛇生存版游戏说明");
	cursorjump(2 * (col / 3)-20, row / 2 - 12);
	printf("1.不能撞墙,不能吃到自己,生命值不能为0,否则死亡");
	cursorjump(2 * (col / 3)-20, row / 2 - 10);
	printf("2.用↑.↓.←.→分别控制蛇的移动");
	cursorjump(2 * (col / 3)-20, row / 2 - 8);
	printf("3.你的初始生命值为8");
	cursorjump(2 * (col / 3)-20, row / 2 - 6);
	printf("4.每改变一次方向你的生命值将会减少2");
	cursorjump(2 * (col / 3)-20, row / 2 - 4);
	printf("5.害怕你死的太快,每吃到一次食物你的生命值将会增加16");
	cursorjump(2 * (col / 3)-20, row / 2 - 2);
	printf("6.space 暂停,按↑.↓.←.→开始");
	cursorjump(2 * (col / 3)-20, row / 2 );
	printf("5.r/R重新开始游戏或返回菜单");
	cursorjump(2 * (col / 3)-20, row / 2 +2);
	printf("7.esc 退出游戏");
	cursorjump(2 * (col / 3)-20, row / 2 +4);
	printf("tips:长按↑.↓.←.→加速");
	_getch(); 
	system("cls");
}
void scmod()
{
	maxlife = 0, life = 9;//初始生命值为8 每改变一次方向将会消耗2生命值
	system("title 贪吃蛇生存版"); 
	system("mode con cols=144 lines=33"); //设置cmd窗口的大小
	hidecursor(); 
	rg(); 
	injm(); 
	insnake(); 
	srand((unsigned int)time(NULL)); //设置随机数生成起点
	randfood(); 
	pfsnake(1); 
	game(); 
}
void mmod()
{
	maxlife = 0, life = 0;//初始生命值为8 每改变一次方向将会消耗2生命值
	system("title 贪吃蛇"); 
	system("mode con cols=144 lines=33"); //设置cmd窗口的大小
	hidecursor(); 
	rg(); 
	minjm(); 
	insnake(); 
	srand((unsigned int)time(NULL)); //设置随机数生成起点
	randfood(); 
	pfsnake(1); 
	mod(); 
}
void in()
{
	color(6);
	cursorjump(2 * (col / 3)+5, row / 2 - 15);
	printf("                                                                                         \n");
	printf("                       __________       ___                                              \n");
	printf("                      /          \\     / \\ \\    |____      __\\__                     \n");
	printf("                     /  ________  \\   / ___ \\  _/ __     | |   /                       \n");
	printf("                     |  |      |__|     _/_   |_|  /    [|] |/                           \n");
	printf("                     |  |              | | |      /     _|_ \\__/                        \n");
	printf("                     \\  \\_______        / \\      |___/        ____                    \n");
	printf("                      \\         \\    ____ ____      ____   __ |  |  ___   ______       \n");
	printf("                       \\_______  \\   |  |/    \\    /    \\_/ / |  | /  /  /      \\   \n");
	printf("                               \\  \\  |    ___  \\  / ____   /  |  |/  /  /  ____  \\   \n");
	printf("                     __        |  |  |   /   \\  \\ | |  |  /   |     /  |  /____\\  |   \n");
	printf("                    \\  \\_______|  |  |  |    |  | | |__|  |   |     \\  |  ________/   \n");
	printf("                     \\            /  |  |    |  |  \\       \\  |  |\\  \\  \\  \\____  \n");
	printf("                      \\__________/   |__|    |__|   \\___/\\__\\ |__| \\__\\  \\______/ \n");	
	cursorjump(2 * (col / 3), row / 2 +3);
	printf("1.正常模式");
	cursorjump(2 * (col / 3), row / 2 +5);
	printf("2.生存模式");
	cursorjump(2 * (col / 3), row / 2 +7);
	printf("3.游戏说明");
	cursorjump(2 * (col / 3), row / 2 +9);
	printf("请选择(1/2/3):");
}
//隐藏光标
void hidecursor()
{
	CONSOLE_CURSOR_INFO curInfo; //定义光标信息的结构体变量
	curInfo.dwSize = 1; //如果没赋值的话,光标隐藏无效
	curInfo.bVisible = FALSE; 
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); //获取控制台句柄
	SetConsoleCursorInfo(handle, &curInfo); //设置光标信息
}
//光标跳转
void cursorjump(int x, int y)
{
	COORD pos; //定义光标位置的结构体变量	typedef unsigned long DWORD;//DWORD 表示 32bit 无符号整数,
	pos.X = x; pos.Y = y; 
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); //获取控制台句柄
	SetConsoleCursorPosition(handle, pos); //设置光标位置
}
//初始化界面
void injm()
{
	color(6); 
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			if (j == 0 || j == col - 1)
			{
				zhuangtai[i][j] = wall; 
				cursorjump(2 * j, i);
				printf("■");
			}
			else if (i == 0 || i == row - 1)
			{
				zhuangtai[i][j] = wall; 
				printf("■");
			}
			else
			{
				zhuangtai[i][j] = nothing; 
			}
		}
	}
	color(6); 
	cursorjump(0, row);
	printf("当前生命值:%d", life);
	cursorjump(col, row);
	printf("历史最高存活生命值:%d", maxlife);
}
//颜色设置
void color(int c)
{
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c); //颜色设置
	//注:SetConsoleTextAttribute是一个API(应用程序编程接口)
}
//从文件读取最高分
void rg()
{
	FILE* pf = fopen("贪吃蛇最高得分记录.txt", "r"); 
	if (pf == NULL) 
	{
		pf = fopen("贪吃蛇最高得分记录.txt", "w"); 
		fwrite(&maxlife, sizeof(int), 1, pf); 
	}
	fseek(pf, 0, SEEK_SET);
	fread(&maxlife, sizeof(int), 1, pf); 
	fclose(pf); pf = NULL; 
}
//更新最高分到文件
void wg()
{
	FILE* pf = fopen("贪吃蛇最高得分记录.txt", "w"); 
	if (pf == NULL) 
	{
		printf("保存最高得分记录失败\n");exit(0);
	}
	fwrite(&life, sizeof(int), 1, pf); 
	fclose(pf); pf = NULL; 
}
//初始化蛇
void insnake()
{
	snake.len = 2; 
	snake.x = col / 2; 
	snake.y = row / 2; 
	//蛇身
	body[0].x = col / 2 - 1;
	body[0].y = row / 2;
	body[1].x = col / 2 - 2;
	body[1].y = row / 2;
	//将蛇头和蛇身位置进行标记
	zhuangtai[snake.y][snake.x] = head;
	zhuangtai[body[0].y][body[0].x] = BODY;
	zhuangtai[body[1].y][body[1].x] = BODY;
}
//随机生成食物
void randfood()
{
	int i, j;
	do
	{
		i = rand() % row;
		j = rand() % col;
	} while (zhuangtai[i][j] != nothing); //确保生成食物的位置为空,若不为空则重新生成
	zhuangtai[i][j] = food; //将食物位置进行标记
	color(12); 
	cursorjump(2 * j, i); //光标跳转到生成的随机位置处
	printf("●"); //打印食物
}
//判断得分与结束
void jgfun(int x, int y)
{
	if (zhuangtai[snake.y + y][snake.x + x] == food)
	{
		snake.len++; 
		life += 16; 
		color(6); 
		cursorjump(0, row);
		printf("当前生命值:%d", life); 
		randfood(); 
	}
	else if (zhuangtai[snake.y + y][snake.x + x] == wall || zhuangtai[snake.y + y][snake.x + x] == BODY||life==0)
	{
		Sleep(1000); //留给玩家反应时间
		system("cls"); //清空屏幕
		color(6); 
		cursorjump(2 * (col / 3), row / 2 - 3);
		if (life > maxlife)
		{
			printf("您已死亡,恭喜你打破最高记录,最高记录更新为%d", life);wg();
		}
		else if (life == maxlife)
		{
			printf("您已死亡,与最高记录持平,加油再创佳绩");
		}
		else
		{
			printf("您已死亡,请继续加油,当前与最高记录相差%d", maxlife - life);
		}
		cursorjump(2 * (col / 3), row / 2);
		printf("YOU DIE !");
		while (1) //询问玩家是否再来一局
		{
			char ch;
			cursorjump(2 * (col / 3), row / 2 + 3);
			printf("是否复活?\n");
			cursorjump(2 * (col / 3), row / 2 + 4);
			printf("Y or N :\n");
			cursorjump(2 * (col / 3)+8, row / 2 + 4);
			scanf("%c", &ch);
			if (ch == 'y' || ch == 'Y')
			{
				system("cls");
				main();
			}
			else if (ch == 'n' || ch == 'N')
			{
				cursorjump(2 * (col / 3), row / 2 + 6);
				exit(0);
			}
			else
			{
				cursorjump(2 * (col / 3), row / 2 + 6);
				printf("选择错误,请再次选择");
			}
		}
	}
}
//打印蛇与覆盖蛇
void pfsnake(int flag)
{
	if (flag == 1) //打印蛇
	{
		color(7); 
		cursorjump(2 * snake.x, snake.y);
		printf("●"); 
		for (int i = 0; i < snake.len; i++)
		{
			color(12);
			cursorjump(2 * body[i].x, body[i].y);
			printf("●"); 
		}
	}
	else 
	{
		if (body[snake.len - 1].x != 0) 
		{
			cursorjump(2 * body[snake.len - 1].x, body[snake.len - 1].y);
			printf("  ");
		}
	}
}
//移动蛇
void movesnake(int x, int y)
{
	pfsnake(0); //先覆盖当前所显示的蛇
	zhuangtai[body[snake.len - 1].y][body[snake.len - 1].x] = nothing; //蛇移动后蛇尾重新标记为空
	zhuangtai[snake.y][snake.x] = BODY; //蛇移动后蛇头的位置变为蛇身
	//蛇移动后各个蛇身位置坐标需要更新
	for (int i = snake.len - 1; i > 0; i--)
	{
		body[i].x = body[i - 1].x;
		body[i].y = body[i - 1].y;
	}
	body[0].x = snake.x;
	body[0].y = snake.y;
	//蛇头
	snake.x = snake.x + x;
	snake.y = snake.y + y;
	pfsnake(1); 
}
//执行按键
void run(int x, int y)
{
	int t = 0;
	while (1)
	{
		if (t == 0)	t = 3000; //t越小越快
		while (--t)
		{
			if (kbhit() != 0) {break;}//若键盘被敲击,则退出循环
		}
		if (t == 0) 
		{
			jgfun(x, y); movesnake(x, y); //移动蛇
		}
		else return; //返回Game函数读取键值
	}
}
//游戏主体逻辑函数
void game()
{
	int n = right; //开始游戏时,默认向后移动
	int tp = 0; //记录蛇的移动方向 当前键值
	goto first; 
	while (1)
	{
		n = getch(); //读取键值
		switch (n)
		{
		case up:
			case down: 
			if (tp != left&&tp != right) 
			{
				n = tp; 
			}
			break;
		case left:
			case right: 
			if (tp != up&&tp != down) 
			{
				n = tp; 
			}
		case space:
		case esc:
		case 'r':
		case 'R':
			break; 
			default:
				n = tp; 
				break;
		}
		first: //第一次进入循环先向默认方向前进
		switch (n)
		{
			case up: //倒着的直角坐标系
			life--; 
			color(6); 
			cursorjump(0, row);
			printf("当前生命值:%d", life);run(0, -1); tp = up;break;
			case down: 
			life--; 
			color(6); 
			cursorjump(0, row);
			printf("当前生命值:%d", life);run(0, 1); tp = down;break;
			case left: 
			life --; 
			color(6); 
			cursorjump(0, row);
			printf("当前生命值:%d", life);run(-1, 0); tp = left;break;
			case right: 
			life --; 
			color(6); 
			cursorjump(0, row);
			printf("当前生命值:%d", life);run(1, 0); tp = right;break;
			case space: 
			system("pause>nul"); break;
			case esc: 
			system("cls"); //清空屏幕
			color(7); 
			cursorjump(col - 8, row / 2);
			printf("  游戏结束  ");
			cursorjump(col - 8, row / 2 + 2);
			exit(0);
		case 'r':
			case 'R': //重新开始
			system("cls"); //清空屏幕
			main(); 
		}
	}
}
void mod()
{
	int n = right; //开始游戏时,默认向后移动
	int tp = 0; //记录蛇的移动方向 当前键值
	goto first; 
	while (1)
	{
		n = getch(); //读取键值
		switch (n)
		{
		case up:
			case down: 
			if (tp != left&&tp != right) 
			{
				n = tp; 
			}
			break;
		case left:
			case right: 
			if (tp != up&&tp != down) 
			{
				n = tp; 
			}
		case space:
		case esc:
		case 'r':
		case 'R':
			break; 
			default:
				n = tp; 
				break;
		}
		first: //第一次进入循环先向默认方向前进
		switch (n)
		{
			case up: //倒着的直角坐标系
			mrun(0, -1); tp = up;break;
			case down: 
			mrun(0, 1); tp = down;break;
			case left: 
			mrun(-1, 0); tp = left;break;
			case right: 
			mrun(1, 0); tp = right;break;
			case space: 
			system("pause>nul"); break;
			case esc: 
			system("cls"); //清空屏幕
			color(7); 
			cursorjump(col - 8, row / 2);
			printf("  游戏结束  ");
			cursorjump(col - 8, row / 2 + 2);
			exit(0);
		case 'r':
			case 'R': //重新开始
			system("cls"); //清空屏幕
			main(); 
		}
	}
}
//执行按键
void mrun(int x, int y)
{
	int t = 0;
	while (1)
	{
		if (t == 0)
			t = 3000; //t越小越快
		while (--t)
		{
			if (kbhit() != 0) break;//若键盘被敲击,则退出循环
		}
		if (t == 0) 
		{
			mjgfun(x, y); movesnake(x, y); //移动蛇
		}
		else break; //返回Game函数读取键值
	}
}
void mjgfun(int x, int y)
{
	if (zhuangtai[snake.y + y][snake.x + x] == food)
	{
		snake.len++; 
		life += 5; 
		color(6); 
		cursorjump(0, row);
		printf("当前得分:%d", life); 
		randfood(); 
	}
	else if (zhuangtai[snake.y + y][snake.x + x] == wall || zhuangtai[snake.y + y][snake.x + x] == BODY)
	{
		Sleep(1000); //留给玩家反应时间
		system("cls"); //清空屏幕
		color(6); 
		cursorjump(2 * (col / 3), row / 2 - 3);
		if (life > maxlife)
		{
			printf("恭喜你打破最高记录,最高记录更新为%d", life);wg();
		}
		else if (life == maxlife)
		{
			printf("与最高记录持平,加油再创佳绩");
		}
		else
		{
			printf("请继续加油,当前与最高记录相差%d", maxlife - life);
		}
		cursorjump(2 * (col / 3), row / 2);
		printf("GAME OVER");
		while (1) //询问玩家是否再来一局
		{
			char ch;
			cursorjump(2 * (col / 3), row / 2 + 3);
			printf("再来一局?\n");
			cursorjump(2 * (col / 3), row / 2 + 4);
			printf("Y or N :\n");
			cursorjump(2 * (col / 3)+8, row / 2 + 4);
			scanf("%c", &ch);
			if (ch == 'y' || ch == 'Y')
			{
				system("cls");
				main();
			}
			else if (ch == 'n' || ch == 'N')
			{
				cursorjump(2 * (col / 3), row / 2 + 6);
				exit(0);
			}
			else
			{
				cursorjump(2 * (col / 3), row / 2 + 6);
				printf("选择错误,请再次选择");
			}
		}
	}
}
void minjm()
{
	color(6); 
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			if (j == 0 || j == col - 1)
			{
				zhuangtai[i][j] = wall; 
				cursorjump(2 * j, i);
				printf("■");
			}
			else if (i == 0 || i == row - 1)
			{
				zhuangtai[i][j] = wall; 
				printf("■");
			}
			else
			{
				zhuangtai[i][j] = nothing; 
			}
		}
	}
	color(6); 
	cursorjump(0, row);
	printf("当前得分:%d", life);
	cursorjump(col, row);
	printf("历史最高得分:%d", maxlife);
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值