c++编程迷宫小游戏
如何才能提供自己的编程水平,就要千锤百炼。
main.cpp
#include "labyrith.h"// 主函数
int main()
{FrameWindow frame; // 建立图形界面frame.Run(); // 运行控制函数while(1) // 主循环{frame.Run(); // 运行控制}getch(); // 当有按键的时候关闭图形closegraph();return 0;
}
labyrinth.cpp
#include "labyrith.h"int Wall[22][22]; // 墙壁
int entranceX; // 入口
int entranceY;
int exitX; // 出口
int exitY;// 默认构造函数
FrameWindow::FrameWindow()
{initgraph(960, 660); // 建立图形界面setbkcolor(LIGHTGREEN); // 设置背景颜色为亮绿色direct = 0; // 设置 direct 的初值为 0control = 0; // 默认控制权为 0 loadimage(&img, "res\\bk.jpg", 29, 29); // 加载图片
}// 运行控制
void FrameWindow::Run()
{cleardevice(); // 清屏NewBackground(); // 绘制新背景图DrawSome(); // 绘制些神马control = 0; // 首先将函数对程序程序的控制权置 0direct = 0; // 设置 direct 的初值为 0// 主循环while(1){if(kbhit()) // 检测按键{direct = getch(); // 从按键获取输入mciSendString("play res\\key.wav", NULL, 0, NULL); // 按键声if( direct == 115 && control == 0) // s 的键值为 115{StartDrawLabyrith(); // 开始绘制迷宫}if(direct == 101 && control == 2) // e 的键值为 101{SetLabyrith(); // 设置迷宫的入口和出口}if(direct == 100 && control == 3) // d 的键值为 100{control = -1; // 将 control 设置为 -1 的目的是// 让程序从 Demo() 回到 Run() 时只响应刷新操作Demo(); // 寻找路径并演示}if(direct == 63 && (control == 0 || control == -1)) // 按 F5 刷新{break;}}else{Sleep(10);}}
}// 绘制新背景
void FrameWindow::NewBackground()
{float H, S, L; // 定义 HSL 颜色模型的 3 个变量H = 110; // 色相S = 1; // 饱和度L = 0.4522f; // 亮度for(int y = 0; y != 660; ++y) // 绘制迷宫背景颜色{L += 0.000125f;S -= 0.00125f;setcolor(HSLtoRGB(H, S, L));line(0, y, 660, y);}H = 50; // 色相S = -3.2555f; // 饱和度L = 0.525617f; // 亮度for(int y = 0; y != 660; ++y) // 绘制提示信息部分背景{L += 0.000000085f;S -= 0.0015f;setcolor(HSLtoRGB(H, S, L));line(660, y, 960, y);}
}// 绘制些神马
void FrameWindow::DrawSome()
{setcolor(LIGHTRED);for(int i = 0; i < 22; ++i) {// 外围墙壁在 Wall 数组中的位置置 1 Wall[0][i] = 1;Wall[i][0] = 1;Wall[21][i] = 1;Wall[i][21] = 1;// 绘制外围墙壁putimage(0 * 30 + 1, i * 30 + 1, &img);putimage(i * 30 + 1, 0 * 30 + 1, &img);putimage(631, i * 30 + 1, &img);putimage(i * 30 + 1, 631, &img);putimage(931, i * 30 + 1, &img);line(i * 30, 0, i * 30, 660); // 绘制格子线line(0, i * 30, 660, i * 30); // 绘制格子线}for(int i = 0; i < 10; ++i) // 绘制提示区域外围框{putimage(i * 30 + 661, 1, &img);putimage(i * 30 + 661, 631, &img);}for(int i = 1; i <= 20; ++i) // 其它的 Wall 数组的值暂时置 0{for(int j = 1; j <= 20; ++j){Wall[i][j] = 0;}}// 绘制提示信息RECT r = {710, 40, 900, 300};setbkmode(TRANSPARENT); // 设置输出文字背景模式为透明setcolor(BLUE); // 设置输出文字颜色setfont(15, 0, "宋体");// 输出提示信息drawtext("游戏操作介绍:\n\n按键 S:绘制迷宫。\n鼠标左键绘制墙壁,\鼠标右键擦除墙壁。\n\n按键 E:设置迷宫的入口和出口。\n使用鼠标\左键来设置入口和出口,右键取消设置。\n\n按键 D:进行迷宫的探索\,寻找从入口到出口的最短路径,由小球来演示从入口到出口的路径。",&r, DT_WORDBREAK);setbkmode(OPAQUE); // 恢复默认填充颜色// 输出提示信息outtextxy(730, 400, "迷宫状态: ");outtextxy(810, 400, "等待绘制");outtextxy(750, 500, "按 F5 重新开始");
}// 开始绘制迷宫
void FrameWindow::StartDrawLabyrith()
{int x = 0, y = 0; // 标记鼠标的坐标使用outtextxy(810, 400, "正在绘制"); // 修改迷宫状态FlushMouseMsgBuffer(); // 清空鼠标消息缓冲区// 主循环while(1){if(kbhit()){direct = getch(); // 获取按键信息mciSendString("play res\\key.wav", NULL, 0, NULL); // 按键声if(direct == 101) // e 的键值为 101{control = 2; // 控制权值为 2 break;}else if(direct == 63) // F5 刷新{break;}}else if(MouseHit()){msg = GetMouseMsg(); // 获取鼠标消息x = msg.x / 30; // 获取鼠标所在格子在 Wall 中的位置y = msg.y / 30;if(msg.x > 30 && msg.x < 630 && msg.y > 30 && msg.y < 630) // 只能在这个区域里面响应鼠标消息{switch(msg.uMsg) // 消息的种类{case WM_LBUTTONDOWN: // 左键按下{Wall[y][x] = 1; // y 对应行, x 对应列, 将对应的位置置 1putimage(x * 30 + 1, y * 30 +1, &img); // 放置图片}break;case WM_RBUTTONDOWN: // 右键按下{Wall[y][x] = 0; // y 对应行, x 对应列, 将对应的位置置 0PrintGrid(x * 30, y * 30); // 重新绘制这个格子setcolor(BLUE );}break;default:break;}}}else {Sleep(10);}}
}// 设置入口和出口
void FrameWindow::SetLabyrith()
{int x = 0, y = 0; // 临时参数entranceX = -1; // 入口entranceY = -1;exitX = -1; // 出口exitY = -1; outtextxy(810, 400, "设置入口"); // 提示信息// 主循环while(1){if(kbhit()) // 键盘消息{direct = getch(); // 获取消息mciSendString("play res\\key.wav", NULL, 0, NULL); // 按键声if(direct == 100 && entranceX != -1 && exitX != -1) // 如果出入口都设置好, 按 d 键退出设置模式{control = 3; // 控制权变为 3, 回到 Run 中由其判断由谁控制程序;break;}else if(direct == 63) // F5 刷新{control = 0;break;}}else if(MouseHit()){msg = GetMouseMsg(); // 获取鼠标消息x = msg.x / 30; // 获取鼠标所在格子在 Wall 中的位置y = msg.y / 30; if(entranceX != -1 && exitX != -1) // 完成设置{outtextxy(810, 400, "设置完成");}if(msg.x > 30 && msg.x < 630 && msg.y > 30 && msg.y < 630) // 只能在这个区域里面响应鼠标消息{if(Wall[y][x] == 0 && msg.uMsg == WM_LBUTTONDOWN) // 如果这个位置不是墙壁, 并且按下左键{if(entranceX == -1 && (exitX != x || exitY != y)) // 确保此处没被设置{entranceX = x; // 入口位置entranceY = y;Wall[y][x] = 1;outtextxy(x * 30 + 8, y * 30 + 10,_T("In")); // 将此处标记为 In if(exitX == -1) // 若此时还未设置出口{outtextxy(810, 400, "设置出口"); // 改变迷宫状态}}else if(exitX == -1 && (entranceX != x || entranceY != y)) // 此处未设置出口且不是入口位置{exitX = x; // 出口位置exitY = y;Wall[y][x] = 1;outtextxy(x * 30 + 4, y * 30 + 8,_T("Out")); // 将此处标记为 Outif(entranceX == -1) // 若此时还未设置入口{outtextxy(810, 400, "设置入口"); // 改变迷宫状态}}}else if(Wall[y][x] == 1 && msg.uMsg == WM_RBUTTONDOWN) // 如果这个位置不是墙壁, 并且按下右键{if(x == entranceX && y == entranceY) // 取消设置入口{entranceX = -1;entranceY = -1;Wall[y][x] = 0;outtextxy(810, 400, "设置入口"); // 改变迷宫状态PrintGrid(x * 30, y * 30); // 从新绘制格子setcolor(BLUE); // 恢复原线条颜色}else if(x == exitX && y == exitY) // 取消设置出口{exitX = -1;exitY = -1;Wall[y][x] = 0;outtextxy(810, 400, "设置出口"); // 改变迷宫状态PrintGrid(x * 30, y * 30); // 重新绘制格子setcolor(BLUE); // 恢复原线条颜色}} } } }
} // 探索迷宫路径, 并演示成果
void FrameWindow::Demo()
{Queue qu;Node node;int zx[4] = {1,0,-1,0},zy[4] = {0,1,0,-1}; // 四个方向int find = 0; // find 值为 1 表示结束寻找路径int x = 0, y = 0; // 临时参数 x, ynode.x = entranceX; // 入口位置node.y = entranceY;outtextxy(810, 400, "正在演示"); // 更改迷宫状态qu.Push(node); // 入队操作// 广度搜索算法寻找最短路径while(qu.GetFront() < qu.GetRear() && find == 0){node.x = qu.visit(qu.GetFront()).x; // 新队头的坐标node.y = qu.visit(qu.GetFront()).y;for(int i = 0; i < 4; ++i) // 朝四个方向探索{x = node.x;y = node.y;node.x += zx[i];node.y += zy[i];if(Wall[node.y][node.x] == 0) // 如果旁边的位置不是墙壁并且没有被访问{qu.Push(node); // 将此位置加入队列Wall[node.y][node.x] = 1;}if(node.x == exitX && node.y == exitY) // 找到出口位置{qu.Push(node); // 将出口位置加入队列find = 1; // find 置 1, 表示找到出口break;}node.x = x;node.y = y;}qu.Pop(); // 将队头出队}if(find == 1) // 如果找到出口{qu.ResetPre(); // 重置节点前驱qu.PrintRoute(); // 输出路径}else{outtextxy(760, 440, "不存在路径"); // 否则, 视为不存在路径}}// 绘制新格子
void PrintGrid(int x, int y)
{float H = 110, S = 1, L = 0.4522f; // 设置 H S L的初值S -= (float)y * 0.00125f; // 设置 S 在这线条的值L += (float)y * 0.000125f; // 设置 L 在这个线条上for(int i = y + 1; i < y + 30; ++i) // 循环绘制线条{L += 0.000125f;S -= 0.00125f;setcolor(HSLtoRGB(H, S, L));line(x + 1, i, x + 29, i);}
}// 默认构造函数
Queue::Queue()
{data = new Node[QueueMaxLength]; // 申请队列存储空间front = 0; // 队头为 0rear = 0; // 队尾为 0
}// 析构函数
Queue::~Queue()
{delete (data); // 释放队列存储空间
}// 出队操作
void Queue::Pop()
{++front; // 出队操作
}// 入队操作
void Queue::Push(Node node)
{data[rear].x = node.x;data[rear].y = node.y;if(rear == 0) // 如果是第一个元素入队, 将其前驱指向空{data[rear].pre = NULL;}else{data[rear].pre = &data[front]; // 不是, 将前驱指向队头}++rear; // 队尾加 1
}// 获取队头
inline int Queue::GetFront()
{return front;
}// 获取队尾
inline int Queue::GetRear()
{return rear;
}// 访问队列
Node Queue::visit(int i)
{return data[i];
}// 重置节点前驱
void Queue::ResetPre()
{Node *s = &data[rear - 1]; // 指向出口Node *p = s->pre; // 出口的前驱Node *r ;// 主循环while(1){r = p->pre; // r 指向 p 的前驱p->pre = s; // p 的前驱指向 ss = p; // s 指向 pp = r; // p 指向 rif(r == NULL) // 如果 r 为空, 退出循环{break;}}
}// 输出路径
void Queue::PrintRoute()
{Node * s = data[0].pre; // 入口位置// 主循环while(s != &data[rear - 1]){setfillstyle(LIGHTRED); // 设置填充颜色// 绘制圆fillcircle(s->x * 30 + 15, s->y * 30 + 15, 10);Sleep(100);s = s->pre; // s 指向其前驱}outtextxy(810, 400, "演示完成"); // 改变迷宫状态
}
labyrith.h
#ifndef labyrith_h
#define labyrith_h#include <iostream>
#include <graphics.h>
#include<windows.h>
#include <conio.h>#pragma comment(lib, "WINMM.LIB") using namespace std;int const QueueMaxLength = 1000; // 堆栈最大长度struct Node // 定义一个节点
{int x; // 保存矩形的 x 坐标int y; // 保存矩形的 y 坐标Node *pre; // 保存其根节点
};class FrameWindow // 定义一个窗口框架
{
private:IMAGE img; // 墙壁图片int direct; // 接受特殊按键时结束绘制迷宫int control; // 标记程序控制控制权MOUSEMSG msg; // 鼠标消息
public:FrameWindow(); // 默认构造函数void NewBackground(); // 绘制新背景void DrawSome(); // 绘制些什么void Run(); // 运行控制void StartDrawLabyrith(); // 开始绘制迷宫void SetLabyrith(); // 设置迷宫void Demo(); // 寻找路径, 并演示
};class Queue // 定义队列类
{
private:Node *data; // 数据域int front; // 队头int rear; // 队尾
public:Queue(); // 队列默认构造函数~Queue(); // 析构函数void Pop(); // 出队操作void Push(Node node); // 入队操作void ResetPre(); // 重置节点前驱Node visit(int i); // 访问节点inline int GetFront(); // 获取队头inline int GetRear(); // 获取队尾void PrintRoute(); // 打印路径
};void PrintGrid(int x, int y); // 在用户取消设置某格子为墙壁之后, 从新绘制格子extern int Wall[22][22]; // 墙壁标记数组
extern int entranceX; // 入口
extern int entranceY;
extern int exitX; // 出口
extern int exitY;#endif
运行结果:
下载链接:
https://download.csdn.net/download/EDU_YONG/85501843
或者私信我:免费提供。
c++编程迷宫小游戏相关推荐
- Python游戏开发,pygame模块,Python实现过迷宫小游戏
前言 今天为大家带来解闷用的过迷宫小游戏分享给大家好了.让我们愉快地开始吧~ 效果展示 开发工具 Python版本: 3.6.4 相关模块: pygame模块: 以及一些Python自带的模块. 环境 ...
- c语言自动按键脚本,C语言键盘控制走迷宫小游戏
本文实例为大家分享了C语言键盘控制走迷宫小游戏的具体代码,供大家参考,具体内容如下 在看了<啊哈C语言>之后想写一个游戏demo 游戏的截图 首先是启动界面 然后是初始化 接下来是键盘操控 ...
- python迷宫小游戏大全_Python迷宫小游戏源代码、源程序
Python迷宫小游戏源程序包括两个文件maze.py和mazeGenerator.py,mazeGenerator.py实现迷宫地图的生成,程序运行截图: mazeGenerator.py impo ...
- 一个Python的迷宫小游戏
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 迷宫小游戏 前言 一.python是什么? 二.使用步骤 1.引入库 2.读入数据 2.1.游戏开始 2.2.控制角色移动 2.3.鼠 ...
- 分享一个C语言矿井逃生迷宫小游戏【附源码】
用C语言写的一个迷宫小游戏,游戏玩法是通过鼠标控制帽子上的灯走出迷宫 // 定义常量 #define PI 3.141592653589 // 圆周率 #define UNIT_GROUND 0 // ...
- 用 Dev-C++ 编写简单的走迷宫小游戏
用 Dev-C++ 编写简单的走迷宫小游戏 前言 基础版 优化版 前言 以下是显示效果 B站视频讲解:[小游戏]用 Dev-C++ 编写简单的控制台走迷宫小游戏 [小游戏]用 Dev-C++ 编写简单 ...
- UEFI开发探索94 – 迷宫小游戏
(请保留-> 作者: 罗冰 https://blog.csdn.net/luobing4365) UEFI下的迷宫小游戏 1 Maze程序结构分析 1)定义全局变量 2)设置迷宫 3) 游戏控制 ...
- 用R写一个迷宫小游戏
R实现迷宫小游戏 效果图 缘起 R的图形API DFS函数生成迷宫 数据结构 代码解析 后话 附录:完整代码 效果图 缘起 刚装了Ubuntu系统,发现里面有自带的扫雷等小游戏.最近又疯狂使用R,忽然 ...
- 用C语言做一个迷宫小游戏
用C语言做一个迷宫小游戏,以下是代码段 这个迷宫游戏使用了递归回溯算法来寻找通往出口的路径.迷宫中的墙用'#'表示,路径用空格表示,入口和出口分别用'S'和'E'表示,已走过的路径用'*'表示.在生成 ...
- c++编程拼图小游戏
如何才能提供自己的编程水平,就要千锤百炼.今天给大家推荐的是拼图小游戏:采用 c++ 编写, 主要使用到了两个类, 分别是 GameFrame 和 Picture.GameFrame 负责游戏界面的初 ...
最新文章
- Spark on K8S及history服务部署
- [js对象]JS入门之Date对象
- python数据框去重_【Python】基于某些列删除数据框中的重复值
- ArcGIS Enterprise 10.5.1 静默安装部署记录(Centos 7.2 minimal)- 6、总结
- 彻底卸载2345系列
- 7.TCP的十一种状态集
- N阶行列式计算(JAVA)
- 当我们在谈论HTTP队头阻塞时,我们在谈论什么?
- 这些NFT项目已经拍成了电影
- 新冠病毒数据分析报告
- JavaScript (一) js的介绍及基本语法变量
- 悟空CRM9从零开始搭建详细步骤——肯定成功
- od使用的小tips
- linux配置usb主从_基于Linux的USB 主/从设备之间通讯的三种方式
- 【新能源】从“材料”到“电池组”一文读懂动力电池生产全流程!
- python实战小项目,多线程百度云盘下载,突破限速,超越迅雷超高速下载
- MATLAB---回归分析
- 龙族路明非和零h_后宫文<路明非的幸福生活>主CP路零诺
- electron教程(四): 使用electron-builder或electron-packager将项目打包为可执行桌面程序(.exe)
- js 转 ts 文件
热门文章
- html校园网页设计作品欣赏,html网页设计作品
- 加班到凌晨三点?一张图看懂华为员工睡眠时间!!
- Python中的切片(详细篇)学起来喔
- the little schemer 笔记(4)
- 关于新正方教务系统(湖北工程学院)的one day越权漏洞的说明
- 什么是微信SCRM客服系统
- 超算入门笔记:大型机上如何运行WRF模式?一文总结(并行运算、Linux基础、作业调度、WRF运行)
- html5断点续传播放视频,HTML5 大文件断点续传完整思路整理
- 一文彻底解决An error occurred while creating the AVD. See idea.log for details问题
- introduction