用C语言实现经典游戏——贪吃蛇

news2024/9/30 11:34:31

目录

1.游戏实现思想

(1)定义蛇对象

(2)食物对象

(3)分数: 

(4)初始化蛇

(5)初始化食物

(6)修改控制台光标位置

(7)画出蛇和食物

(8)蛇的移动控制

(9)开始游戏 

(10)蛇移动

(11)画墙

(12)去除蛇尾

(13)去除光标

(14)显示分数

(15)加速

2.游戏实现代码和头文件


该项目适合刚学完C语言结构体,有一定C语言基础的练习,该小项目可以帮助自己锻练的面向对象编程思想。

1.游戏实现思想

要想实现贪吃蛇游戏,根据面向对象的思想,要实现出以下几个模块

1. 定义蛇对象、食物对象

2. 初始化蛇、初始化食物

3. 控制流程:

        1) 蛇头和墙壁的碰撞

        2) 蛇头和蛇身体的碰撞

        3) 蛇头和食物的碰撞

            1> 蛇身增长

            2> 食物消失 -- 新食物产生

            3> 分数累加

            4> 移动速度增大

      4)蛇的移动

            自动移动

            手动控制移动: ASWD --- 左下上右

       5)显示分数

            排行榜 

  4. 图形界面。


(1)定义蛇对象

蛇对象实现方式原理是坐标,而设置X,Y分别表示横坐标与纵坐标,身体使用数组方式表示可以body[0],表示蛇头,其他表示蛇身,蛇的大小会根据吃的食物个数而增加。

struct BODY {

		int x;

		int Y;
	};

	struct SNAKE {

		struct BODY body[20*60];	// 蛇身 。 body[0] -- 蛇头

		int size;			// 蛇的大小
	}snake;

 

(2)食物对象

食物对象实现和蛇对象实现同理

struct FOOD {

		int X;

		int Y;
	}food;

(3)分数: 
 

    int score;

(4)初始化蛇

封装一个函数 完成蛇的初始,蛇的初始大小为2,分别表示蛇身和蛇头


	void initSnake(void)
	{
		snake.size = 2;

		snake.body[0].X = WIDE/2;		// 初始化好了蛇头
		snake.body[0].Y = HiGH/2;

		snake.body[1].X = WIDE/2 - 1;		// 初始化一节蛇身
		snake.body[1].Y = HIGH/2;
	}

(5)初始化食物

void initFood(void)
	{	
		food.X = rand() % WIDE;  // 0-59
		food.Y = rand() % HIGH;  // 0-59

		return;
	}

(6)修改控制台光标位置

会将光标位置,定位到 初始化好的蛇头位置(WIDE/2, HIGH/2). 屏幕中间 。注意实现下面代码要用到头文件:#include <conio.h>,#include <Windows.h>

COORD coord;		// COORD  --> 结构体, 有两个成员变量:x,y 坐标

	coord.X = snake.body[0].X;
	coord.Y = snake.body[0].Y;

	setConsoleCursorPositon(GetStdHandle(STD_OUTPUT_HANDLE), coord);

(7)画出蛇和食物

“@”表示蛇头,“*”表示蛇身。“#”表示食物

封装函数, initUI()

	COORD coord = {0};					// 光标移动的位置。

	// 画蛇
	for (size_t i = 0; i < snake.size; i++)
	{
		coord.X = snake.body[i].X;
		coord.Y = snake.body[i].Y;

		SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);

		if (i == 0)
			putchar('@');
		else
			putchar('*');
	}

	// 画食物
	coord.X = food.X;
	coord.Y = food.Y;

	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);

	putchar('#');

(8)蛇的移动控制

键盘输入

  W:(0, -1)  --> 影响蛇头。

    s:(0, +1)

    A:(-1, 0)

    D:(+1, 0)


    不回显:可以让键盘打的asdw不显示在输入界面

        getch()    接收用户输入。    

        char key = getch();

        编译时出错,尝试使用 _getch();


    不阻塞:可以让输入的小蛇光标不阻塞

        kbhit(); 不阻塞判断用户输入。

        有用户输入,返回 “真”, 否则返回“假”值。

        编译时出错,尝试使用 _kbhit();

(9)开始游戏 

void playGame(void)
	{

		char key = 'd'; // 默认蛇向右移动

		// 蛇头和墙壁的碰撞:

		while ( 判断是否撞墙 ) {

			// 重画蛇身 intiUI

			// 接收用户键盘输入。

				在全局 添加:kx, ky --》 根据 asdw 按键得不同坐标,影响蛇头

			// 蛇头和身体的碰撞

			// 蛇与食物的碰撞
			
			// 蛇身体移动 : 前一节给后一节赋值,蛇头收 kx ky 的影响。

			system("cls");  清屏 -- 去除蛇尾。
		}
	}

蛇头和墙壁的碰撞

判断条件

snake.body[0].X > 0 && snake.body[0].X < WIDE 
		&&
		  snake.body[0].Y > 0 && snake.body[0].Y < HIGH

蛇头和身体的碰撞    

蛇头的坐标 和 任意一节身体的坐标 完全一致。

for(i = 1; i < snake.size; i++)
		{
			if (snake.body[0].X == snake.body[i].X && snake.body[0].Y == snake.body[i].Y )
			{
				终止游戏。
				return ;
			}
		}


    蛇头和食物的碰撞

if (snake.body[0].X == food.X && snake.body[0].Y == food.Y)
		{
			蛇身增长: snake.size++;

			食物消失:(产生一个新食物)initFood()

			加分:score += 10;

			加速:sleepSecond -= 20;
		}

(10)蛇移动

    前一节身体给后一节身体赋值。 蛇头按照 aswd 换算的坐标值 进行变换。

      

  for (size_t i = snake.size-1; i > 0; i--)
        {
            snake.body[i].X = snake.body[i - 1].X;
            snake.body[i].Y = snake.body[i - 1].Y;
        }
        snake.body[0].X += kx;        // 蛇头坐标根据用户按键,修改。
        snake.body[0].Y += ky;

(11)画墙

void initWall(void)
{
	for (size_t i = 0; i <= HIGH; i++)	// 多行
	{
		for (size_t j = 0; j <= WIDE; j++)			// 一行中的多列
		{
			if (j == WIDE)
			{
				printf("|");
			}
			else if (i == HIGH)
			{
				printf("_");
			}
			else
			{
				printf(" ");
			}
		}
		printf("\n");
	}
}

(12)去除蛇尾

蛇移动之前保存蛇尾坐标。

    定义全局变量 :lastX, lastY;

    lastX = snake.body[snake.size-1].X ;

    lastY = snake.body[snake.size-1].Y ;

    在initUI中, 将蛇尾 替换为 ' '

coord.X = lastX;

		coord.Y = lastY;

		setConsoleCursorPosition(GetSTDHandler(STD_OUTPUT_HANDLE), coord);

		putchar(' ');

(13)去除光标

取消显示的光标:请按任意位置继续,使得界面更美观

typedef struct _CONSOLE_CURSOR_INFO {
    		DWORD  dwSize;		// 大小
    		BOOL   bVisible;	// 是否可见。
	} CONSOLE_CURSOR_INFO;

	定义结构体变量:

		CONSOLE_CURSOR_INFO  cci;

		cci.dwSize = sizeof(cci);

		cci.bVisible = FALSE; //  0 假 --- 不可见

	设置光标不可见生效:

		setConsoleCursorInfo(GetSTDHandler(STD_OUTPUT_HANDLE), &cci);


	在main函数中,调用一次即可生效。

(14)显示分数

    playGame调用结束时,打印 全局score 值。

(15)加速

全局定义变量: sleepSecond = 400;

            Sleep(sleepSecond);

            成功吃食物,    sleepSecond -= 20;

2.游戏实现代码和头文件

游戏使用建议使用VS编辑器,不建议初学者使用dev编辑器,下面有完整代码和实现好的exe文件,感兴趣的可以打包带走。

下图是代码实现后

 


 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/687388.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring Data JPA 报 HOUR_OF_DAY: 0 -> 1异常的解决过程和方案

在进行数据查询时&#xff0c;控制台报了Caused by: com.mysql.cj.exceptions.WrongArgumentException: HOUR_OF_DAY: 0 -> 1异常&#xff0c;查询得知&#xff1a;这是由于查mysql库&#xff0c;转换类型为datetime类型的字段引起的。 网上的解决方案有多种&#xff0c;大…

坐标系转换QGIS插件GeoHey

最近要将面要素&#xff08;GCJ02火星坐标系&#xff09;转WGS84&#xff0c;用程序转太麻烦了&#xff0c;找了半天没找到合适的。 插件非常好用&#xff01;&#xff01;&#xff01; 在QGIS中&#xff0c;由极海&#xff08;GeoHey&#xff09;团队提供GeoHey Toolbox插件…

Linux_清理docker容器的log

最近发现服务器硬盘空间满了&#xff0c;就排查了一番&#xff0c;发现有docker容器的log文件占用太多&#xff0c;所以要做一下清理。 首先是要找到docker容器log文件的储存位置。 1、首先在执行了一下 df -Th 命令&#xff0c;发现根目录满了。 2、然后去到根目录下&#xff…

Android项目中接入 Lint代码规范

一、概述 Android Studio 提供了一个名为 Lint 的代码扫描工具,可帮助开发者发现并更正代码结构质量方面的问题,并且无需您实际执行应用,也不必编写测试用例。系统会报告该工具检测到的每个问题并提供问题的描述消息和严重级别,以便开发者可以快速确定需要优先进行的关键改…

Linux下vim的常见命令操作(快速复查)

目录 前言1、Vim常用操作1.1、环境参数1.2、方向1.3、插入命令1.4、定位命令1.5、删除命令1.6、复制和剪切命令1.7、替换和取消命令1.8、搜索和搜索替换命令1.9、保存和退出命令1.10、其他命令1.11、可视模式 前言 本篇文章不面向新手&#xff0c;全文几乎都是命令&#xff0c;…

【Redis】多级缓存之缓存数据同步策略与Canal

目录 一、数据同步策略 1.设置有效期 2.同步双写 3.异步通知 二、Canal 三、监听Canal 一、数据同步策略 缓存数据同步的常见方式有三种&#xff1a; 1.设置有效期 给缓存设置有效期&#xff0c;到期后自动删除。再次查询时更新&#xff0c;他简单、方便&#xff0c;但…

H5学习 (一)--创建工程

文章目录 一、下载安装VS Code二、创建新文件1. 使用cmd N&#xff0c;创建一个文件2. 点击 Select a language&#xff0c;改变文件的编码类型3. 选择HTML 语言模式4. 输入 !按回车键&#xff0c;就会自动生成一个HTML模版5. 右击项目&#xff0c;选择 “Open In Default Bro…

交叉熵、Focal Loss以及其Pytorch实现

交叉熵、Focal Loss以及其Pytorch实现 本文参考链接&#xff1a;https://towardsdatascience.com/focal-loss-a-better-alternative-for-cross-entropy-1d073d92d075 文章目录 交叉熵、Focal Loss以及其Pytorch实现一、交叉熵二、Focal loss三、Pytorch1.[交叉熵](https://pyto…

浅谈商业智能BI的过去、现在和未来

互联网的大发展也在引领各行各业的改变&#xff0c;包括商业智能BI&#xff0c;商业智能BI就是在数字化时代下飞速发展的。商业智能BI与互联网发展的同时&#xff0c;人工智能、大数据、区块链、云计算等新一代信息化、数字化技术也开始进行加速商业智能BI发展及应用&#xff0…

vmareWorkstation-提取vmdk-文件系统

参考博文-CSDN-BugM&#xff08;作者&#xff09;-将vmdk作为硬盘挂载到另一个linux系统的虚拟机上 一、以管理员身份运行wmware-workstation 二、将目的vmdk文件映射到一个linux虚拟机上 选择左下方的添加按钮 添加的文件的路径可以查看需要添加的虚拟机的情况&#xff0c;如…

PXE批量网络装机、PXE无人值守安装

目录 一、批量部署的优点 二、基本部署过程 三、部署pxe网络体系要求 四、搭建PXE远程安装服务器的步骤 1.安装并启用TFTP服务 2.安装并启用dhcp服务 3.准备linux内核、初始化镜像文件 4.准备PXE引导程序 5.安装FTP服务&#xff0c;准备CentOS7安装源 6.配置启动菜单文…

ATA-3090功率放大器在新能源汽车上的应用

随着全球对环境保护和节能减排的重视&#xff0c;新能源汽车正逐渐成为汽车市场的主流。而功率放大器作为电子控制系统中的关键部件之一&#xff0c;也扮演着越来越重要的角色。那么&#xff0c;功率放大器在新能源汽车上的应用有哪些呢&#xff1f; 图&#xff1a;新能源汽车 …

数字IC前端学习笔记:仲裁轮询(五)

相关文章 数字IC前端学习笔记&#xff1a;LSFR&#xff08;线性反馈移位寄存器&#xff09; 数字IC前端学习笔记&#xff1a;跨时钟域信号同步 数字IC前端学习笔记&#xff1a;信号同步和边沿检测 数字IC前端学习笔记&#xff1a;锁存器Latch的综合 数字IC前端学习笔记&am…

聚焦云原生安全|安全专家揭秘如何强化容器威胁检测能力

4月15日&#xff0c;由极狐主办的“当效率遇上安全 一起开启质效升级之旅”活动顺利开展。 作为国内云原生安全领导厂商&#xff0c;安全狗受邀出席此次活动。 厦门服云信息科技有限公司&#xff08;品牌名&#xff1a;安全狗&#xff09;成立于2013年&#xff0c;致力于提供云…

【中危】BootCDN 投毒风险

漏洞描述 BootCDN是免费的前端开源项目 CDN 加速服务&#xff0c;通过同步cdnjs仓库&#xff0c;提供了常用javascript组件的CDN服务。 多个开发者发现在特定请求中&#xff08;如特定Referer及移动端user-agent&#xff09;会返回包含指向union.macoms.la地址的恶意js文件&a…

快速提取地形图坐标到Revit建立场地模型?

一、快速提取地形图坐标到Revit建立场地模型? 1、打开免费三维地形软件&#xff1a; 2、定位项目位置&#xff1a; 3、按步骤提取坐标及高程&#xff1a; 4、保存为csv文件格式&#xff0c;打开CSV文件&#xff0c;删除第一行&#xff1a; 5、打开坐标转换软件&#xff0c;按步…

python3套接字编程之socket和socketserver(TCP和UDP通信)

socket和socketserver是python3中socket通信模块&#xff0c;关于其使用做如下总结。 目录 1.socket 1.1模块引入 1.2套接字获取 1.3套接字接口 1.3.1 服务端 1.3.2 客户端套接字函数 1.3.3 公共套接字函数 1.3.4 面向锁的套接字方法 1.3.5 面向文件的套接字的函数 …

Python注释解密、变量大揭秘,数据类型轻松入门!

文章目录 前言注释单行注释多行注释 变量数据类型1.整型&#xff08;int&#xff09;2.浮点型&#xff08;float&#xff09;3.布尔型&#xff08;bool&#xff09;4.字符串&#xff08;str&#xff09;5.列表&#xff08;list&#xff09;6.元组&#xff08;tuple&#xff09;…

RabbitMQ高可用集群部署

文章目录 1.RabbitMQ常见的集群模式2.部署基于镜像队列模式的RabbitMQ高可用集群2.1.镜像队列集群原理2.2.分别在两台机器中部署RabbitMQ2.2.1.基础环境配置2.2.2.安装Erlang环境2.2.3.部署RabbitMQ并开启管理界面2.2.4.配置RabbitMQ各节点变量信息2.2.5.访问RabbitMQ后台管理系…

vue3基础------ 下

目录 二.vue3基础 5.事件处理器 5-1 事件处理器 - 告别原生事件 5-2 事件修饰符 - 事件偷懒符? 6.表单控件绑定 6-1表单输入绑定-一根绳上的蚂蚱 6-2购物车案例 6-3表单修饰符 7.计算属性 7-1计算属性-很聪明&#xff0c;会缓存 7-2 可写计算属性 7-3之前案例的小改…