项目实践---贪吃蛇小游戏(下)

  • 对于贪吃蛇小游戏,最主要的还是主函数部分,这里就和大家一一列举出来,
  • 上一章已经写过头文件了,这里就不多介绍了。

  • 首先就是打印桌面,也就是背景,则对应的代码为:
void SetPos(short x, short y)
{
	//获取标准输出设备的句柄
	HANDLE houtput = NULL;
	houtput = GetStdHandle(STD_OUTPUT_HANDLE);


	//定位光标的位置
	COORD pos = { x,y };
	SetConsoleCursorPosition(houtput, pos);
}


void WelcomeToGame()
{
	system("cls");
	SetPos(40, 14);
	wprintf(L"欢迎来到贪吃蛇小游戏\n");
	SetPos(42, 20);
	system("pause");
	system("cls");
	SetPos(35, 14);
	wprintf(L"用 w.s.a.d来控制蛇的移动,按q加速,e减速\n");
	SetPos(35, 15);
	wprintf(L"加速能够得到更高的分数\n");

	SetPos(42, 20);
	system("pause");
	system("cls");

}

  • 然后就是打印墙体,在打印墙体之前,要先声明一下类型,用#define,来定义。则对应的代码为:
void CreateMap()
{
	//上
	int i = 0;
	SetPos(0, 0);
	for (i = 0; i < 58; i ++)
	{
		wprintf(L"%lc", WALL);
	}

	//下
	SetPos(0, 26);
	for (i = 0; i < 58; i++) 
	{
		wprintf(L"%lc", WALL);
	}

	//左
	for (i = 1; i <= 26; i++)
	{
		SetPos(0, i);
		wprintf(L"%lc", WALL);
	}

	//右
	for (i = 1; i <= 26; i++)
	{
		SetPos(56, i);
		wprintf(L"%lc",WALL);

	}
}

  • 然后就是创建蛇身(用链表来实现)和食物,则代码为:
    void InitSnake(pSnake ps)
    {
    	int i = 0;
    	pSnakeNode cur = NULL;
    
    	for (i = 0; i < 6; i++)
    	{
    		cur = (pSnakeNode)malloc(sizeof(SnakeNode));
    		if (cur == NULL)
    		{
    			perror("InitSnake()::malloc");
    			return;
    		}
    		cur->next = NULL;
    		cur->x = POS_X + 2 * i;
    		cur->y = POS_Y;
    
    		//头插法插入链表
    
    		if (ps->_pSnake == NULL)  //空链表
    		{
    			ps->_pSnake = cur;
    		}
    		else  //非空
    		{
    			cur->next = ps->_pSnake;
    			ps->_pSnake = cur;
    		}
    	}
    
    	cur = ps->_pSnake;
    	while (cur)
    	{
    		SetPos(cur->x, cur->y);
    		wprintf(L"%lc", BODY);
    		cur = cur->next;
    	}
    
    
    	//设置贪吃蛇得属性
    	ps->_dir = RIGHT; //默认向右
    	ps->_score = 0;
    	ps->_food_weight = 10;
    	ps->_sleep_time = 200;   //单位是ms
    	ps->_status = OK;
    }
    
    
    void CreateFood(pSnake ps)
    {
    	int x = 0;
    	int y = 0;
    
    
    	//生成2的倍数
    	//x:2~53
    	//y:1~25
    
    again:
    	do
    	{
    		x = rand() % 53 + 2;
    		y = rand() % 25 + 1;
    	} while (x % 2 != 0);
    
    
    	//x和y的坐标不能和蛇的身体坐标冲突
    
    
    	pSnakeNode cur = ps->_pSnake;
    	while(cur)
    	{
    		if (x == cur->x && y == cur->y)
    		{
    			goto again;
    		}
    
    		cur = cur->next;
    	}
    
    	//创建食物的节点
    
    	pSnakeNode pFood = (pSnakeNode)malloc(sizeof(SnakeNode));
    	if (pFood == NULL)
    	{
    		return;
    	}
    	pFood->x = x;
    	pFood->y = y;
    	pFood->next = NULL;
    
    	SetPos(x, y);//定义位置
    
    	wprintf(L"%lc", FOOD);
    	ps->_pFood = pFood;
    }

    有点小多,请耐心看完哦。

  • 蛇的移步和游戏的初始化,则代码为:
    void GameStart(pSnake ps)
    {
    	//1.先设置窗口得大小,再光标隐藏
    	system("mode con cols = 100 lines = 30");
    	system("title 贪吃蛇");
    	HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);
    
    	//隐藏光标操作
    	CONSOLE_CURSOR_INFO CursorInfo;
    	GetConsoleCursorInfo(houtput, &CursorInfo);//获取控制台光标信息
    	CursorInfo.bVisible = false; //隐藏控制台光标
    	SetConsoleCursorInfo(houtput, &CursorInfo);  //设置控制台光标状态
    
    	//2.打印环境界面和功能介绍
    	WelcomeToGame();
    
    	//3.绘制地图
    	CreateMap();
    
    	//4.创建蛇
    	InitSnake(ps);
    
    	//5.创建食物
    	CreateFood(ps);
    }
    
    void SnakeMove(pSnake ps)
    {
    	//创建一个节点,表示蛇即将到的下一个节点
    	pSnakeNode pNextNode = (pSnakeNode)malloc(sizeof(SnakeNode));
    	if (pNextNode == NULL)
    	{
    		perror("SnakeMove()::malloc()");
    		return;
    	}
    	switch (ps->_dir)
    	{
    	case UP:
    		pNextNode->x = ps->_pSnake->x;
    		pNextNode->y = ps->_pSnake->y - 1;
    		break;
    
    	case DOWN:
    		pNextNode->x = ps->_pSnake->x;
    		pNextNode->y = ps->_pSnake->y + 1;
    		break;
    
    	case LEFT:
    		pNextNode->x = ps->_pSnake->x-2;
    		pNextNode->y = ps->_pSnake->y;
    		break;
    
    	case RIGHT:
    		pNextNode->x = ps->_pSnake->x+2;
    		pNextNode->y = ps->_pSnake->y;
    		break;
    	}
    
    	//检测下一个坐标处是否是食物
    	if (NextIsFood(pNextNode, ps))
    	{
    		EatFood(pNextNode, ps);
    	}
    	else
    	{
    		NoFood(pNextNode, ps);
    	}
    }

  • 判断下一个坐标是否是食物和下一个位置是食物和下一个位置不是食物,就吃掉食物:则代码为:

    int NextIsFood(pSnakeNode pn, pSnake ps)
    {
    	return (ps->_pFood->x == pn->x && ps->_pFood->y == pn->y);
    }
    
    void EatFood(pSnakeNode pn, pSnake ps)
    {
    	//头插法
    	ps->_pFood->next = ps->_pSnake;
    	ps->_pSnake = ps->_pFood;
    
    	//释放下一个位置的节点
    	free(pn);
    	pn = NULL;
    
    
    	pSnakeNode cur = ps->_pSnake;
    
    	//打印蛇
    	while (cur)
    	{
    		SetPos(cur->x, cur->y);
    		wprintf(L"%lc", BODY);
    		cur = cur->next;
    	}
    	ps->_score += ps->_food_weight;
    
    	//重新创建食物
    	CreateFood(ps);
    }
    
    void NoFood(pSnakeNode pn, pSnake ps)
    {
    	//头插法
    	pn->next = ps->_pSnake;
    	ps->_pSnake = pn;
    
    	pSnakeNode cur = ps->_pSnake;
    	while (cur->next->next != NULL)
    	{
    		SetPos(cur->x, cur->y);
    		wprintf(L"%lc", BODY);
    		cur = cur->next;
    	}
    
    	//把最后一个节点打印成空格
    	SetPos(cur->next->x, cur->next->y);
    	printf(" ");
    
    	//释放最后一个节点
    	free(cur->next);
    
    	//把倒数第二个节点的地址置为NULL
    	cur->next = NULL;
    }

    确实多,请耐心看完。

  • 游戏运行的逻辑,则代码为:
    void GameRun(pSnake ps)
    {
    	//打印帮助信息
    	PrintHelpInfo();
    
    
    	do
    	{
    		//打印总分数和食物的分值
    		SetPos(64, 10);
    		printf("总分数:%d\n", ps->_score);
    		SetPos(64, 11);
    		printf("当前食物的分数:%d\n", ps->_food_weight);
    
    		if (KEY_PRESS(VK_UP) && ps->_dir != DOWN)
    		{
    			ps->_dir = UP;
    		}
    		else if (KEY_PRESS(VK_DOWN) && ps->_dir != UP)
    		{
    			ps->_dir = DOWN;
    		}
    		else if (KEY_PRESS(VK_LEFT) && ps->_dir != RIGHT)
    		{
    			ps->_dir = LEFT;
    		}
    		else if (KEY_PRESS(VK_RIGHT) && ps->_dir != LEFT)
    		{
    			ps->_dir = RIGHT;
    		}
    		else if (KEY_PRESS(VK_SPACE))
    		{
    			pause();
    		}
    		else if (KEY_PRESS(VK_ESCAPE))
    		{
    			//正常退出游戏
    			ps->_status = END_NORMAL;
    
    		}
    		else if (KEY_PRESS(VK_F3))
    		{
    			//加速
    			if (ps->_sleep_time > 80)
    			{
    				ps->_sleep_time -= 30;
    				ps->_food_weight += 2;
    			}
    		}
    		else if (KEY_PRESS(VK_F4))
    		{
    			//减速
    			if (ps->_food_weight > 2)
    			{
    				ps->_sleep_time += 30;
    				ps->_food_weight -= 2;
    			}
    		}
    
    		SnakeMove(ps); //蛇走一步的过程
    
    		Sleep(ps->_sleep_time);
    
    	} while (ps->_status == OK);
    }

  • 暂停响应,检测蛇是否撞墙,检测是否撞到自己和结束游戏 - 善后工作,则代码为:
    void pause()
    {
    	while (1)
    	{
    		Sleep(200);
    		if(KEY_PRESS(VK_SPACE))
    		{
    			break;
    		}
    	}
    }
    
    void KillByWall(pSnake ps)
    {
    	if (ps->_pSnake->x == 0 || ps->_pSnake->x == 56 || ps->_pSnake->y == 0 || ps->_pSnake->y == 26)
    	{
    		ps->_status = KILL_BY_WALL;
    	}
    }
    
    void KillBySelf(pSnake ps)
    {
    	pSnakeNode cur = ps->_pSnake->next;
    	while (cur)
    	{
    		if (cur->x == ps->_pSnake->x && cur->y == ps->_pSnake->y)
    		{
    			ps->_status = KILL_BY_SELF;
    			break;
    		}
    		cur = cur->next;
    	}
    }
    
    void GameEnd(pSnake ps)
    {
    	SetPos(24, 12);
    	switch (ps->_status)
    	{
    	case END_NORMAL:
    		wprintf(L"你主动退出\n");
    		break;
    	case KILL_BY_WALL:
    		wprintf(L"您撞上自己了 ,游戏结束!\n");
    		break;
    	case KILL_BY_SELF:
    		wprintf(L"您撞墙了,游戏结束!\n");
    		break;
    	}
    
    
    	//释放蛇身的链表
    
    	pSnakeNode cur = ps->_pSnake;
    	while (cur)
    	{
    		pSnakeNode del = cur;
    		cur = cur->next;
    		free(del);
    	}
    }
    
    

  • 这贪吃蛇的主函数代码确实多,但也是最重要一部分。请大家耐心看完哦。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

huggingface模型下载至本地并调用教程

huggingface内有许多预训练模型&#xff0c;可以在线调用模型或者将模型部署至本地&#xff0c;但有时候通过网址调用模型会很慢&#xff0c;有些服务器甚至无法通过网址调用… 那么&#xff0c;正题&#xff0c;如何将huggingface的模型部署至本地呢&#xff1f;其实很简单&am…

el-image组件预览图片同时操作页面

背景&#xff1a;el-image组件打开预览效果不能滑动页面。 Q:那么如何才能在打开遮罩层后还能操作页面呢&#xff1f; A:改变遮罩层的大小。CSS3有一个属性width&#xff1a;fit-content&#xff1b;可以解决这个问题。 打开F12看看饿了么的原生样式如下 加上width&#xff1…

R可视化:ggplot2绘制双y轴图

介绍 ggplot2绘制双y轴图加载R包 knitr::opts_chunk$set(message = FALSE, warning = FALSE) library(tidyverse) library(readxl)# rm(list = ls()) options(stringsAsFactors = F) options(future.globals.maxSize = 10000 * 1024^2)Importing data 下载Underdetection of c…

网页自动跳转到其他页面,点击浏览器返回箭头,回不到原来页面的问题

背景&#xff1a;今天产品提个需求&#xff0c;需要从index页面自动触发跳转到下一页面的事件&#xff0c;从而不做任何操作&#xff0c;直接跳转到test页面。 代码是这样的&#xff1a; index.vue: <template><div style"width:500px;height:600px;background-…

(三)Servlet教程——Tomcat安装与启动

首先打开浏览器在浏览器地址栏中输入清华大学开源软件镜像站地址&#xff0c;地址如下 https://mirrors.tuna.tsinghua.edu.cn/ 输入地址后回车会出现如下图所示的界面 在该界面找tomcat不是很好找&#xff0c;在搜索框中输入apache然后回车&#xff0c;输入apache后并回车后出…

WebSocket的原理、作用、API、常见注解和生命周期的简单介绍,附带SpringBoot示例

文章目录 原理作用客户端 API服务端 API生命周期常见注解SpringBoot示例 WebSocket是一种 通信协议 &#xff0c;它在 客户端和服务器之间建立了一个双向通信的网络连接 。WebSocket是一种基于TCP连接上进行 全双工通信 的 协议 。 WebSocket允许客户端和服务器在 单个TCP连接上…

AI道路交通违章智能抓拍系统解决方案

项目概述 背景 目前&#xff0c;XX市市全市民用汽车保有量94.62万辆&#xff0c;比上年末增长15.9%&#xff0c;其中私人汽车保有量35.48万辆&#xff0c;减少0.01%。轿车保有量39.45万辆&#xff0c;增长82.1%&#xff0c;其中私人轿车38.65万辆&#xff0c;增长82.1%。电动自…

【项目实战】基于高并发服务器的搜索引擎

【项目实战】基于高并发服务器的搜索引擎 目录 【项目实战】基于高并发服务器的搜索引擎搜索引擎部分代码index.htmlindex.hpplog.hppparser.cc&#xff08;用于对网页的html文件切分且存储索引关系&#xff09;searcher.hpputil.hpphttp_server.cc&#xff08;用于启动服务器和…

免费https证书申请

HTTPS证书&#xff0c;也称为SSL证书&#xff08;Secure Sockets Layer&#xff09;或TLS证书&#xff08;Transport Layer Security&#xff09;&#xff0c;是一种数字证书&#xff0c;用于在互联网通信中确保数据传输的安全性、完整性和真实性。它是基于公钥基础设施&#x…

VirtualFlow亮相核反应堆技术全国重点实验室2024学术年会

为加强先进核能技术领域科技创新与应用&#xff0c;核反应堆技术全国重点实验室及先进核能技术全国重点实验室2024年学术年会在四川成都启幕&#xff0c;9名院士和近百家科研院所、高校和企业等近700名专家学者齐聚一堂&#xff0c;聚焦和探讨核反应堆及先进核能重大基础理论和…

RAG开山之作:结合参数化与非参数化记忆的知识密集型NLP任务新解法

20年RAG刚提出时的论文&#xff1a;Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks&#xff0c;也算是RAG的开山之作之一了。 摘要&#xff1a;检索增强生成&#xff08;RAG&#xff09;方法结合了预训练语言模型与基于检索的非参数化记忆&#xff0c;通过…

正整数的性质:和与根

目录 数字和 数字和介绍 数字和简单应用 哈沙德数 最小元素各数位之和 数字根 数字根介绍 数字根简单应用 数字和 数字和介绍 简单来说&#xff0c;数字和即一个整数数字每一位数值相加求和所得的值&#xff0c;数字和可以为任意正整数&#xff0c;使用代码获取一个数值的数字和…

Git笔记-配置ssh

Git在Deepin中的ssh配置 一、环境二、安装1. 查看GitHub账户2. 配置 git3. 生成 ssh key 三、配置 一、环境 系统&#xff1a; Deepin v23 Git仓库&#xff1a;GitHub 二、安装 1. 查看GitHub账户 在设置界面看到自己的邮箱&#xff0c;这个邮箱就是后面会用到的邮箱 2. …

在Java中使用XxlCrawler时防止被反爬的几种方式

目录 前言 一、常见的反爬措施 1、User-Agent识别 2、Referer识别 3、频率限制 4、IP限制 二、XxlCrawer的应对之道 1、User-Agent应对 2、频率限制 3、IP限制 三、XxlCrawler执行解析 1、XxlCrawler对象 2、启动对象 3、信息爬取线程 总结 前言 众所周知&#x…

LAMMPS单层石墨烯建模

本文主要介绍两种晶胞建模方式。 一、Z形晶胞 晶胞分析&#xff1a;a1沿水平x轴方向&#xff0c;a2沿垂直y轴方向。石墨烯是二维结构&#xff0c;a3取小于单层石墨烯厚度。假设石墨烯键长L1.421&#xff0c;则a13L&#xff0c;a21.732L&#xff0c;a32L&#xff08;低于3.35即…

IDEA离线安装插件

1、下载地址 https://plugins.jetbrains.com/idea 如果去其他编辑器&#xff0c;点击下拉&#xff0c;选择即可。 2.搜索 在输入框输入关键词&#xff0c;按照提示选择即可&#xff0c;点击搜索按钮&#xff0c;查看结果。 3、选择版本 按照自己的版本选择合适的版本 4、安…

探索比特币符文热:市场趋势与持续性分析

在加密货币世界中&#xff0c;比特币一直是备受关注的焦点之一。然而&#xff0c;近年来&#xff0c;随着DeFi&#xff08;去中心化金融&#xff09;的兴起&#xff0c;一种新的潮流开始崭露头角——比特币符文。本文将探讨比特币符文的兴起&#xff0c;分析市场趋势&#xff0…

FTP与SMB深度对比:文件传输协议谁更胜一筹?

在数字化时代&#xff0c;文件传输已成为日常工作中不可或缺的一部分。 FTP&#xff08;文件传输协议&#xff09;和SMB&#xff08;服务器消息块&#xff09;是两种最为常见的文件传输协议。它们各自在文件传输领域拥有独特的优势和特点&#xff0c;但同时也存在一些差异。 今…

【学习】软件测试自动化,是未来的趋势还是当前的必需

在当今快速迭代的软件开发周期中&#xff0c;速度和质量成为了企业生存的关键。随着DevOps实践的普及和持续集成/持续部署&#xff08;CI/CD&#xff09;流程的标准化&#xff0c;软件测试自动化已经从未来的趋势转变为当前的必要性。本文将探讨自动化测试的现状、必要性以及其…

C基础语法速览

叠甲&#xff1a;以下文章主要是依靠我的实际编码学习中总结出来的经验之谈&#xff0c;求逻辑自洽&#xff0c;不能百分百保证正确&#xff0c;有错误、未定义、不合适的内容请尽情指出&#xff01; 文章目录 1.数据类型1.1.数据类型的常见分类1.2.数据类型的符号修饰1.3.数据…