C++贪吃蛇(控制台版)
C++自学精简实践教程 目录(必读)
目录
主要考察
需求
输入文件
运行效果
实现思路
枚举类型 enum class
启动代码
输入文件data.txt 的内容
参考答案
学生实现的效果
主要考察
模块划分
文本文件读取
UI与业务分离
控制台交互
数据抽象
需求
用户输入字母表示方向,实现贪吃蛇游戏。
规则:碰到边缘和碰到蛇自己都算游戏结束。
输入文件
第一行,包括两个整数,表示游戏棋盘大小。分别表示行数和列数。
后面的内容是一个行数乘以列数的二维数组。
数组的元素为0表示这里没有食物,也没有蛇的身体。
数组的元素为 @ 表示蛇的头。
数组元素为 # 表示蛇的身体。
程序启动一开始运行的时候,蛇没有身体,只有头。
运行效果
实现思路
正式实现代码Snake.cpp只有180行不到。
枚举类型 enum class
enum class 通常用来提供字面值常量。也就是一些固定值。比如,表示方向的东、南、西、北。表示空间的上、下、左、右、前、后。
启动代码
#include <list>
#include <utility>
#include <fstream>
#include <sstream>
#include <iostream>
#include <random>//随机数
#include <chrono>//日期时间
using namespace std;class Snake
{// 游戏的任意位置 只有三种情况:什么也没有;蛇的身体;食物enum class MatrixValueEnum{NOTHING = '0', SNAKE_BODY = '#', FOOD = '2'};
public:// 从文件中加载界面数据,存放到内部容器中,再根据容器内容绘制界面bool LoadPlayDataFromFile(const std::string& file);// 开始游戏void Play(void);
private:// 用户输入一个字符(e/s/f/d),决定将蛇的头部往哪个方向移动bool GoAhead(char userInputDirection);// 核心函数// 移动蛇的头的坐标(x,y) = (x,y) + (i,j)bool GoAhead(int i, int j);//撞到墙壁或者蛇自己的身体就结束游戏bool IsGameOver(int, int) const;// 获取蛇的头的坐标std::pair<int, int> GetCurrentPosition(void) const;// 计算蛇的头移动一次后的新坐标std::pair<int, int> GetNextPosition(int, int) const;// 打印贪吃蛇游戏void PrintMatrix(void) const;// 判断 (i,j) 处是否是一个食物bool ExistFood(int i, int j) const;// 在界面上生成一个新的食物给蛇吃void CreateFood(void);
private:std::vector<std::vector<char>> m_playMatrix;// 整个游戏的数据(二维数组)std::list<std::pair<int, int>> m_snakeBody;// 蛇的身体数据
};bool Snake::LoadPlayDataFromFile(const std::string& file)
{std::ifstream fin(file);if (!fin){std::cout << "can not open file " << file << endl;return false;}std::string line;std::getline(fin, line);std::istringstream iss(line);// 字符串流 https://zhuanlan.zhihu.com/p/441027904int row = 0, column = 0;//读取行数和列数//(1) your codefor (size_t i = 0; i < row; i++){std::vector<char> lineData;std::getline(fin, line);std::istringstream issLineData(line);for (size_t j = 0; j < column; j++){char data;//读取一个元素// (2) your code//将组成蛇的头#存放到蛇m_snakeBody容器中//在文件里,一开始蛇的身体只有一个头,需要把这个数据存起来//(3) your code 判断两个char相等即可// 参考:https://zhuanlan.zhihu.com/p/357348144}//将第一行数据存放到二维数组中,作为第一维的一个元素(子数组)//(4) your code}if (m_snakeBody.size() != 1){cout << "snake body is empty! init game failed." << endl;return false;}return true;
}bool Snake::IsGameOver(int x, int y) const
{//判断游戏是否已经结束了// x y 是蛇的头打算要去的目的地,这个目的地会导致gomeover// 比如超出了游戏界面(下标越界)// 比如撞到了蛇的身体//(5) your codereturn true;
}
std::pair<int, int> Snake::GetCurrentPosition(void) const
{//返回蛇 的头的坐标,是m_snakeBody的第一个元素的值//(6) your code 下面的代码需要自己修改,不可以直接使用std::pair<int, int> front;return front;
}
std::pair<int, int> Snake::GetNextPosition(int i, int j) const
{//根据蛇的头的位置,以及一个移动的向量 (i,j) 得到蛇头部打算要去的新目的地的坐标auto old = GetCurrentPosition();//(7) your code 下面的代码需要自己修改,不可以直接使用int x = 0;int y = 0;return std::make_pair(x, y);
}
bool Snake::ExistFood(int i, int j) const
{//返回 坐标(i,j)处是否是有蛇的食物可以吃//(8) your code 下面的代码需要自己修改,不可以直接使用return false;
}
void Snake::CreateFood(void)
{// 生成一个新的食物给蛇来吃// 随机生成一个新的位置,但是这个位置可能已经是蛇的身体了// 所以,需要用一个循环不断的重复在一个新生成的随机位置放置食物// 直到放置成功为止do{unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();std::mt19937 g(seed); // mt19937 is a standard mersenne_twister_engine//生成新的随机的坐标//随机数的用法:https://blog.csdn.net/calmreason/article/details/72655060//(9) your code 下面的代码需要自己修改,不可以直接使用int x = 0;int y = 0;// 在新坐标处放置一个食物,记得检查可以放才能放// 一旦放好,记得退出循环,让程序继续执行//(10) your code} while (true);
}
bool Snake::GoAhead(char userInputDirection)
{switch (userInputDirection){case 'w':case 'W':return GoAhead(-1, 0);//upcase 'a':case 'A':return GoAhead(0, -1);//leftcase 'd':case 'D':return GoAhead(0, +1);//rightcase 's':case 'S':return GoAhead(+1, 0);//downdefault:return true;}
}
bool Snake::GoAhead(int i, int j)
{auto nextPosition = GetNextPosition(i, j);//垂直方向x不变,竖直方向y减少1// 首先判断游戏是否已经结束if (IsGameOver(nextPosition.first, nextPosition.second)){return false;}// 判断nextPosition 处是否有食物// 如果有食物,就吃掉这个食物// 并生成一个新的食物if (ExistFood(nextPosition.first, nextPosition.second)){// (11) your code//直接吃掉,尾巴不用移动m_playMatrix[nextPosition.first][nextPosition.second] = static_cast<char>(MatrixValueEnum::SNAKE_BODY);CreateFood();//随机生成一个食物}// 如果 nextPosition 处没有食物,就移动蛇的身体else{// (12) your code//尾巴移动 auto tail = m_snakeBody.back();m_playMatrix[tail.first][tail.second] = static_cast<char>(MatrixValueEnum::NOTHING);m_snakeBody.pop_back();}
}void Snake::Play(void)
{CreateFood();//随机生成一个食物while (true){/*清屏,这不是C++的一部分,是系统调用。这个语句执行的快慢与代码无关,与控制台用户自己设置的缓冲区大小有关。*/system("cls");PrintMatrix();std::cout << "direction: W(up) A(left) S(down) D(right)\n";std::cout << "$: food\n";std::cout << "@: snake head\n";std::cout << "#: snake tail\n";char direction;std::cin >> direction;//往前走一步,如果判断无法往前走到用户指定的位置,就退出程序// (13) your codeif (!GoAhead(direction)){std::cout << "Game Over!" << std::endl;break;}}
}
void Snake::PrintMatrix(void) const
{auto headPosition = m_snakeBody.front();for (size_t i = 0; i < m_playMatrix.size(); i++){for (size_t j = 0; j < m_playMatrix[i].size(); j++){if (i == headPosition.first && j == headPosition.second){std::cout << "@" << " ";}else if (m_playMatrix[i][j] == static_cast<char>(MatrixValueEnum::FOOD)){std::cout << "$" << " ";}else if (m_playMatrix[i][j] == static_cast<char>(MatrixValueEnum::NOTHING)){std::cout << "_" << " ";}else{std::cout << m_playMatrix[i][j] << " ";}}std::cout << std::endl;}
}int main(int argc, char** argv)
{Snake snake;if (snake.LoadPlayDataFromFile("data.txt")){snake.Play();}return 0;
}
输入文件data.txt 的内容
7 7
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 # 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
参考答案
贪吃蛇(控制台版)(答案)
其他参考:
Qt版本的一个贪吃蛇实现 Qt Snake C++
学生实现的效果
视频资源加载失败
视频资源加载失败
相关文章:
C++贪吃蛇(控制台版)
C自学精简实践教程 目录(必读) 目录 主要考察 需求 输入文件 运行效果 实现思路 枚举类型 enum class 启动代码 输入文件data.txt 的内容 参考答案 学生实现的效果 主要考察 模块划分 文本文件读取 UI与业务分离 控制台交互 数据抽象 需求 用户输入字母表示方…...
Java之字符串实践
功能概述 字符串是Java编程中常用的数据类型,本文对String部分常见功能做了对应实践以及分析。 功能实践 场景1:字符串比较 用例代码 Test public void test_string_compare() {String s1 "abc";String s2 s1;String s5 "abc&quo…...
BM20 数组中的逆序对
描述 解题思路:归并排序 分治:分治即“分而治之”,“分”指的是将一个大而复杂的问题划分成多个性质相同但是规模更小的子问题,子问题继续按照这样划分,直到问题可以被轻易解决;“治”指的是将子问题单独进…...
高德猎鹰轨迹查询相关接口
高德猎鹰轨迹官网:服务管理-API文档-开发指南-猎鹰轨迹服务 | 高德地图API 轨迹查询 httpclient的post // post方法请求 创建轨迹 private static void createTrace() {String key "高德注册的key";String sid "服务id"; // 服务idString…...
整理总结新手开始抖音小店经营:常见问题及解决办法
抖音小店作为一种新兴的电商模式,在短时间内获得了广泛的关注和使用。然而,对于新手来说,抖音小店经营可能会遇到一些问题。下面是四川不若与众总结的一些常见的问题以及相应的解决办法。 问题一:产品选择困难 对于新手来说&#…...
4-1-netty
非阻塞io 服务端就一个线程,可以处理无数个连接 收到所有的连接都放到集合channelList里面 selector是有事件集合的 对server来说优先关注连接事件 遍历连接事件...
hive 动态分区-动态分区数量太多也会导致效率下降只设置非严格模式也能执行动态分区
hive 动态分区-动态分区数量太多也会导致效率下降&只设置非严格模式也能执行动态分区 结论 在非严格模式下不开启动态分区的功能的参数(配置如下),同样也能进行动态分区数据写入,目测原因是不严格检查SQL中是否指定分区或者…...
java八股文面试[JVM]——JVM调优
知识来源: 【2023年面试】JVM性能调优实战_哔哩哔哩_bilibili...
FairyGUI-Unity 异形屏适配
本文中会修改到FairyGUI源代码,涉及两个文件Stage和StageCamera,需要对Unity的屏幕类了解。 在网上查找有很多的异形屏适配操作,但对于FairyGUI相关的描述操作很少,这里我贴出一下自己在实际应用中的异形屏UI适配操作。 原理 获…...
Oracle监听器启动出错:本地计算机上的OracleOraDb11g_home1TNSListener服务启动后又停止了解决方案
在启动oracle的服务OracleOraDb11g_home1TNSListener时,提示服务启动后又停止了。 解决方法: 修改oracle安装目录下的两个配置文件: 以上两个文件,对应的HOST的值,都改为127.0.0.1 然后再启动服务,启动成…...
Spring复习:(58)<context:annotation-config/>的作用
引入如下的BeanPostProcessor • ConfigurationClassPostProcessor • AutowiredAnnotationBeanPostProcessor • CommonAnnotationBeanPostProcessor • PersistenceAnnotationBeanPostProcessor • EventListenerMethodProcessor如果xml文件配置了bean中使用了Autowired注解…...
“东方杯”英特尔oneAPI黑客松大赛—参赛经验分享
目录 前言1、大赛要求2、oneMKL介绍3、准备 oneMKL基本使用1、下载:2、安装:3、初始化oneMKL环境:4、编译代码5、运行 所需的头文件使用oneMKL工具生成随机数使用fftw3计算FFT调用oneMKL API加速计算FFT对比两种方法的准确性输出结果结束语 前…...
win10家庭版远程桌面补丁_rdp wrapper
RDP Wrapper Library 就是可以帮你在 Windows 7、Windows 8、Windows 10 家庭版中打开远程桌面的工具。 1、把电脑上打开的安全软件与杀毒软件都关掉,因为这个远程桌面补丁会修改系统文件,所以安全软件可能会拦截。 2、下载RDP Wrapper Library补丁压缩…...
【C++设计模式】开放-封闭原则
2023年8月27日,周日下午 我觉得我的这篇博客还是写得很不错的,哈哈哈。 目录 概述举例说明用开放-封闭原则重构 概述 开放-封闭原则(Open-Closed Principle,OCP)是面向对象设计中的一个重要原则,也是许多…...
vue+file-saver+xlsx+htmlToPdf+jspdf实现本地导出PDF和Excel
页面效果如下(echarts图表按需添加,以下代码中没有) 1、安装插件 npm install xlsx --save npm install file-saver --save npm install html2canvas --save npm install jspdf --save2、main.js引入html2canvas import htmlToPdf from …...
axios 进阶
axios 进阶 接口传参方式 使用 xhr 原生技术或者是 axios 时,它的 post 传参方式是键值对的形式 keyvalue。但是在实际开发中一般是使用对象的形式定义数据,方便读取和赋值。所以当我们需要发起请求时可以通过 qs 这一款插件将对象转成键值对形式&…...
Redis限流实践:实现用户消息推送每天最多通知2次的功能
🏆作者简介,黑夜开发者,CSDN领军人物,全栈领域优质创作者✌,CSDN博客专家,阿里云社区专家博主,2023年6月CSDN上海赛道top4。 🏆数年电商行业从业经验,历任核心研发工程师…...
uniapp 存储base64资源为http链接图片
1. 新建一个base64.js 文件 const fsm wx.getFileSystemManager(); // base64data base64资源 // name 文件名 function base64src(base64data, name, cb) {const time new Date().getTime();const filePath ${wx.env.USER_DATA_PATH}/${name}.${time}.png;const buffer …...
列表类控件虚拟化
WPF列表控件提供的最重要的功能是UI虚拟化(WPF编程宝典说的)。所有的WPF列表控件(所有继承自ItemsControl的控件,包括ListBox、CombBox、ListView、TreeView、DataGrid)都支持UI虚拟化。 UI虚拟化的支持实际上没有被构…...
c# 多线程Task.Run 取消正在执行的多线程
c# 异步处理,上次处理没有完成,下次有紧接着处理多线程出错 在 C# 中进行异步处理时,确保处理上一个任务完成后再处理下一个任务是很重要的,特别是在涉及多线程的情况下。如果上一个任务尚未完成,而下一个任务又开始执…...
sql server 如何设置主键
开始之前 限制和局限 一个表只能包含一个 PRIMARY KEY 约束。 在 PRIMARY KEY 约束中定义的所有列都必须定义为 NOT NULL。 如果没有指定为 Null 性,则加入 PRIMARY KEY 约束的所有列的为 Null 性都将设置为 NOT NULL。 创建主键会自动创建相应的唯一群集索引、…...
【LeetCode-中等题】19. 删除链表的倒数第 N 个结点
文章目录 题目方法一:节点加入集合找索引方法二:直接计算长度,然后找出要删除的节点的前一个节点方法三:栈方法四:前后双指针 题目 这题的关键在与两个点 一定要设置一个哑结点,防止删除第一个元素时,导致空…...
Matlab图像处理-减法运算
减法运算 图像减法也称为差分方法,是一种常用于检测图像变化及运动物体的图像处理方法。常用来检测一系列相同场景图像的差异,其主要的应用在于检测同一场景下两幅图像之间的变化或是混合图像的分离。 差影法 将同一景物在不同时问拍摄的图像或同一景…...
stm32之11.USART串口通信
可以添加上拉电阻,但会增加功耗,传输距离变长 要添加库函数USART 官方参考文档说明书位置 ALT+左键可实现整体删除(如下图) 输出模式第三种模式AF ---------------------- 源码 远程控制pc端 #include <stm32f4x…...
Python实现T检验
今天来分享一下T检验的python实现方法。 01 先来上一波概念。 1.单样本t检验,又称单样本均数t检验,适用于来自正态分布的某个样本均数与已知总体均数的比较,其比较目的是检验样本均数所代表的总体均数是否与已知总体均数有差别。已知总体均数…...
校招算法题实在不会做,有没有关系?
文章目录 前言一、校招二、时间复杂度1、单层循环2、双层循环 三、空间复杂度四、数据结构五、校招算法题实在不会做,有没有关系?六、英雄算法集训 前言 英雄算法联盟八月集训 已经接近尾声,九月算法集训将于 09月01日 正式开始,目…...
Michael.W基于Foundry精读Openzeppelin第32期——SignatureChecker.sol
Michael.W基于Foundry精读Openzeppelin第32期——SignatureChecker.sol 0. 版本0.1 SignatureChecker.sol 1. 目标合约2. 代码精读2.1 isValidSignatureNow(address signer, bytes32 hash, bytes memory signature) 0. 版本 [openzeppelin]:v4.8.3,[for…...
如何修改字符串内容?
⭐ 作者:小胡_不糊涂 🌱 作者主页:小胡_不糊涂的个人主页 📀 收录专栏:浅谈Java 💖 持续更文,关注博主少走弯路,谢谢大家支持 💖 String 1. 修改字符串2. StringBuilder和…...
pgadmin4中的备份与恢复
一,postgresql 数据的备份与恢复 (一)数据库备份与恢复 1,备份 windows环境 1> dump 逻辑备份 1,用管理员身份打开power shell 2,切换到本机 postgresql 安装目录下的 bin 目录: PS C…...
内网穿透——搭建私人影音媒体平台
文章目录 1. 前言2. Jellyfin服务网站搭建2.1. Jellyfin下载和安装2.2. Jellyfin网页测试 3.本地网页发布3.1 cpolar的安装和注册3.2 Cpolar云端设置3.3 Cpolar本地设置 4.公网访问测试5. 结语 1. 前言 随着移动智能设备的普及,各种各样的使用需求也被开发出来&…...
学做网站多长时间/教育培训机构平台
周四见 公开课系列We,知数堂习惯用实力介绍自己—我们只分享干货重磅福利来袭2018年8月9日,20:30-22:00周四见不见不散!郑 松 华知数堂《SQL优化》课程讲师资深数据库工程师对SQL优化有独到见解7年SQL开发和调优经验于韩国法院数据中心从事数据库技术支…...
学生做兼职的网站/宝塔建站系统
这几日,看了一些博客。发现在一些博客的底部添加了一些版权信息,很新颖。如下图: 写信给博客园的客服,问如何做出来的。回复是添加自己的“签名”。无语了,只能自己研究了。 在分析了别人的页面后,终于摸索…...
建设厅网站平顶山/沈阳cms建站模板
❝作者介绍:何凯,百度商业平台研发部-资深研发工程师,主要负责商业平台创意中心前端技术研发与架构,专注于打造创意中心前端SDK技术架构,赋能业务系统创意管理、推荐、制作和加工等创意核心能力,持续快速迭…...
做网站工作怀孕/百度用户服务中心人工24小时电话
转自百度百科 数据库防火墙 系统,串联部署在数据库服务器之前,解决数据库应用侧和运维侧两方面的问题,是一款基于 数据库 协议分析与控制技术的数据库安全防护系统。DBFirewall基于主动防御机制,实现数据库的访问行为控制、危险…...
一起做网站17怎么下单/企业网站模板图片
小升初奥数综合训练(十八十九)余数和同余【知识要点】1、例如:375=7……2,四者之间的数量关系:被除数除数商余数2、同余的概念:两个整数,被同一个大于1的整数m除,所得余数如果相同,那…...
网站搭建设计 是什么/今日热搜排行第一名
List<Map>是什么意思? List集合中的对象是一个Map对象,而这个Map对象的键是String类型,值是Object类型 List以Map接口对象为列表对象。 Map以String为键,以Object为值。 List里只能放Map类型的对象,而这个Map类型的对象又只能放以St…...