c++贪吃蛇源代码 完整版

文章目录

  • c++ 实现贪吃蛇, 完整源码
    • 0.非常重要的注意事项
    • 1.数据结构分析:
    • 2.程序运行分析
    • 3.难点分析
      • 1.蛇移动怎么显示?
      • 2.怎么控制吃到食物后蛇的速度的变化?
      • 3.怎么解决屏幕闪烁?
    • 4.一些废话
    • 5.源代码
    • 6.运行效果展示
    • 7.总结

c++ 实现贪吃蛇, 完整源码

0.非常重要的注意事项

请注意:
1.这是c++代码,请建立.cpp文件而不是.c文件,然后将代码拷贝进去,再使用c++编译器进行编译运行。

2.因为使用了一些c++11标准当中的语法,所以c++编译器的编译标准至少需要设置到c++11以上,不然会报错。编译标准可以在你的IDE里设置,或者使用命令行编译时附加-std=c++11选项。

3.代码中使用了getch()函数,用于无回显的接收用户输入;使用了kbhit()函数用于判断用户是否按下键盘。但是如果你在visual studio中直接运行本代码可能会报错,你可以将上述两个函数替换为_getch()函数和_kbhit()函数就可以了。

1.数据结构分析:

这里我采用双向队列的数据结构存储蛇身节点,目的是:方便,减少屏闪。并且双向队列也能更好的体现贪吃蛇本身的特点。有利于实现,且效率也较高。

2.程序运行分析

程序开始用户随机按下w,a,s,d中任意按键开始游戏并且作为蛇运动的初始方向(如果刚开始觉得蛇的运动速度太慢可以键入’v’使变为当前运行素的1.25倍速,键入’b’则会使之变为当前速度的2/3倍速),然后进入循环持续游戏直到游戏结束,显示分数之后用户输入任意按键退出游戏。

3.难点分析

1.蛇移动怎么显示?

这也就是我采用双向队列的原因,蛇每运动一步,就从双向队列中弹出队尾,然后将新的队首(即蛇头)压入队列首部,然后再清除蛇尾打印蛇身即可,不需要对贪吃蛇全部进行清楚以及打印,可以极大的减少程序运行过程中出现的闪烁现象。如果吃到食物那么本次运动就会在将蛇尾变为蛇头的同时再加入一个蛇身达到使蛇身长度加一的目的(我认为双向队列更能从本质上体现贪吃蛇本来的特点,而每次弹出队尾,加入队首而不对中间的蛇身进行改变也使程序变得更加简洁,运行更流畅)

2.怎么控制吃到食物后蛇的速度的变化?

最开始我设置初始速度为1000(即:Sleep()函数的参数为1000)每次吃到食物就将速度乘以0.8以此达到加速的目的。但我发现到后面速度越来越快没有上限,根本无法控制。
解法:设置一个上限为MaxSpeed,则速度为 MaxSpeed + Index,MaxSpeed 保持不变且较小作为蛇速度的渐进上限,每次乘以0.8(可自定义)则乘到Index上面,这样的话速度就不会无限制的上升。

3.怎么解决屏幕闪烁?

解:不要使用system(“cls”);清屏函数,使用函数SetConsoleCursorPosition控制光标填充空格进行覆盖能大大减少屏闪问题!!这一点要注意了!

4.一些废话

1.首先肯定是存储蛇身的数据结构方面,有很多种选择:链表,双向队列,循环队列,vector甚至数组都可以用来存储蛇身。
2.最开始以为这个比较简单…上手就开始写写废了一次,提醒大家在写程序(特别是这种结构比较复杂且步骤较多的程序)时一定要先进行规划,想清楚要使用的数据结构以及构建方式,想清楚再写,避免浪费时间。

5.源代码

下面是源代码,还需要什么功能大家可以在此基础上进行改动。

#include<iostream>
#include<windows.h>
#include<conio.h>
#include<deque>
#include<ctime>
#include<stdexcept>
using namespace std;struct Snake { //蛇类结构体char image;short x, y; //坐标
};class snakeGame {public:snakeGame();void printMap();// 控制光标移动void gotoxy(short x, short y) {hOut = GetStdHandle(STD_OUTPUT_HANDLE); //获取句柄pos = {x, y};SetConsoleCursorPosition(hOut, pos); //移动光标}//隐藏光标void HideCursor(){HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);CONSOLE_CURSOR_INFO CursorInfo;GetConsoleCursorInfo(handle, &CursorInfo);//获取控制台光标信息CursorInfo.bVisible = false; //隐藏控制台光标SetConsoleCursorInfo(handle, &CursorInfo);//设置控制台光标状态}// 初始化蛇身,可根据需要更改初始长度void initSnake() {snake.push_front({'@', width / 2, height / 2});for (int i=0; i<2;++i)snake.push_back({'+', width/2,static_cast<short>(height/2+i+1)});}// 判断是否食物产生位置与蛇身冲突int WrongLocation() {for (Snake body : snake)if(body.x == food_x && body.y == food_y) return 0;return 1;}// 产生食物,并打印void createFood() {do {food_x = rand() % (width - 4) + 2;food_y = rand() % (height - 2) + 1;} while (!WrongLocation());//处理冲突gotoxy(food_x,food_y); cout << '*' << endl; //打印食物}void printSnake();// 清除蛇尾inline void clearSnake(Snake &tail) {gotoxy(tail.x, tail.y); cout << ' '; //覆盖蛇尾,不使用清屏函数,避免了闪烁}void judgeCrash();void foodEaten();// 监控用户键盘输入void userInput() {char ch;switch(ch=getch()) {case 'w':if (dir != 's') dir = ch;break;case 'a':if (dir != 'd') dir = ch;break;case 's':if (dir != 'w') dir = ch;break;case 'd':if (dir != 'a') dir = ch;break;case 'v':speed*=0.8;break; case 'b':speed*=1.5;break;case ' ':gotoxy(width / 2, height); cout << "游戏已暂停,任意键继续"; getch();gotoxy(width / 2, height); cout << "                     "; break;default:break;}}private:// 以下是程序运行当中需要用到的一些中间变量或者是数据变量。enum MapSize {height = 40,width = 120}; //地图尺寸HANDLE hOut; COORD pos;char dir; //directionbool beg,eatFood=false;double speed=200;deque<Snake> snake;int food_x,food_y;int score=0;
};
// 处理吃到食物的情况
void snakeGame::foodEaten() {createFood();eatFood=true;speed*=.8;++score;
}
// 判断蛇是否撞墙或者吃到自己的尾巴
void snakeGame::judgeCrash() {int flag=0;if (snake.size()>=5) {deque<Snake>::iterator iter = snake.begin() + 1;int x = (iter-1)->x, y = (iter-1)->y;for (; iter != snake.end(); ++iter) {if (iter->x == x && iter->y == y) flag=1;}}if (flag || snake.front().x == 1 || snake.front().x == width - 2 || snake.front().y == 0 || snake.front().y == height - 1)//检测是否撞墙或者是否吃到自身{gotoxy(width / 2 - 10, height /2);cout << "游戏结束!您的分数是: " << score << "分(回车继续)"<<endl;while(1) {dir = getch();if (dir == '\r') break;}runtime_error quit("游戏结束,正常退出"); throw quit;}
}
// 将蛇身打印出来
void snakeGame::printSnake() {deque<Snake>::const_iterator iter = snake.begin();for (; iter <= snake.begin() + 1 && iter < snake.end(); ++iter) {gotoxy(iter->x, iter->y); cout << iter->image;}
}
// 打印出边框
void snakeGame::printMap() {int i;for (i = 0; i != width; i += 2) cout << "■"; //这个图案宽度占2,高度占1gotoxy(0, 1);for (i = 1; i != height; ++i) cout << "■" << endl;for (i = 1; i != height; ++i) {gotoxy(width - 2, i); cout << "■";}gotoxy(0, height - 1);for (i = 0; i != width; i += 2) cout << "■";cout << "贪吃蛇:1.方向键开始游戏 2.*代表食物 3.空格键暂停游戏\n        4.键入'v'加速    5.键入'b'减速";
}
// 类的构造函数。
// 包含了程序的初始化(地图绘制,蛇身初始化),程序运行,程序结束等内容
// 是程序最关键的部分
snakeGame::snakeGame() {HideCursor(); // 隐藏光标srand(static_cast<unsigned int>(time(NULL)));beg=true;Snake tmp1,tmp2;while (1) {if(beg) { // 判断是不是第一次运行程序,因为第一次运行需要打印边框printMap();dir = getch();initSnake();createFood();beg = eatFood=false;}tmp2=snake.back();tmp1=snake.front();snake.pop_back();if (eatFood) { // 如果吃到食物...tmp2.image='+';snake.push_back(tmp2);eatFood=false;}else clearSnake(tmp2);// 判断当前的前进方向,根据dir来进行移动if      (dir == 's') ++tmp1.y;else if (dir == 'a') --tmp1.x;else if (dir == 'd') ++tmp1.x;else 				 --tmp1.y;try{judgeCrash(); // 判断是否撞墙或者吃到自己}catch(runtime_error &quitSignal) {throw quitSignal;}snake.front().image='+';snake.push_front(tmp1);printSnake();Sleep(speed+30);if (tmp1.x == food_x && tmp1.y == food_y) foodEaten();// 监测用户的键入if(kbhit()) userInput();}
}
int main() {// 设置小黑框的一些参数system("mode con cols=120 lines=42");try{snakeGame game;}catch(runtime_error &gameEnd) {system("cls");cout<<gameEnd.what();getch();}
}

6.运行效果展示

将边界改成方块后的运行截图

7.总结

网上真正能用的贪吃蛇源代码还是很少的,就算找到了不是要收费下载就是复制过来一大堆报错或者bug运行不了,所以本着帮助他人的想法自己写了一个版本的。写得不是很好,有不足之处欢迎大家批评指正。
有任何问题可以留在评论区,力所能及可以给予帮助。
peace~

如果代码有报错可以去看看开头的重要注意事项喔~

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

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

相关文章

Python贪吃蛇游戏详细代码和注释

在写Python游戏项目时&#xff0c;最重要的时python中的pygame库。安装pygame库和用法在我CSDN博客另一篇文章上。这里就不详细说了。下边时运行游戏界面。 下边是详细的代码和注释 import pygame,sys,random,time from pygame.locals import * #从pygame模块导入常用的函数…

贪吃蛇Python版 源码+代码分析

跳转目录 前言运行示例程序分析捕获键盘操作输出游戏画面 代码分析一安装运行环境游戏地图的实现炸弹的实现食物的实现蛇的实现 初步测试键盘控制的实现主程序game函数图形界面显示分数, 得分结束函数游戏主函数 源码下载 前言 该程序未使用pygame库, 而是采用keyboard库的on_p…

1.02亿美元从数字资产基金撤出!BTC价格已经触底!预示下跌趋势即将逆转?

根据CoinShares的一份报告&#xff0c;上周全球数字资产基金流出总额为1.02亿美元&#xff0c;美国数字资金外流共计9800万美元&#xff0c;而欧洲仅为200万美元&#xff0c;这表明美国市场的不稳定程度越来越高。 事实上&#xff0c;数字资产基金是一种投资工具&#xff0c;旨…

c语言 搜索彩票期数,根据福利彩票的规则用c++编写一个买彩票开奖的程序,求程序代码,谢谢...

满意答案 haslis3ila 2016.03.13 采纳率&#xff1a;58% 等级&#xff1a;7 已帮助&#xff1a;611人 1、完整代码如下&#xff0c;已经过VS2012编译及实际测试 2、基本上不存在什么缺憾&#xff0c;唯一的缺憾是很难中奖。#include #include #include #include using names…

电影解说怎么操作?电影解说都用什么配音软件?

我们都知道&#xff0c;短视频现在非常火爆&#xff0c;我们平时刷视频&#xff0c;可以看到很多的电影解说&#xff0c;不仅语言生动&#xff0c;而且配音很逼真&#xff0c;很多人以为电影解说的配音都是自己配音的&#xff0c;其实不然。以目前的市场现状来说&#xff0c;绝…

使用 ChatGPT 生成数据,4 个示例

如今&#xff0c;国家列表和货币列表等标准数据源很容易在互联网上获得。然而&#xff0c;丰富或重新格式化这些数据通常非常耗时。在本文中&#xff0c;我们探讨如何使用 ChatGPT 有效地生成和增强数据。我们将提供示例来演示 ChatGPT 的功能。 示例 1 — 获取 CSV 格式的世界…

java实现双色球生成器

题目要求&#xff1a; 思路&#xff1a; 生成红球&#xff1a; 使用random对象随机生成1-33的数字&#xff0c;使用长度为6的数组接收&#xff0c;比较生成树在数组里是否有重复如果重复就&#xff0c;本次随机数作废&#xff0c;重新生成不重复就放入数组使用Arrays.sort&am…

python彩票号码生成器

突然想到好久没动代码了&#xff0c;手痒痒&#xff0c;但是又不知道弄啥。想了想平时自己闲来无事都会买彩票&#xff0c;路过买两块&#xff0c;中不中全看天意。 但是经常买彩票的时候不知道选什么号码&#xff0c;犹豫的几分钟时间就浪费了&#xff0c;所以写了个彩票号码…

什么是CMP(同意管理平台)与Cookies?

有时访问网站时&#xff0c;会弹出弹窗或下面弹出横条&#xff0c; 这就是CMP。 什么是个人数据&#xff1f; 个人数据或个人信息是可用于识别活着的个人的信息。不同的数据保护法&#xff0c;如GDPR和CCPA&#xff0c;对个人数据的定义不同&#xff0c;但大体上它们都同意这样…

信息学奥赛C++语言:可口可乐

【题目描述】 便利店给出以下的优惠&#xff1a;“每3个空瓶可以换1瓶可口可乐。” 现在&#xff0c;您准备从便利店买一些可口可乐&#xff08;N瓶&#xff09;&#xff0c;您想知道您最多可以从便利店拿到多少瓶可口可乐。下图给出N8的情况。方法是&#xff1a;喝完8瓶可乐之…

喝汽水问题(使用c语言解决)

目录 问题描述 解题方法一 解题思路&#xff1a; 代码实现 解题方法二 解题思路&#xff1a; 代码实现 解题方法三 解题思路: 代码实现 总结 问题描述 喝汽水&#xff0c;1瓶汽水1元&#xff0c;2个空瓶可以换一瓶汽水&#xff0c;给20元&#xff0c;可以喝多少汽水&…

ESP8266接入小爱同学—智能LED台灯或风扇(利用继电器)

ESP8266接入小爱同学—智能LED台灯或风扇 上周用esp8266做了一个语音智能台灯&#xff0c;也参考了很多网上的教程&#xff0c;也不难&#xff0c;挺简单的&#xff0c;在这里分享一下。 首先我用的是arduino IDE对esp8266进行的编译&#xff0c;arduino对8266编译环境的具体…

【Homeassistant 的Node-red插件之小爱同学语音功能开通】

欢迎大家阅读2345VOR的博客【Homeassistant 的Node-red插件之小爱同学语音功能开通】,本页是Homeassistant 的Node-red插件之小爱同学语音功能开通,实现播报任意带变量的文本🥳🥳🥳2345VOR鹏鹏主页: 已获得CSDN《嵌入式领域优质创作者》称号🎉🎉、阿里云《arduino…

esp8266接入米家、小爱同学,附开源app控制

超简单&#xff0c;两步完事 第一步 下载程序到esp8266第二步 绑定到米家第三步 &#xff08;附&#xff09;开源app控制 第一步 下载程序到esp8266 下载地址: 点击下载 本demo 是利用arduino IDE开发&#xff0c;关于arduino IDE 的ESP8266环境配置可参考&#xff1a;环境配…

【IoT物联网全栈之路 ②】如何快速体验,微信公众号配网,天猫精灵和小爱同学双通讯;(附带Demo)

本系列博客学习由非官方人员 半颗心脏 潜心所力所写&#xff0c;仅仅做个人技术交流分享&#xff0c;不做任何商业用途。如有不对之处&#xff0c;请留言&#xff0c;本人及时更改。 1、 开门大篇&#xff0c;xClouds是什么&#xff1f;我什么要做&#xff1f;为什么要开源&…

ESP8266对接巴法云平台实现小爱同学控制开关灯

原理&#xff1a;esp8266连接巴法云平台mqtt服务并订阅主题&#xff0c;通过小爱语音发出指令&#xff0c;相当于mqtt的消息推送&#xff0c;从而进行控制esp8266 。 1. 巴法云平台创建MQTT设备云主题 在控制台新建mqtt设备云主题&#xff0c;字母数字自定义组合即可。 现在支…

小爱同学桌面提醒器开发0基础教程

1、视频效果 小爱同学桌面显示器 学会烧录软件到开发板&#xff0c;会改代码修改wifi信息&#xff0c;我在添加一下你的信息&#xff0c;就可以玩了。 2、实现原理 3、实现步骤&#xff1a; 购买开发板》烧录代码》连接大白服务器&#xff08;服务器对接小爱同学开放平台过程…

Arduino应用开发——通过小爱同学控制灯光

Arduino应用开发——通过小爱同学控制灯光 目录 Arduino应用开发——通过小爱同学控制灯光前言1 工作原理2 硬件准备3 软件准备3.1 Arduino IDE环境搭建3.2 Blinker APP账号注册和使用 4 编写程序5 关联米家APP和Blinker设备6 语音控制测试7 进阶用法7.1 亮度控制7.2 色温控制7…

小爱同学控制单片机或者其它硬件的思路记录

由于小米只能家具生态的协议是不开放的&#xff0c;但是有很多同学想使用小爱同学的语音功能去控制单片机、树莓派或者其他DIY硬件。因此有个下面这个构想。初步验证可行。 实验具备条件 DIY设备联网&#xff08;直接或者间接&#xff09; 小米手机&#xff08;小爱同学&…

小爱同学、Blinker 控制esp32自带灯熄灭---Micropython版本

操作官方案例修改增加小爱同学控制支持&#xff0c;具体代码上传到github可以参考&#xff0c;有帮助的话麻烦请star支持下&#xff0c;有细节问题也麻烦指出和交流 github地址: https://github.com/lonngxiang/xiaoai_blinker_mpy小爱控制eap32、blinker 1、具体实现细节 主…