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++

学生实现的效果

视频资源加载失败

视频资源加载失败

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

外观模式:简化复杂子系统的访问与使用

文章目录 1. 简介2. 外观模式的基本结构3. 外观模式的实现步骤4. 外观模式的应用与实例4.1 图形界面库的外观模式应用4.2 文件压缩与解压缩的外观模式应用4.3 订单处理系统的外观模式应用 5. 外观模式的优缺点5.1 优点5.2 缺点 6. 总结 1. 简介 外观模式是一种结构型设计模式&…

基于java+springboot+vue的点餐平台网站-lw-源码

​ 系统介绍&#xff1a; 随着现在网络的快速发展&#xff0c;网上管理系统也逐渐快速发展起来&#xff0c;网上管理模式很快融入到了许多商家的之中&#xff0c;随之就产生了“点餐平台网站”&#xff0c;这样就让点餐平台网站更加方便简单。 对于本点餐平台网站的设计来说…

实操教程 | 触发器实现 Apache DolphinScheduler 失败钉钉自动告警

作者 | sqlboy-yuzhenc 背景介绍 在实际应用中&#xff0c;我们经常需要将特定的任务通知给特定的人&#xff0c;虽然 Apache DolphinScheduler 在安全中心提供了告警组和告警实例&#xff0c;但是配置起来相对复杂&#xff0c;并且还需要在定时调度时指定告警组。通过这篇文…

BIO到NIO、多路复用器, 从理论到实践, 结合实际案例对比各自效率与特点(上)

文章目录 文章引入IO模型及概念梳理BIO简单介绍代码样例压测结果 NIO(单线程模型)简单介绍与BIO的比较代码样例压测结果 多路复用器问题引入 文章引入 如果你对BIO、NIO、多路复用器有些许疑惑, 那么这篇文章就是肯定需要看的, 本文将主要从概念, 代码实现、发展历程的角度去突…

JavaScript设计模式(二)——简单工厂模式、抽象工厂模式、建造者模式

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;正逐渐往全干发展 &#x1f4c3;个人状态&#xff1a; 研发工程师&#xff0c;现效力于中国工业软件事业 &#x1f680;人生格言&#xff1a; 积跬步…

使用element-ui中的el-table回显已选中数据时toggleRowSelection报错

最近在写一个后台&#xff0c;需要在表格中多选&#xff0c;然后点击编辑按钮的时候&#xff0c;需要回显已经选中的表单项 <el-table v-loading"loading" :data"discountList" :row-key"(row) > row.id" refmultipleTable selection-cha…

[ES]二基础 |

一、索引库操作 1、mapping属性 mapping是对索引库中文档的约束&#xff0c;常见的mapping属性包括&#xff1a; 1)type&#xff1a;字段数据类型&#xff0c;常见的简单类型有&#xff1a; ①字符串&#xff1a;text(可分词的文本)、keyword&#xff08;精确值&#xff0c…

基于JavaWeb和mysql实现校园订餐前后台管理系统(源码+数据库)

一、项目简介 本项目是一套基于JavaWeb和mysql实现网上书城前后端管理系统&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。 包含&#xff1a;项目源码、项目文档、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都…

【Terraform学习】Terraform模块基础操作(Terraform模块)

本站以分享各种运维经验和运维所需要的技能为主 《python》&#xff1a;python零基础入门学习 《shell》&#xff1a;shell学习 《terraform》持续更新中&#xff1a;terraform_Aws学习零基础入门到最佳实战 《k8》暂未更新 《docker学习》暂未更新 《ceph学习》ceph日常问题解…

SpringBoot中自定义starter

SpringBoot自动装配原理&#xff1a; EnableAutoConfiguration注解开启自动装配功能&#xff0c;该注解通常放在应用的主类上。spring.factories文件位于META-INF目录下的配置文件中定义各个自动装配类的全限定名 当SpringBoot启动时&#xff0c;会加载classpath下所有的spri…

说说Flink运行模式

分析&回答 1.开发者模式 在idea中运行Flink程序的方式就是开发模式。 2.local-cluster模式 Flink中的Local-cluster(本地集群)模式,单节点运行&#xff0c;主要用于测试, 学习。 3.Standalone模式 独立集群模式&#xff0c;由Flink自身提供计算资源。 4.Yarn模式 把Fl…

android frida 逆向 自吐加密算法

前言&#xff1a; ♛ frida hook android Android 逆向神器 前几天在学习 Android 逆向的时候发现了一个神器&#xff1a;通过 frida hook 我们可以 “劫持” 一些函数 为我们所用&#xff0c; 今天就和大家上手一个 加密函数的劫持 让打印出&#xff1a; 加密秘钥 …

Window11-Ubuntu双系统安装

一、制作Ubuntu系统盘 1.下载Ubuntu镜像源 阿里云开源镜像站&#xff1a;https://mirrors.aliyun.com/ubuntu-releases/ 清华大学开源软件镜像网站&#xff1a;https://mirrors.tuna.tsinghua.edu.cn/ubuntu-releases/ 选择想要的版本下载&#xff0c;我用的是20.04版本。 2…

【广州华锐互动】AR昆虫认知学习系统实现对昆虫形态的捕捉和还原

随着科技的不断发展&#xff0c;人们对自然界的认识也在不断加深。在这个过程中&#xff0c;AR&#xff08;增强现实&#xff09;技术的出现为人们带来了全新的体验方式。为此&#xff0c;广州华锐互动开发了AR昆虫认知学习系统&#xff0c;本文将为大家详细介绍这款系统的特点…

无涯教程-Android - Style Demo Example函数

下面的示例演示如何将样式用于单个元素。让我们开始按照以下步骤创建一个简单的Android应用程序- 步骤说明 1 您将使用Android Studio IDE创建一个Android应用程序,并在 com.example.saira_000.myapplication 包下将其命名为 myapplication ,如中所述您好世界Example一章。 2 …

【方案】基于视频与AI智能分析技术的城市轨道交通视频监控建设方案

一、背景分析 地铁作为重要的公共场所交通枢纽&#xff0c;流动性非常高、人员大量聚集&#xff0c;轨道交通需要利用视频监控系统来实现全程、全方位的安全防范&#xff0c;这也是保证地铁行车组织和安全的重要手段。调度员和车站值班员通过系统监管列车运行、客流情况、变电…

vue小测试之拖拽、自定义事件

在开始之前我去复习了一下&#xff0c;clientX、clientY、pageX、pageY的区别&#xff0c;对于不熟悉offsetLeft和offsetTop的也可以在这里去复习一下。 vue拖拽指令之offsetX、clientX、pageX、screenX_wade3po的博客-CSDN博客_vue offset 客户区坐标位置&#xff08;clientX&…

讲讲几道关于 TCP/UDP 通信的面试题

TCP &#xff08;1&#xff09;TCP 的 accept 发生在三次握手的哪个阶段&#xff1f; 如下图connect和accept的关系&#xff1a; accept过程发生在三次握手之后&#xff0c;三次握手完成后&#xff0c;客户端和服务器就建立了tcp连接并可以进行数据交互了。这时可以调用accep…

像linux 一样清理Windows C盘

像 linux 有命令 du -sh 查看文件夹大小 但是windows 可就没有这个命令了&#xff0c;就算有命令&#xff0c;也不能扫描子目录里面的文件 但是windows 可以借助 软件来清理&#xff0c;和linux 一样 文件上面是目录&#xff0c;下面是文件所占用空间大小的图&#xff0c;咋…

通过参数化可变形曲线直接从 X 射线投影数据计算分割研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…