C++实现简单贪吃蛇游戏

文章目录

    • 1 开发历程
    • 2 开发思路
    • 3 使用介绍
    • 4 源文件代码
    • 5 游戏截图
    • 6 小结

1 开发历程

游戏使用C++语言开发,是博主某个下午心血来潮的结果,后面又花了点时间加了计分,记录历史得分的功能。

2 开发思路

其实贪吃蛇主要难在蛇身的移动上,想像着蛇移动的模样,不禁让人想起链表这种数据结构,蛇的头带动蛇身的第二节,第二节带动第三节,每一节的移动方向会遗传给下一节,把握住这一点,难点就迎刃而解了。

3 使用介绍

由于整个项目只有一个文件,使用g++ -o snake main.cpp命令编译源文件,就可以得到一个名为snakeexe可运行程序,接着在exe同目录下打开cmd使用下面两个命令来执行程序:

  • snake start,开始游戏,w、s、a、d四个按键(不分大小写)控制蛇的移动方向,若蛇碰到墙壁或者自身,则游戏结束,并将计分存入名为rank.txt的文件中。
  • snake rank,查看历史前五得分记录。

4 源文件代码

#include <iostream>
#include <cstring>
#include <fstream>
#include <set>
#include <windows.h>
#include <conio.h>
#include <time.h>
#define HEIGHT 15
#define WIDTH 35
#define INIT_FLUSHRATE 200
#define INIT_SCORE 0
#define BODY '@'
#define EMPTY ' '
#define FOOD '*'
#define EDGE '#'
#define RANKFILE "rank.txt"
using namespace std;
bool keyIsput = false;enum class Orient {UP, DOWN, LEFT, RIGHT};typedef struct node {int row;int col;Orient direction;struct node* next;
} Node;typedef struct {int frow;int fcol;
} Food;bool FoodInSnake(const int& r, const int& c, Node* q) {while (q != NULL) {if (q->row == r && q->col == c)return true;q = q->next;}return false;
}void printRank(){ifstream fin(RANKFILE);if(!fin){cerr << RANKFILE << " does not exit or open file error!!";exit(1);}if(fin.peek()==ifstream::traits_type::eof()){cout << "file is empty";exit(1);}for(int i=0; i<5; ++i){int tmp;if(fin.eof())break;fin >> tmp;cout << "No." << i+1 << ": " << tmp << '\n';}
}class Snake {
private:Node* snakeHead;public:static Orient tmp_1, tmp_2;Snake(int r, int c, Orient ori) {snakeHead = new Node;snakeHead->row = r;snakeHead->col = c;snakeHead->direction = ori;snakeHead->next = NULL;}Node* getHead() {return snakeHead;}void setOrient(Orient ori) {tmp_1 = snakeHead->direction;snakeHead->direction = ori;}void move() {Node* p = snakeHead;while (p != NULL) {if (p == snakeHead) {if(keyIsput==false)tmp_1 = p->direction;}else if (p != snakeHead) {tmp_2 = p->direction;p->direction = tmp_1;tmp_1 = tmp_2;}switch (p->direction) {case Orient::UP:(p->row)--; break;case Orient::DOWN:(p->row)++; break;case Orient::LEFT:(p->col)--; break;case Orient::RIGHT:(p->col)++; break;default:break;}p = p->next;}keyIsput = false;}void longer(int row, int col, Orient direction) {Node* newbody = new Node;newbody->row = row;newbody->col = col;newbody->direction = direction;newbody->next = snakeHead;snakeHead = newbody;}virtual ~Snake() {Node *p = snakeHead, *q=NULL;while (p != NULL) {q = p->next;delete p;p = q;}}
};class Board {
private:Snake* s;int playground[HEIGHT][WIDTH] = {0};Food* food;bool foodIsEaten;bool gameOver;int score;int flushRate;public:Board(int sr=HEIGHT/2, int sc=WIDTH/2, Orient sori=Orient::RIGHT):gameOver(false),foodIsEaten(false),score(INIT_SCORE),flushRate(INIT_FLUSHRATE){s = new Snake(sr, sc, sori);playground[sr][sc] = 1;food = new Food;while ((food->frow = rand() % HEIGHT) == sr);while ((food->fcol = rand() % WIDTH) == sc);playground[food->frow][food->fcol] = 2;}void refresh() {s->move();Node* shead = s->getHead();if((gameOver = isCollision(shead)))return;if (shead->row == food->frow && shead->col == food->fcol) {foodIsEaten = true;switch (shead->direction){case Orient::UP: s->longer(shead->row - 1, shead->col, shead->direction); break;case Orient::DOWN: s->longer(shead->row + 1, shead->col, shead->direction); break;case Orient::LEFT: s->longer(shead->row, shead->col - 1, shead->direction); break;case Orient::RIGHT: s->longer(shead->row, shead->col + 1, shead->direction); break;default:break;}}if (foodIsEaten)refreshFood();memset(playground, 0, sizeof(playground));Node* p = s->getHead();while (p != NULL) {playground[p->row][p->col] = 1;p = p->next;}if(!foodIsEaten)playground[food->frow][food->fcol] = 2;}void printBoard() {for (int i = 0; i < HEIGHT; ++i) {for (int j = 0; j < WIDTH; ++j)playground[i][j] == 1 ? cout << BODY : (playground[i][j]==2? cout << FOOD:cout << EMPTY);i==0?cout << EDGE << "  Your score: " << score << '\n':cout << EDGE << '\n';}for (int k = 0; k < WIDTH; ++k)cout << EDGE;}void setSnakeOrient(Orient ori) {s->setOrient(ori);}void refreshFood() {score++;if(flushRate>50)flushRate-=5;Node* p = s->getHead();while (FoodInSnake(food->frow = rand() % HEIGHT, food->fcol = rand() % WIDTH, p));foodIsEaten = false;}void keyCheck() {if (_kbhit()) {keyIsput = true;char key = _getch();switch (key){case 'w':case'W':setSnakeOrient(Orient::UP); break;case 'a':case'A':setSnakeOrient(Orient::LEFT); break;case 's':case'S':setSnakeOrient(Orient::DOWN); break;case 'd':case'D':setSnakeOrient(Orient::RIGHT); break;default:break;}}}bool isCollision(Node*& head){if(head->row<0 || head->row>=HEIGHT)return true;if(head->col<0 || head->col>=WIDTH)return true;Node* p = head;while(p!=NULL){if(p!=head && p->row==head->row && p->col==head->col)return true;p = p->next;}return false;}int getFlushRate() const{return flushRate;}bool isGameOver(){return gameOver;}void printEnd(){ifstream fin(RANKFILE);if(!fin){fin.close();ofstream fout(RANKFILE);fout << score;fout.close();}else{set<int> r;int tmp;r.insert(score);while(!fin.eof()){fin >> tmp;r.insert(tmp);}fin.close();ofstream fout(RANKFILE);for(auto i=r.rbegin();i!=r.rend();++i)++i==r.rend()?fout << *(--i):fout << *(--i) << '\n';fout.close();}cout << "Game Over!!\n";cout << "Your score is " << score << ".\n";}~Board() {delete s;delete food;}
};Orient Snake::tmp_1 = Orient::RIGHT, Snake::tmp_2 = Orient::RIGHT;int main(int argc, char* argv[]) {if(argc!=2 || (strcmp(argv[1], "start")!=0 && strcmp(argv[1], "rank")!=0)){cerr << "Usage: \"snake start\" to begin game.\n";cerr << "       \"snake rank\" to look rank(1-5).";return 1;}if(strcmp(argv[1], "rank")==0){printRank();return 0;}srand((unsigned)time(NULL));Board* gameboard = new Board();while (!gameboard->isGameOver()) {gameboard->printBoard();Sleep(gameboard->getFlushRate());system("cls");gameboard->keyCheck();gameboard->refresh();}gameboard->printEnd();delete gameboard;return 0;
}

5 游戏截图

在这里插入图片描述

在这里插入图片描述

6 小结

程序中使用了windows的库,所以暂时只支持win系统运行,这个游戏可以说是人人皆知,博主小时候特别喜欢这个游戏,现在动手实现了,感觉还是很不错的。再次感谢各位的阅读,希望可以帮到各位,喜欢的可以点赞支持一波,Thank you very much!!

后话:想学习C语言的,可以看看博主的C现代方法笔记的文章哦!

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

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

相关文章

(C#源码)LIMS实验室信息系统,管理实验室的样本、数据、实验和设备等信息

LIMS系统&#xff0c;LIMS实验室信息系统源码&#xff0c;C# LIMS系统源码&#xff0c; 什么是LIMS&#xff1f; LIMS即实验室信息管理系统&#xff08;Laboratory Information Management System&#xff09;&#xff0c;是一种专门为实验室设计的信息管理系统&#xff0c;用…

小程序基础学习(组件化)

&#xff08;一&#xff09;创建 找到components文件夹下面创建新的文件夹 然后再文件夹内创建component格式的文件 创建后这样 我创建的是my-info的文件夹以及my-info的components文件&#xff0c;跟着普通的页面一样 &#xff08;二&#xff09; 注册组件 找到你需要使用组…

leetcode:滑动窗口

目录 1.定长滑动窗口 1.1 几乎唯一子数组的最大和(使用map来计数) 1.2 长度为k子数组中的最大和 2.不定长滑动窗口 2.1 最多k个重复元素的最长子数组 2.2 绝对差不超过限制的最长连续子数组(multiset&#xff09; 2.3 将x减到0的最小操作数(正难则反 逆向思维) 2.4 统计…

Developer Tools for Game Creator 1

插件包含: 持久世界时间管理系统 单击以生成对象或预设 游戏内调试控制台 游戏内事件控制台 控制台管理控制 命令模板脚本 游戏内屏幕截图 低分辨率和高分辨率图像 缩略图生成 移动支持 使用Game Creator Action或拖放来激活和控制组件,无需编码。 通过此资产,您可以获得: …

Android 15即将到来,或将推出5大新功能特性

Android15 OneUI电池优化 三星最近完成了对其所有设备的稳定版 One UI 6.0 更新的推出&#xff0c;引起了用户的极大兴奋。据新出现的互联网统计数据显示&#xff0c;即将发布的基于 Android 15 的 One UI 7 将通过优化电池和功耗来重新定义用户体验&#xff0c;这是一项具有突…

React之自定义路由组件

开篇 react router功能很强大&#xff0c;可以根据路径配置对应容器组件。做到组件的局部刷新&#xff0c;接下来我会基于react实现一个简单的路由组件。 代码 自定义路由组件 import {useEffect, useState} from "react"; import React from react // 路由配置 e…

【C++】C++11中的常见语法(上)

C11 一、C11简介二、统一的列表初始化1.&#xff5b;&#xff5d;初始化2. std::initializer_list 三、声明1. auto2. decltype3. nullptr 四、右值引用和移动语义1. 左值引用和右值引用2. 左值引用与右值引用比较3. 右值引用使用场景和意义4. 右值引用引用左值及其一些更深入的…

Python知识点(史上最全)

Python期末考试知识点&#xff08;史上最全&#xff09; python简介 Python是一种解释型语言 Python使用缩进对齐组织代码执行&#xff0c;所以没有缩进的代码&#xff0c;都会在载入时自动执行 数据类型&#xff1a;整形 int 无限大 浮点型 float…

概率论与数理统计-第6章 参数估计

6.1 点估计问题概述 一、点估计的概念 二、评价估计量的标准 无偏性 定义1&#xff1a;设^ θ(X1,…,Xn)是未知参数θ的估计量&#xff0c;若E(^ θ)θ,则称^θ为θ的无偏估计量定理1&#xff1a;设X1,…,Xn,为取自总体X的样本&#xff0c;总体X的均值为μ&#xff0c;方差为…

快速打通 Vue 3(四):标签的 ref 属性与 Vue3 生命周期

很激动进入了 Vue 3 的学习&#xff0c;作为一个已经上线了三年多的框架&#xff0c;很多项目都开始使用 Vue 3 来编写了 这一组文章主要聚焦于 Vue 3 的新技术和新特性 如果想要学习基础的 Vue 语法可以看我专栏中的其他博客 Vue&#xff08;一&#xff09;&#xff1a;Vue 入…

centos 8.0 安装sysbench 1.0.17

序号步骤说明执行命令执行结果备注1 下载并解压sysbench-1.0.17.zip sysbench-1.0.17.zip2安装依赖文件 yum install automake libtool -y yum install /usr/include/libpq-fe.h 3安装sysbench cd sysbench-1.0.17 ./autogen.sh ./configure \ --prefix/sysbench \ --with-pgsq…

【Docker】Linux中Docker技术入门与实战及实用的常规命令

目录 一、引言 1. 说明&#xff1a; 2. Linux介绍 3. Docker简介 二、Docker三要素 1. 镜像&#xff08;Image&#xff09; 2. 容器&#xff08;Container&#xff09; 3. 仓库&#xff08;Repository&#xff09; 三、实现案例 1. 创建 2. 设置镜像 3. 开启设置 …

MidTool的AIGC与NFT的结合-艺术创作和版权保护的革新

在数字艺术和区块链技术的交汇点上&#xff0c;NFT&#xff08;非同质化代币&#xff09;正以其独特的方式重塑艺术品的收藏与交易。将MidTool&#xff08;https://www.aimidtool.com/&#xff09;的AIGC&#xff08;人工智能生成内容&#xff09;创作的图片转为NFT&#xff0c…

Windows启动MongoDB服务报错(错误 1053:服务没有及时响应启动或控制请求)

问题描述&#xff1a;修改MongoDB服务bin目录下的mongod.cfg&#xff0c;然后在任务管理器找到MongoDB服务-->右键-->点击【开始】&#xff0c;启动失败无提示&#xff1a; 右键点击任务管理器的MongoDB服务-->点击【打开服务】&#xff0c;跳转到服务页面-->找到M…

云服务器租用价格表,阿里云腾讯云华为云2024年优惠对比

作为多年站长使市面上大多数的云厂商的云服务器都使用过&#xff0c;很多特价云服务器都是新用户专享的&#xff0c;本文有老用户特价云服务器&#xff0c;阿腾云atengyun.com有多个网站、小程序等&#xff0c;国内头部云厂商阿里云、腾讯云、华为云、UCloud、京东云都有用过&a…

2024--Django平台开发-基础信息(一)

一、前置知识点 - Python环境搭建 (Python解释器、Pycharm、环境变量等) - 基础语法(条件、循环、输入输出、编码等) - 数据类型(整型、布尔型、字符串、列表、字典、元组、集合等) - 函数(文件操作、返回值、参数、作用域等) - 面向对象 (类、对象、封装、继承、多态等)包和模…

java基础之异常练习题

异常 1.Java 中所有的错误/异常都继承自 Throwable类&#xff1b;在该类的子类中&#xff0c; Error 类表示严重的底层错误&#xff0c; 对于这类错误一般处理的方式是 直接报告并终止程序 &#xff1b; Exception 类表示异常。 2.查阅API&#xff0c;完成以下填空&#xff1a;…

大数据-hive函数与mysql函数的辨析及练习-将多行聚合成一行

目录 1. &#x1f959;collect_list: 聚合-不去重 2. &#x1f959;collect_set(col): 聚合-去重 3. &#x1f959;mysql的聚合函数-group_concat 4. leetcode练习题 1. &#x1f959;collect_list: 聚合-不去重 将组内的元素收集成数组 不会去重 2. &#x1f959;collec…

unity中0GC优化方案《zstring》

文章目录 序言简介GC带来的问题性能瓶颈玩家体验受损 使用方式 序言 游戏开发秉承遇到好东西要分享&#xff0c;下面介绍zstring&#xff0c;感谢作者开源无私奉献 源码地址&#xff1a;https://github.com/871041532/zstring 简介 GC带来的问题 性能瓶颈 GC暂停主线程执行…

C++内存小练习

使用数据文件中的一组地震检波器测量值确定可能的地震事件的位置 程序的输入是名为map.txt的数据文件和用于计算短时间能量和长时间能量的 取样值的数目。输出是给出关于潜在的地震事件次数的报告 #include <iostream> #include <fstream>using namespace std;//定…