基于STL实现自动贪心寻路算法的贪吃蛇小游戏


写贪吃蛇小游戏的想法来自CometOJ-Contest#13的B题,当时用STL双端队列维护蛇身的时候觉得非常方便,现在用EasyX图形库实现一下。


运行截图:

脑残贪吃蛇

欢迎界面:

普通模式:

无敌模式:


实现思路:

代码很短,写的时候基本上是想到哪写到哪。

现在看的话大概要分成四部分。

一、初始化,全局控制等

初始化所有信息,模式选择等。

二、蛇身

存储蛇位置,运动方向,控制蛇移动,更改方向等。

蛇身用std::deque实现,dq的前后端添加及弹出非常方便,不用过多担心溢出问题。

三、地图

存储下一个食物的坐标和已经被蛇身覆盖的坐标,对于普通模式可以判断是否会撞到自己的身体。

四、绘制

用exayX库在屏幕上绘制已经计算好的图形并显示。


几个point:

✦记录运行方向,可以快速计算蛇头下一个位置,同余坐标即可实现穿墙功能。

✦每次移动蛇尾pop一个单位,蛇头push一个单位即可,当蛇头吃到食物则蛇尾不用pop。

✦普通模式下蛇头撞向蛇身结束游戏。

✦无敌模式下可以蛇身覆盖。

✦Q键切换到自动模式。自动寻找食物采用曼哈顿距离贪心算法,无敌模式下没有问题,普通模式下可能会撞死自己(考虑到可以种子填充判断,但是时空复杂度要大一倍,没写(懒))。

✦游戏自动加速,初始时游戏速度为10fps,随着分数增加fps线性增加,当fps达到100(10ms/帧)时达到上限,游戏速度不再增加。


代码:

/*Zeolim - An AC a day keeps the bug away
*/
​
#include <graphics.h>
#include <iostream>
#include "stdafx.h"
#include <easyx.h>
#include <random>
#include <conio.h>
#include <queue>
#include <unordered_map>
#include <time.h>
#include <map>
#include <process.h>
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef std::pair <int, int> pii;
typedef std::vector <int> vi;
​
#define mp(x, y) make_pair(x, y)
#define fr(x, y, z) for(int x = y; x < z; ++x)
#define pb(x) push_back(x)
#define mem(x, y) memset(x, y, sizeof(x))
​
const int ROW = 32;
const int COL = 48;
const int lineHigh = 17;
const int mov[4][2] = { { 1, 0 },{ 0, 1 },{ 0, -1 },{ -1,0 } };
int gameMode = 0;
int runSpd = 100;
​
int coler[7][3] =
{{ 85,107,47 }, //WALL{ 245,245,245 }, //Back{ 211,211,211 } // line
};
​
bool fucked, autoC; //记录是否死亡,和是否开启自动模式
​
struct rmap
{int dmap[COL][ROW];int x, y;void init() //初始化地图{memset(dmap, 0, sizeof(dmap));getFood();}void getFood() //生成下一个食物{do{x = rand() % COL, y = rand() % ROW;} while (dmap[x][y] != 0);}bool isFucked(int x, int y) //判断是否死亡{return dmap[x][y] == 1;}
}MP;
​
struct body
{std::deque < pii > D;int dir;void init() //初始化蛇身 方向{D.clear();dir = 1; D.push_back(std::make_pair(COL / 2, ROW / 2));D.push_back(std::make_pair(COL / 2, ROW / 2 - 1));D.push_back(std::make_pair(COL / 2, ROW / 2 - 2));for (auto x : D)++MP.dmap[x.first][x.second];}void move() //向当前运行方向前方移动一格{pii p = D.front();int x = (p.first + mov[dir][0] + COL) % COL;int y = (p.second + mov[dir][1] + ROW) % ROW;if (p.first == MP.x && p.second == MP.y) //如果迟到食物 生成新食物{MP.getFood();}else //没有吃到尾巴缩短一格{pii x = D.back();--MP.dmap[x.first][x.second];D.pop_back();}
​if (gameMode == 1 && MP.isFucked(x, y)) //判断死亡{fucked = 1;}++MP.dmap[x][y];     //更新蛇头D.push_front(std::make_pair(x, y));}void ChangeDir(char x) //更新方向{int _dir = -1;if (x == 'A' || x == 'a' && dir != 0)_dir = 3;if (x == 'D' || x == 'd' && dir != 3)_dir = 0;if (x == 'W' || x == 'w' && dir != 1)_dir = 2;if (x == 'S' || x == 's' && dir != 2)_dir = 1;if (_dir != -1)dir = _dir;}
}Snk;
​
void drawMap()
{BeginBatchDraw(); //开始绘制setbkcolor(RGB(coler[1][0], coler[1][1], coler[1][2])); //绘制背景色cleardevice();
​Snk.move(); //蛇移动setlinecolor(RGB(211, 211, 211));  for (int i = 0; i < COL; ++i)  //绘制网格{for (int j = 0; j < ROW; ++j){rectangle(i * 10, j * 10 + lineHigh, i * 10 + 10, j * 10 + 10 + lineHigh);}}
​setlinecolor(RGB(30, 144, 255));setfillcolor(RGB(176, 224, 230));
​for (int i = 0; i < Snk.D.size(); ++i) //绘制蛇 注意坐标等比例扩大{pii x = Snk.D[i];fillrectangle(x.first * 10, x.second * 10 + lineHigh, x.first * 10 + 10, x.second * 10 + 10 + lineHigh);}
​setlinecolor(RGB(255, 69, 0));setfillcolor(RGB(255, 140, 0));fillcircle(MP.x * 10 + 5, MP.y * 10 + 5 + lineHigh, 5); //绘制食物
​setlinecolor(RGB(30, 144, 255));setfillcolor(RGB(225, 255, 255));pii x = Snk.D.front();fillrectangle(x.first * 10, x.second * 10 + lineHigh, x.first * 10 + 10, x.second * 10 + 10 + lineHigh);
​WCHAR text[200];settextcolor(RGB(0, 0, 0)); //绘制分数,模式等信息wsprintf(text, L"Score: %06d     GameSpeed: %06d     (q) AutoMode: (%d)     (e)Exit", Snk.D.size(), runSpd, autoC);outtextxy(20, 0, text);EndBatchDraw(); //结束绘制
}
​
void drawWelcome()
{BeginBatchDraw();setbkcolor(RGB(coler[1][0], coler[1][1], coler[1][2]));cleardevice();
​WCHAR text[50];settextcolor(RGB(0, 0, 0));wsprintf(text, L"Input Game Mode:  1.Normal  2.Who`s your daddy!");outtextxy(COL / 2 * 3, ROW / 2 * 8, text);
​wsprintf(text, L"Auther: Zeolim");outtextxy(COL / 2 * 8, ROW / 2 * 11, text);EndBatchDraw();
​do //获取键盘输入并更改模式{char x = _getch();if (x == '1')gameMode = 1;if (x == '2')gameMode = 2;} while (gameMode == 0);
​fucked = 0, autoC = 0;
}
​
void autoChange() //曼哈顿距离贪心
{int x = Snk.D.front().first, y = Snk.D.front().second;int nowdis = abs(x - MP.x) + abs(y - MP.y), rdis = 1000, p = -1;for (int i = 0; i < 4; ++i){if (i + Snk.dir == 3)continue;else{int rx = (x + mov[i][0] + COL) % COL, ry = (y + mov[i][1] + ROW) % ROW;if (gameMode == 1 && MP.isFucked(rx, ry)) //模式1 下一格必死不能走 continue;if (abs(rx - MP.x) + abs(ry - MP.y) < rdis) //贪心选择更新{rdis = abs(rx - MP.x) + abs(ry - MP.y);p = i;}}}if (p != -1) //更新方向Snk.dir = p;
}
​
​
int main()
{srand(time(0));initgraph(COL * 10, ROW * 10 + lineHigh);
​while (true){gameMode = 0;MP.init();Snk.init();
​drawWelcome(); //绘制主页面
​double t1, t2;
​t1 = GetTickCount();while (true){runSpd = max(10, 100 - int(Snk.D.size()));t2 = GetTickCount();
​if (t2 >= t1 + runSpd){t1 = GetTickCount();
​drawMap();
​if (_kbhit()) //keyboard hit 该函数为非阻塞函数 未敲击时不影响其他函数继续运行{auto x = _getch(); //获取一个字符if (x == 'q' || x == 'Q') //更新模式autoC ^= 1;else if (x == 'e' || x == 'E') //退出到主菜单break;else{Snk.ChangeDir(x); //更新方向 wasdcontinue;}}if (autoC) //如果自动 则寻找下一个位置{autoChange();}}
​if (fucked) //死亡退出{MessageBox(GetHWnd(), L"You fucked!", L"SORRY", MB_OK);break;}}}
​return 0;
}

Done!

基于STL实现自动贪心寻路算法的贪吃蛇小游戏相关推荐

  1. STM32F407基于陀螺仪的贪吃蛇小游戏(全网最详细)

    一.前言 本次设计我用MPU6050在KEIL 5的环境下改进了贪吃蛇小游戏,用的开发板是STM32F407,本次设计综合利用多种ARM外设接口实现对外部设备信息的采集.处理及显示,实现了贪吃蛇游戏实 ...

  2. 基于stm32、0.96寸OLED实现的贪吃蛇小游戏(详细源码注释)

    简介:本实验基于stm32最小系统.0.96寸OLED(68*128)和摇杆实现一个经典的贪吃蛇小游戏.项目源码地址:点击下载. 硬件设计: 普通摇杆,0.96寸OLED 单色屏幕(SPI协议通讯), ...

  3. 基于Stm32f407 的贪吃蛇小游戏【正点原子-探索者开发板】

    基于单片机stm32f407的单机小游戏----贪吃蛇小游戏 1.介绍 这是我花一个星期完成的一个简单地单机贪吃蛇小游戏项目,芯片是stm32f407,项目是基于正点原子-探索者开发板完成的,有需要的 ...

  4. 基于C语言Ncurse库和链表的简单贪吃蛇小游戏

    参考:基于C语言Ncurse库和链表的简单贪吃蛇小游戏 作者:三速何时sub20 发布时间:2020-09-29 10:23:51 网址:https://blog.csdn.net/weixin_44 ...

  5. 基于STM32的贪吃蛇小游戏

    基于STM32的贪吃蛇小游戏 初学32一个月,学的并不多,便想着做一个贪吃蛇小游戏,因为有51单片机做贪吃蛇的经验,所以实现出来并不困难. 作品简介 游戏面版将在4.3寸480*800)液晶上显示,初 ...

  6. 计算机毕业设计-基于Java的GUI实现贪吃蛇小游戏

    标题:基于Java多线程版本GUI贪吃蛇小游戏 1.项目技术点 1.多线程的运用. 2.JAVA的GUI的运用. 3.数据结构的灵活运用. 4.随机食物的生成. 5.关卡加速,随着蛇身增长,蛇的速度也 ...

  7. 基于Linux ncurses图形库的贪吃蛇小游戏

    达者为先  师者之意 基于Linux ncurses图形库的贪吃蛇小游戏 前言 1 ncurses库程序的标准模式 2 ncurses库的常用函数 3 基于Linux ncurses图形库的贪吃蛇小游 ...

  8. 【精选】基于EasyX的贪吃蛇小游戏

    文章目录 前言 一.项目环境 1.Visual Studio 2019 2.EasyX 20200902 二.运行效果展示 0.加载游戏 1.主菜单 2.游戏设置 3.游戏说明 4.生存模式 5.无尽 ...

  9. html5小游戏源码_[源码和报告分享]基于HTML5实现的贪吃蛇小游戏

    1 游戏介绍 贪吃蛇的经典玩法有两种: 积分闯关 一吃到底 第一种是笔者小时候在掌上游戏机最先体验到的(不小心暴露了年龄),具体玩法是蛇吃完一定数量的食物后就通关,通关后速度会加快:第二种是诺基亚在1 ...

最新文章

  1. MATLAB对字符串进行分割
  2. preempt_count详解
  3. 任务队列和异步接口的正确打开方式(.NET Core版本)
  4. zxing二维码生成工具类
  5. sqlyog设置自动补全_Visual Studio Code 最好的功能、插件和设置
  6. web开发要学多久,HTML表格标签,薪资翻倍
  7. 为什么你跟高手有差距?因为他们会在假期里读这5本书
  8. 串口循环缓存区 简单 免初始化 不用堆、指针、分段memcpy
  9. 资料管理工具VSGoogle?
  10. android开发-01-搭建环境
  11. 左手招新,右手裁员,2019开年就业形势扑朔迷离
  12. OBLOG4.5 商业SQL版 漏洞解析
  13. BZOJ2827 千山鸟飞绝
  14. java用zipOutputStream压缩后用WinRAR解压出现“不可预料的压缩文件末端”错误
  15. No JSON object could be decoded
  16. 你们以为洗白了张柏芝,自己就不是婊子
  17. 油猴脚本 from greasyfork
  18. 人工智能算法之三数码
  19. [视觉SLAM十四讲]学习笔记2-关于欧拉角和万向锁
  20. js学习笔记--了解promise

热门文章

  1. 安卓判断虚拟导航键是否显示
  2. ubuntu安装nvidia显卡的驱动和cuda
  3. centos 6.5 无线网卡配置(hp mini)
  4. 在Cocos Creator Store中下载的插件和代码存放在哪里呢?
  5. 微信一键激活会员卡(跳转自定义链接地址)
  6. 13 个问题帮你选型 “客户体验管理SaaS平台”
  7. 推荐一些好用的工具网站
  8. Python 简单爬虫下载小说txt
  9. 博图V15.1 如何启用仿真
  10. 信息系统建设和能力服务评估(CS)资质申报意义