zoukankan      html  css  js  c++  java
  • 贪吃蛇

    贪吃蛇小游戏

    版本要求:VS2019

    编写目的:回顾C语言课程设计以及熟练掌握C语言。

    实现效果:




    代码展示:

    #include<stdio.h>
    #include<stdlib.h>
    #include<Windows.h>
    #include<time.h>
    #include<conio.h>
    constexpr auto maphigh = 28, mapwide = 84;
    struct virus
    {
    	int x;
    	int y;
    }virus;
    unsigned short snakesize = 50, speed = 300, len = 4;
    struct snake
    {
    	int x[50];
    	int y[50];
    	int len;//蛇的长度
    	int speed;//蛇的速度
    }snake;
    int key = 'w';//初始化方向
    void gotoxy(int x, int y);
    void drawmap();
    void keydown();
    void creatvirus();
    int snakestatus();
    void startgame();
    int menuselect();
    void goodbye();
    void introduce();
    void edition();
    int setup();
    void respect();
    int setup1();
    int modifydiffculty();
    void diffculty();
    int customize();
    void customize1();
    int main()
    {
    	for (;;)
    	{
    		system("cls");//清屏
    		switch (menuselect())
    		{
    		case 1://开始游戏
    			startgame();
    			break;
    		case 2://介绍
    			introduce();
    			break;
    		case 3://版本
    			edition();
    			break;
    		case 4://设置
    			setup1();
    			break;
    		case 5:
    			goodbye();
    			return 0;
    		default:
    			break;
    		}
    	}
    }
    void drawmap()//1.画地图
    {
    	//⊙:病毒    █:蛇身(占用两个字符)
    	srand((unsigned int)time(NULL));//随机病毒出现的位置
    	int i, k;
    	for (i = 0; i <= maphigh; i++)
    	{
    		gotoxy(0, i);
    		printf("█");//打印左边框
    		gotoxy(mapwide, i);
    		printf("█");//打印右边框
    	}
    	for (i = 0; i <= mapwide; i += 2)//+=2因为 █占两个字节
    	{
    		gotoxy(i, 0);
    		printf("█");//打印下边框
    		gotoxy(i, maphigh);
    		printf("█");//打印上边框
    	}
    	//画蛇
    	snake.len = len;
    	snake.speed = speed;
    	//初始化蛇的位置
    	snake.x[0] = mapwide / 2;
    	snake.y[0] = maphigh / 2;//[0]为蛇头的位置
    	//画蛇头
    	gotoxy(snake.x[0], snake.y[0]);
    	printf("█");
    	//画蛇身
    	for (k = 1; k < snake.len; k++)
    	{
    		snake.x[k] = snake.x[k - 1] + 2;
    		snake.y[k] = snake.y[k - 1];
    		gotoxy(snake.x[k], snake.y[k]);
    		printf("█");
    	}
    	while (1)
    	{
    		virus.x = rand() % (mapwide - 4) + 2;//+2,+1这个与█所占的字符有关,长占两个字符宽1个
    		virus.y = rand() % (maphigh - 2) + 1;//画个图,显而易见
    		if (virus.x % 2 == 0)
    			break;
    	}
    	gotoxy(virus.x, virus.y);
    	printf("⊙");
    	gotoxy(mapwide + 4, maphigh);
    	printf("⊙:%d", snakesize - snake.len);
    }
    void creatvirus()//2.产生病毒
    {
    	if (snake.x[0] == virus.x && snake.y[0] == virus.y)
    	{
    		//printf("a");//声音
    		snake.len++;
    		srand((unsigned)time(NULL));
    		while (1)
    		{
    			int flag = 1;
    			virus.x = rand() % (mapwide - 4) + 2;//+2,+1这个与█所占的字符有关,长占两个字符宽1个
    			virus.y = rand() % (maphigh - 2) + 1;//画个图,显而易见
    		//产生的病毒不能在蛇的身上
    			for (int k = 0; k < snake.len; k++)
    			{
    				if (snake.x[k] == virus.x && snake.y[k] == virus.y)
    				{
    					flag = 0;//virus不合适的标志
    					break;
    				}
    			}
    			if (flag == 1 && virus.x % 2 == 0)//病毒位置合法且x坐标为偶数
    			{//x左右是以两个字节为单位运动的,若virus的x坐标为奇数,就不存在snake.x[k] == virus.x
    				break;
    			}
    		}
    	}
    	gotoxy(virus.x, virus.y);
    	printf("⊙");
    	gotoxy(mapwide + 8, 0);//将光标移走
    	printf("W");
    	gotoxy(mapwide + 6, 1);
    	printf("A S D 	进行控制");
    	gotoxy(mapwide + 4, maphigh);
    	printf("⊙:%d", snakesize - snake.len);
    }
    void keydown()//3.按键
    {
    	int i, temp;
    	if (_kbhit()) //kbhit函数检查当前是否有键盘输入,若有则返回一个非0值,否则返回0
    	{
    		fflush(stdin);// 清空输入缓冲区,通常是为了确保不影响后面的数据读取
    		temp = _getch();//getch:从控制台读取一个字符,但不显示在屏幕上
    		if ((temp == 'a' || temp == 'A') && (key != 'D' && key != 'd'))//解决了按反方向键蛇自杀的问题
    		{
    			key = temp;
    		}
    		if ((temp == 'w' || temp == 'W') && (key != 's' && key != 'S'))
    		{
    			key = temp;
    		}
    		if ((temp == 's' || temp == 'S') && (key != 'W' && key != 'w'))
    		{
    			key = temp;
    		}
    		if ((temp == 'D' || temp == 'd') && (key != 'a' && key != 'A'))
    		{
    			key = temp;
    		}
    	}
    	//擦除最后一节
    	gotoxy(snake.x[snake.len - 1], snake.y[snake.len - 1]);
    	printf("  ");
    	for (i = snake.len - 1; i > 0; i--)
    	{
    		snake.x[i] = snake.x[i - 1];//以前1的位置现在变成了2,0变成了1
    		snake.y[i] = snake.y[i - 1];
    	}
    	switch (key)//最后一节已经擦出,前移后0,1位置重合,左上角坐标为0,0
    	{
    	case'w':
    	case'W':
    		snake.y[0]--;
    		break;
    	case's':
    	case'S':
    		snake.y[0]++;
    		break;
    	case'a':
    	case'A':
    		snake.x[0] -= 2;
    		break;
    	case'd':
    	case'D':
    		snake.x[0] += 2;
    		break;
    	}
    	gotoxy(snake.x[0], snake.y[0]);
    	printf("█");
    	gotoxy(mapwide + 2, 0);//将光标移走
    }
    int snakestatus()//4.蛇的状态
    {
    	if ((snake.x[0] == 0 || snake.x[0] == mapwide) || (snake.y[0] == 0 || snake.y[0] == maphigh))
    		return 0;
    	for (int k = 1; k < snake.len; k++)
    	{
    		if (snake.x[0] == snake.x[k] && snake.y[0] == snake.y[k])
    			return 0;
    	}
    	return 1;
    }
    void gotoxy(int x, int y)
    {//1.找到控制台这个窗口
    	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
    	/*HANDLE为句柄  ↑得到(输出窗口的)句柄。
    	Windows是一个以虚拟内存为基础的操作系统,很多时候,
    	进程的代码和数据并不全部装入内存,进程的某一段装入内存后,
    	还可能被换出到外存,当再次需要时,再装入内存。两次装入的地址绝大多数情况下是不一样的。
    	也就是说,同一对象在内存中的地址会变化。那么,程序怎么才能准确地访问到对象呢?为了解决这个问题,Windows引入了句柄。
    	数值上,是一个32位无符号整型值(32位系统下);逻辑上,相当于指针的指针;形象理解上,是Windows中各个对象的一个唯一的、固定不变的ID;
    	作用上,Windows使用句柄来标识诸如窗口、位图、画笔等对象,并通过句柄找到这些对象。*/
    	//2.设置光标
    	COORD coord;
    	/*COORD 为Windows.h中自带函数原型大体为struct _coord{short x;short y;}coord;*/
    	coord.X = x;
    	coord.Y = y;
    	//4.同步到控制台SetConsoleCursorPosition
    	SetConsoleCursorPosition(handle, coord);//定位到handle这个窗口,把光标打在coord坐标
    }
    void startgame()
    {
    	system("cls");
    	drawmap();
    	while (1)
    	{
    		creatvirus();
    		keydown();
    		Sleep(snake.speed);//void sleep(int seconds)自带函数参数 seconds 为要暂停的毫秒数。
    		if (!snakestatus())//判断死亡时snakestaus为0,
    		{
    			gotoxy(mapwide / 2, maphigh / 2);
    			printf("Game Over");
    			getchar();
    			getchar();
    			break;
    		}
    		if (snake.len == snakesize)
    		{
    			gotoxy(mapwide / 3, maphigh / 2);
    			printf("恭喜您消灭了全部病毒,胜利(^-^)V");
    			getchar();
    			respect();
    			break;
    		}
    	}
    }
    int menuselect()
    {
    	char number;
    	int a;
    	printf("
    
    						1.开始游戏
    ");
    	printf("
    						2.游戏介绍
    ");
    	printf("
    						3.游戏版本
    ");
    	printf("
    						4.设置
    ");
    	printf("
    						5.退出游戏
    ");
    	printf("
    						请选择(数字)");
    	while (1)
    	{
    		number = getchar();
    		a = (int)number - 48;
    		if (number <= '5' && number >= '1')
    			return a;
    		printf("
    							      ");
    	}
    }
    void goodbye()
    {
    	system("cls");
    	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED);//设置红色
    	gotoxy(0, 12);
    	printf("						谢谢使用!再见!
    ");
    	getchar();
    	getchar();
    }
    void respect()
    {
    	system("cls");
    	gotoxy(0, 4);
    	printf("		*在此向全国的医护人员表示敬意*
    
    ");
    	Sleep(1000);
    	printf("		*感谢他们的默默付出*
    
    ");
    	Sleep(1000);
    	printf("		*感谢他们对抗击疫情做出的贡献*
    
    ");
    	Sleep(1000);
    	printf("		*此致*
    
    ");
    	printf("		*                      敬礼 *
    
    ");
    	Sleep(2000);
    	getchar();
    }
    void introduce()
    {
    	system("cls");
    	gotoxy(0, 4);
    	printf("				        游戏规则           
    
    ");
    	printf("				2020年新冠病毒肆虐,威胁着人类
    
    ");
    	printf("				玩家将控制蛇消灭随机出现的病毒⊙
    
    ");
    	printf("				消灭所有病毒即可获得胜利。
    
    ");
    	printf("
    
    
    
    
    ");
    	printf("					Enter返回主菜单");
    	getchar();
    	getchar();
    }
    void edition()
    {
    	system("cls");
    	gotoxy(0, 4);
    	printf("				*********************************************
    
    ");
    	printf("				*               欢         迎               *
    
    ");
    	printf("				*                版本号: 1.2               *
    
    ");
    	printf("				*        更新:1.修复了反方向自杀的问题     *
    
    ");
    	printf("				*              2.修复了蛇吃墙的问题         *
    
    ");
    	printf("				*              3.新增了菜单与设置功能       *
    
    ");
    	printf("				*              4.修改了部分整形变量节省空间 *
    
    ");
    	printf("				*********************************************
    
    ");
    	printf("					Enter返回主菜单");
    	getchar();
    	getchar();
    }
    int setup()
    {
    	//system("color 6f"); //第一个为背景色,第二个为字体颜色
       /*0 = 黑色       8 = 灰色
    	1 = 蓝色       9 = 淡蓝色
    	2 = 绿色       A = 淡绿色
    	3 = 湖蓝色     B = 淡浅绿色
    	4 = 红色       C = 淡红色
    	5 = 紫色       D = 淡紫色
    	6 = 黄色       E = 淡黄色
    	7 = 白色       F = 亮白色*/
    	char s;
    	int a;
    	system("cls");
    	printf("
    
    						1.修改难度
    ");
    	printf("
    						2.自义定设置
    ");
    	printf("
    						3.颜色设置
    ");
    	printf("
    						4.音效设置
    ");
    	printf("
    						5.返回
    ");
    	printf("
    						请选择(数字)");
    	while (1)
    	{
    		s = getchar();
    		a = (int)s - 48;
    		if (s <= '5' && s >= '1')
    			return a;
    		printf("
    							      ");
    	}
    }
    int setup1()
    {
    	switch (setup())
    	{
    	case 1:
    		diffculty();
    		break;
    	case 2:
    		customize1();
    		break;
    	default:
    		break;
    	}
    	return 0;
    }
    int modifydiffculty()
    {
    	char s;
    	int a;
    	system("cls");
    	printf("
    
    						1.简单
    ");
    	printf("
    						2.普通
    ");
    	printf("
    						3.困难
    ");
    	printf("
    						4.修罗地狱
    ");
    	printf("
    						请选择(数字)");
    	while (1)
    	{
    		s = getchar();
    		a = (int)s - 48;
    		if (s <= '4' && s >= '1')
    			return a;
    		printf("
    							      ");
    	}
    }
    void diffculty()
    {
    	switch (modifydiffculty())
    	{
    	case 1:
    		len = 4;
    		speed = 500;
    		snakesize = 10;
    		system("cls");
    		gotoxy(8, 8);
    		printf("						 修改成功!
    ");
    		printf("						 
    ");
    		system("pause");
    		break;
    	case 2:
    		len = 4;
    		speed = 300;
    		snakesize = 25;
    		system("cls");
    		gotoxy(8, 8);
    		printf("						 修改成功!
    ");
    		printf("						 
    ");
    		system("pause");
    		break;
    	case 3:
    		len = 4;
    		speed = 70;
    		snakesize = 50;
    		system("cls");
    		gotoxy(8, 8);
    		printf("						 修改成功!
    ");
    		printf("						 
    ");
    		system("pause");
    		break;
    	case 4:
    		len = 4;
    		speed = 25;
    		snakesize = 70;
    		system("cls");
    		gotoxy(8, 8);
    		printf("						 修改成功!
    ");
    		printf("						 
    ");
    		system("pause");
    		break;
    	default:
    		break;
    	}
    }
    int customize()
    {
    	char s;
    	int a;
    	system("cls");
    	printf("
    
    						1.自定义速度
    ");
    	printf("
    						2.自定义初始长度
    ");
    	printf("
    						请选择(数字)");
    	while (1)
    	{
    		s = getchar();
    		a = (int)s - 48;
    		if (s <= '2' && s >= '1')
    			return a;
    		printf("
    							      ");
    	}
    }
    void customize1()
    {
    	int s;
    	switch (customize())
    	{
    	case 1://自定义速度
    		system("cls");
    		gotoxy(8, 8);
    		printf("				请输入速度(1-999)");
    		scanf_s("%d", &s);
    		speed = (1000 - s);
    		break;
    	case 2:
    		system("cls");
    		gotoxy(8, 8);
    		printf("				请输入初始长度:");
    		scanf_s("%d", &s);
    		len = s;
    		break;
    	default:
    		break;
    	}
    }
    
  • 相关阅读:
    第七十一课 图的定义与操作
    第七十课 二叉树经典面试题分析
    第六十九课 二叉树的线索化实现
    第六十八课 二叉树的比较与相加
    第六十七课 二叉树的典型遍历方式
    第六十六课 二叉树结构的层次遍历
    第六十五课 二叉树中属性操作的实现
    2018华为笔试题
    交错01串
    操作序列(网易)
  • 原文地址:https://www.cnblogs.com/hunanloudi/p/14530683.html
Copyright © 2011-2022 走看看