基于STL实现自动贪心寻路算法的贪吃蛇小游戏
基于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实现自动贪心寻路算法的贪吃蛇小游戏相关推荐
- STM32F407基于陀螺仪的贪吃蛇小游戏(全网最详细)
一.前言 本次设计我用MPU6050在KEIL 5的环境下改进了贪吃蛇小游戏,用的开发板是STM32F407,本次设计综合利用多种ARM外设接口实现对外部设备信息的采集.处理及显示,实现了贪吃蛇游戏实 ...
- 基于stm32、0.96寸OLED实现的贪吃蛇小游戏(详细源码注释)
简介:本实验基于stm32最小系统.0.96寸OLED(68*128)和摇杆实现一个经典的贪吃蛇小游戏.项目源码地址:点击下载. 硬件设计: 普通摇杆,0.96寸OLED 单色屏幕(SPI协议通讯), ...
- 基于Stm32f407 的贪吃蛇小游戏【正点原子-探索者开发板】
基于单片机stm32f407的单机小游戏----贪吃蛇小游戏 1.介绍 这是我花一个星期完成的一个简单地单机贪吃蛇小游戏项目,芯片是stm32f407,项目是基于正点原子-探索者开发板完成的,有需要的 ...
- 基于C语言Ncurse库和链表的简单贪吃蛇小游戏
参考:基于C语言Ncurse库和链表的简单贪吃蛇小游戏 作者:三速何时sub20 发布时间:2020-09-29 10:23:51 网址:https://blog.csdn.net/weixin_44 ...
- 基于STM32的贪吃蛇小游戏
基于STM32的贪吃蛇小游戏 初学32一个月,学的并不多,便想着做一个贪吃蛇小游戏,因为有51单片机做贪吃蛇的经验,所以实现出来并不困难. 作品简介 游戏面版将在4.3寸480*800)液晶上显示,初 ...
- 计算机毕业设计-基于Java的GUI实现贪吃蛇小游戏
标题:基于Java多线程版本GUI贪吃蛇小游戏 1.项目技术点 1.多线程的运用. 2.JAVA的GUI的运用. 3.数据结构的灵活运用. 4.随机食物的生成. 5.关卡加速,随着蛇身增长,蛇的速度也 ...
- 基于Linux ncurses图形库的贪吃蛇小游戏
达者为先 师者之意 基于Linux ncurses图形库的贪吃蛇小游戏 前言 1 ncurses库程序的标准模式 2 ncurses库的常用函数 3 基于Linux ncurses图形库的贪吃蛇小游 ...
- 【精选】基于EasyX的贪吃蛇小游戏
文章目录 前言 一.项目环境 1.Visual Studio 2019 2.EasyX 20200902 二.运行效果展示 0.加载游戏 1.主菜单 2.游戏设置 3.游戏说明 4.生存模式 5.无尽 ...
- html5小游戏源码_[源码和报告分享]基于HTML5实现的贪吃蛇小游戏
1 游戏介绍 贪吃蛇的经典玩法有两种: 积分闯关 一吃到底 第一种是笔者小时候在掌上游戏机最先体验到的(不小心暴露了年龄),具体玩法是蛇吃完一定数量的食物后就通关,通关后速度会加快:第二种是诺基亚在1 ...
最新文章
- MATLAB对字符串进行分割
- preempt_count详解
- 任务队列和异步接口的正确打开方式(.NET Core版本)
- zxing二维码生成工具类
- sqlyog设置自动补全_Visual Studio Code 最好的功能、插件和设置
- web开发要学多久,HTML表格标签,薪资翻倍
- 为什么你跟高手有差距?因为他们会在假期里读这5本书
- 串口循环缓存区 简单 免初始化 不用堆、指针、分段memcpy
- 资料管理工具VSGoogle?
- android开发-01-搭建环境
- 左手招新,右手裁员,2019开年就业形势扑朔迷离
- OBLOG4.5 商业SQL版 漏洞解析
- BZOJ2827 千山鸟飞绝
- java用zipOutputStream压缩后用WinRAR解压出现“不可预料的压缩文件末端”错误
- No JSON object could be decoded
- 你们以为洗白了张柏芝,自己就不是婊子
- 油猴脚本 from greasyfork
- 人工智能算法之三数码
- [视觉SLAM十四讲]学习笔记2-关于欧拉角和万向锁
- js学习笔记--了解promise