如何使用C++语言实现拼图游戏
发表于:2024-11-12 作者:千家信息网编辑
千家信息网最后更新 2024年11月12日,小编给大家分享一下如何使用C++语言实现拼图游戏,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!开发环境:Visual St
千家信息网最后更新 2024年11月12日如何使用C++语言实现拼图游戏
小编给大家分享一下如何使用C++语言实现拼图游戏,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!
开发环境:Visual Studio 2019,easyx图形库。
easyx下载官网:
EasyX Graphics Library for C++
https://easyx.cn/
easyx使用文档:
EasyX 文档 - 函数说明
https://docs.easyx.cn/zh-cn/reference
游戏功能列表:
其主要功能描述如下:
1.图片尺寸自适应
2.图片动态分割
3.查看原图
4.随机切换图片
5.鼠标拖动拼图<-->交换拼图块
6.自动判断拼图成功
拓展功能:
背景音乐(开,关)
游戏中Esc键返回桌面
游戏规则窗口
游戏效果
封面(音乐按钮有点拉跨~)
游戏初始图(我的心是冰冰的)
通关图
一.头文件和基本量
#include#include #include #include #include #include //音乐#pragma comment(lib,"Winmm.lib") //静态库,调用音乐using namespace std;constexpr auto N = 3; //3*3拼图IMAGE img[4], imgs[9]; //img存整张图片,imgs暂存拼图块int aim_c, aim_r; //拼图块坐标int map[3][3] = { 0 }; //存拼图块int NUM = 0; //关卡数计数
二.封面
//开始界面void start(){ loadimage(NULL, L"cover.jpg"); setbkmode(TRANSPARENT); settextcolor(BLACK); settextstyle(60, 0, _T("楷体"),0,0,4,false,false,false); outtextxy(180, 120, L"拼图游戏"); //游戏名称 settextstyle(30, 0, _T("微软雅黑")); setfillcolor(BROWN); setlinestyle(BS_SOLID, 5); setlinecolor(RED); fillroundrect(220, 220, 370, 270, 10, 10); settextstyle(30, 0, _T("宋体"), 0, 0, 6, false, false, false); //开始按钮 outtextxy(270, 230, L"开始"); fillroundrect(220, 300, 370, 350, 10, 10); outtextxy(240, 310, L"游戏规则"); setfillcolor(BROWN); setlinestyle(BS_SOLID, 5); setlinecolor(BLACK); fillcircle(490, 440, 30); //音乐控制按钮:开 fillcircle(560, 440, 30); //音乐控制按钮:关 outtextxy(380, 430, L"音乐:"); setfillcolor(BLACK); POINT pts[] = { {481,425},{481,455},{507,440} }; fillpolygon(pts, 3); fillrectangle(546, 425, 554, 455); fillrectangle(566, 425, 574, 455); rules();}
三.数据初始化
//游戏初始化void init(){ //加载资源图片,4张图4个关卡 loadimage(&img[0], L"picture1.jpg", 600, 600); loadimage(&img[1], L"picture2.jpg", 600, 600); loadimage(&img[2], L"picture3.jpg", 600, 600); loadimage(&img[3], L"picture4.jpg", 600, 600); //设置最后一张图片为空白图片,作为目标图片 loadimage(&imgs[8], L"white.jpg", 200, 200); //设置随机种子 srand((unsigned)time(NULL));}
四.封面规则按钮
//封面规则函数int rules(){ ExMessage Mou; //鼠标消息 while (1) { Mou = getmessage(EM_MOUSE); switch (Mou.message) //对鼠标信息进行匹配 { case WM_LBUTTONDOWN: //按下左键 if (Mou.x >= 220 && Mou.x <= 370 && Mou.y >= 300 && Mou.y <= 350) { HWND hwnd = GetHWnd(); MessageBox(NULL, L"1.鼠标左键点击空白图处周围图片交换位置\n2.鼠标右键任意处按下显示参照图片\n3.鼠标中键更换背景图片\n4.按Esc键返回封面", L"游戏规则", MB_OKCANCEL); break; //规则按钮 } if (Mou.x >= 220 && Mou.x <= 370 && Mou.y >= 220 && Mou.y <= 270) { return 0; //开始按钮 } if (Mou.x >= 460 && Mou.x <= 520 && Mou.y >= 410 && Mou.y <= 470) { BGM(); //音乐播放按钮 break; } if (Mou.x >= 530 && Mou.x <= 590 && Mou.y >= 410 && Mou.y <= 470) { mciSendString(L"close back", 0, 0, 0); //音乐关闭按钮 break; } } } }
五.构造拼图
//拼图构造函数void GameInit(){ //把拼图贴上去 putimage(0, 0, &img[NUM]); //设置绘图目标为img对象 对拼图图片进行切割 SetWorkingImage(&img[NUM]); for (int y = 0, n = 0; y < N; y++) { for (int x = 0; x < N; x++) { if (n == 8) break; //获取100*100像素图片,存储在img中; getimage(&imgs[n++], x * 200, y * 200, (x + 1) * 200, (y + 1) * 200); } } //设置绘图目标为绘图窗口 SetWorkingImage(); //初始化地图0~15 for (int i = 0, k = 0; i < N; i++) { for (int j = 0; j < N; j++) { map[i][j] = k++; } } //打乱地图 for (int k = 0; k <= 1000; k++) { //得到目标所在的行和列 for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { if (map[i][j] == 8) //空白图片作为交换目标 { aim_r = i; aim_c = j; break; } } } //一千次打乱顺序之后需要将空白图片转移到右下角 //可以封装成函数下面这个代码 if (k == 1000) { //将空白图片循环转移到右下角 while (aim_r < 2) { //保证空白目标在最下 map[aim_r][aim_c] = map[aim_r + 1][aim_c]; map[aim_r + 1][aim_c] = 8; aim_r++; } while (aim_c < 2) { //保证空白目标在最右 map[aim_r][aim_c] = map[aim_r][aim_c + 1]; map[aim_r][aim_c + 1] = 8; aim_c++; } return; } int dir = rand() % 4; //随机一个方向 switch (dir) { case 0: //向上交换 if (aim_r >= 1) { //空白图片和空白处上面的图片交换 map[aim_r][aim_c] = map[aim_r - 1][aim_c]; map[aim_r - 1][aim_c] = 8; break; } case 1: //向下交换 if (aim_r < 2) { //空白图片和空白处下面的图片交换 map[aim_r][aim_c] = map[aim_r + 1][aim_c]; map[aim_r + 1][aim_c] = 8; break; } case 2: //向左交换 if (aim_c >= 1) { //空白图片和空白处左边的图片交换 map[aim_r][aim_c] = map[aim_r][aim_c - 1]; map[aim_r][aim_c - 1] = 8; break; } case 3: //向右交换 if (aim_c < 2) { //空白图片和空白处右边的图片交换 map[aim_r][aim_c] = map[aim_r][aim_c + 1]; map[aim_r][aim_c + 1] = 8; break; } } }}
六.绘图函数
//绘图函数void DrawMap(){ FlushBatchDraw(); //开始渲染图片 for (int y = 0; y < N; y++) { for (int x = 0; x < N; x++) { putimage(x * 200, y * 200, &imgs[map[y][x]]); } } EndBatchDraw();}
七.背景音乐
//背景音乐函数void BGM(){ //打开音乐,播放音乐 mciSendStringW(L"open ./Thrills.mp3 alias back", NULL, 0, NULL); mciSendStringW(_T("play back repeat"), 0, 0, 0);}
八.数据更新
//数据更新函数void play(){ int col, row; //鼠标点击的位置 ExMessage msg; //鼠标消息 msg = getmessage(EM_MOUSE|EM_KEY); //获取鼠标消息 switch (msg.message) //对鼠标消息进行匹配 { case WM_LBUTTONDOWN: //当鼠标消息是左键按下时 //获取鼠标按下所在列 col = msg.x / 200; if (msg.x == 600) col = 2; //获取鼠标按下所在行 row = msg.y / 200; if (msg.y == 600) row = 2; //得到目标所在行和列 for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { if (map[i][j] == 8) //空白处为交换目标 { aim_r = i; aim_c = j; } } } //判断鼠标点击位置和目标是否相邻,相邻交换数据 if (row == aim_r && col == aim_c + 1 || row == aim_r && col == aim_c - 1 || row == aim_r + 1 && col == aim_c || row == aim_r - 1 && col == aim_c) { //鼠标点击图片和空白目标图片交换 map[aim_r][aim_c] = map[row][col]; map[row][col] = 8; } DrawMap(); break; case WM_RBUTTONDOWN: //当鼠标消息是右键按下时 putimage(0, 0, &img[NUM]); //将关卡图片贴到窗口上 break; case WM_RBUTTONUP: //当鼠标消息是右键抬起时 DrawMap(); break; case WM_MBUTTONDOWN: NUM++; if (NUM == 4) NUM = 0; //返回第一张图 //重新开始游戏 GameInit(); //游戏初始化 DrawMap(); //渲染地图 break; case WM_KEYDOWN: if (msg.vkcode == VK_ESCAPE) //按Esc键返回封面 { start(); break; } } }
九.通关判断
//通关判断函数void Judge(){ //判断当前每张图片是否在对应位置 if (map[0][0] == 0 && map[0][1] == 1 && map[0][2] == 2 && map[1][0] == 3 && map[1][1] == 4 && map[1][2] == 5 && map[2][0] == 6 && map[2][1] ==7 && map[2][2] == 8 ) { //挑战成功之后将全图贴上 putimage(0, 0, &img[NUM++]); //四个关卡都胜利之后退出程序 if (NUM == 4) { MessageBox(GetHWnd(), L"挑战成功", L"Vectory", MB_OK); exit(0); return; } //每过一个关卡判断是否进入下一个关卡 if (MessageBox(GetHWnd(), L"是否进入下一关", L"Vectory", MB_YESNO) == IDYES) { //重新开始游戏 GameInit(); //游戏初始化 DrawMap(); //渲染地图 } //退出游戏 else exit(0); }}
十.完整程序
#include#include #include #include #include #include #pragma comment(lib,"Winmm.lib") using namespace std;constexpr auto N = 3;IMAGE img[4], imgs[9];int aim_c, aim_r;int map[3][3] = { 0 };int NUM = 0;//游戏规则,开始界面设计void start();//封面按钮int rules();//加载资源void init();//游戏数据初始化void GameInit();//游戏渲染void DrawMap();//播放音乐void BGM();//玩家操作void play();//判断输赢void Judge();int main(){ //设置窗口大小 initgraph(6 * 100, 6 * 100); //设置图片 start(); init(); GameInit(); DrawMap(); while (1) { play(); Judge(); } system("pause");//等待用户按键 closegraph(); return 0;}//开始界面void start(){ loadimage(NULL, L"cover.jpg"); setbkmode(TRANSPARENT); settextcolor(BLACK); settextstyle(60, 0, _T("楷体"),0,0,4,false,false,false); outtextxy(180, 120, L"拼图游戏"); //游戏名称 settextstyle(30, 0, _T("微软雅黑")); setfillcolor(BROWN); setlinestyle(BS_SOLID, 5); setlinecolor(RED); fillroundrect(220, 220, 370, 270, 10, 10); settextstyle(30, 0, _T("宋体"), 0, 0, 6, false, false, false); //开始按钮 outtextxy(270, 230, L"开始"); fillroundrect(220, 300, 370, 350, 10, 10); outtextxy(240, 310, L"游戏规则"); setfillcolor(BROWN); setlinestyle(BS_SOLID, 5); setlinecolor(BLACK); fillcircle(490, 440, 30); //音乐控制按钮:开 fillcircle(560, 440, 30); //音乐控制按钮:关 outtextxy(380, 430, L"音乐:"); setfillcolor(BLACK); POINT pts[] = { {481,425},{481,455},{507,440} }; fillpolygon(pts, 3); fillrectangle(546, 425, 554, 455); fillrectangle(566, 425, 574, 455); rules();}//游戏初始化void init(){ //加载资源图片,4张图4个关卡 loadimage(&img[0], L"picture1.jpg", 600, 600); loadimage(&img[1], L"picture2.jpg", 600, 600); loadimage(&img[2], L"picture3.jpg", 600, 600); loadimage(&img[3], L"picture4.jpg", 600, 600); //设置最后一张图片为空白图片,作为目标图片 loadimage(&imgs[8], L"white.jpg", 200, 200); //设置随机种子 srand((unsigned)time(NULL));}//封面选项函数int rules(){ ExMessage Mou; //鼠标消息 while (1) { Mou = getmessage(EM_MOUSE); switch (Mou.message) //对鼠标信息进行匹配 { case WM_LBUTTONDOWN: //按下左键 if (Mou.x >= 220 && Mou.x <= 370 && Mou.y >= 300 && Mou.y <= 350) { HWND hwnd = GetHWnd(); MessageBox(NULL, L"1.鼠标左键点击空白图处周围图片交换位置\n2.鼠标右键任意处按下显示参照图片\n3.鼠标中键更换背景图片\n4.按Esc键返回封面", L"游戏规则", MB_OKCANCEL); break; //规则按钮 } if (Mou.x >= 220 && Mou.x <= 370 && Mou.y >= 220 && Mou.y <= 270) { return 0; //开始按钮 } if (Mou.x >= 460 && Mou.x <= 520 && Mou.y >= 410 && Mou.y <= 470) { BGM(); //音乐播放按钮 break; } if (Mou.x >= 530 && Mou.x <= 590 && Mou.y >= 410 && Mou.y <= 470) { mciSendString(L"close back", 0, 0, 0); //音乐关闭按钮 break; } } } }//拼图构造函数void GameInit(){ //把拼图贴上去 putimage(0, 0, &img[NUM]); //设置绘图目标为img对象 对拼图图片进行切割 SetWorkingImage(&img[NUM]); for (int y = 0, n = 0; y < N; y++) { for (int x = 0; x < N; x++) { if (n == 8) break; //获取100*100像素图片,存储在img中; getimage(&imgs[n++], x * 200, y * 200, (x + 1) * 200, (y + 1) * 200); } } //设置绘图目标为绘图窗口 SetWorkingImage(); //初始化地图0~15 for (int i = 0, k = 0; i < N; i++) { for (int j = 0; j < N; j++) { map[i][j] = k++; } } //打乱地图 for (int k = 0; k <= 1000; k++) { //得到目标所在的行和列 for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { if (map[i][j] == 8) //空白图片作为交换目标 { aim_r = i; aim_c = j; break; } } } //一千次打乱顺序之后需要将空白图片转移到右下角 //可以封装成函数下面这个代码 if (k == 1000) { //将空白图片循环转移到右下角 while (aim_r < 2) { //保证空白目标在最下 map[aim_r][aim_c] = map[aim_r + 1][aim_c]; map[aim_r + 1][aim_c] = 8; aim_r++; } while (aim_c < 2) { //保证空白目标在最右 map[aim_r][aim_c] = map[aim_r][aim_c + 1]; map[aim_r][aim_c + 1] = 8; aim_c++; } return; } int dir = rand() % 4; //随机一个方向 switch (dir) { case 0: //向上交换 if (aim_r >= 1) { //空白图片和空白处上面的图片交换 map[aim_r][aim_c] = map[aim_r - 1][aim_c]; map[aim_r - 1][aim_c] = 8; break; } case 1: //向下交换 if (aim_r < 2) { //空白图片和空白处下面的图片交换 map[aim_r][aim_c] = map[aim_r + 1][aim_c]; map[aim_r + 1][aim_c] = 8; break; } case 2: //向左交换 if (aim_c >= 1) { //空白图片和空白处左边的图片交换 map[aim_r][aim_c] = map[aim_r][aim_c - 1]; map[aim_r][aim_c - 1] = 8; break; } case 3: //向右交换 if (aim_c < 2) { //空白图片和空白处右边的图片交换 map[aim_r][aim_c] = map[aim_r][aim_c + 1]; map[aim_r][aim_c + 1] = 8; break; } } }}//绘图函数void DrawMap(){ FlushBatchDraw(); //开始渲染图片 for (int y = 0; y < N; y++) { for (int x = 0; x < N; x++) { putimage(x * 200, y * 200, &imgs[map[y][x]]); } } EndBatchDraw();}//背景音乐函数void BGM(){ //打开音乐,播放音乐 mciSendStringW(L"open ./Thrills.mp3 alias back", NULL, 0, NULL); mciSendStringW(_T("play back repeat"), 0, 0, 0);}//数据更新函数void play(){ int col, row; //鼠标点击的位置 ExMessage msg; //鼠标消息 msg = getmessage(EM_MOUSE|EM_KEY); //获取鼠标消息 switch (msg.message) //对鼠标消息进行匹配 { case WM_LBUTTONDOWN: //当鼠标消息是左键按下时 //获取鼠标按下所在列 col = msg.x / 200; if (msg.x == 600) col = 2; //获取鼠标按下所在行 row = msg.y / 200; if (msg.y == 600) row = 2; //得到目标所在行和列 for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { if (map[i][j] == 8) //空白处为交换目标 { aim_r = i; aim_c = j; } } } //判断鼠标点击位置和目标是否相邻,相邻交换数据 if (row == aim_r && col == aim_c + 1 || row == aim_r && col == aim_c - 1 || row == aim_r + 1 && col == aim_c || row == aim_r - 1 && col == aim_c) { //鼠标点击图片和空白目标图片交换 map[aim_r][aim_c] = map[row][col]; map[row][col] = 8; } DrawMap(); break; case WM_RBUTTONDOWN: //当鼠标消息是右键按下时 putimage(0, 0, &img[NUM]); //将关卡图片贴到窗口上 break; case WM_RBUTTONUP: //当鼠标消息是右键抬起时 DrawMap(); break; case WM_MBUTTONDOWN: NUM++; if (NUM == 4) NUM = 0; //返回第一张图 //重新开始游戏 GameInit(); //游戏初始化 DrawMap(); //渲染地图 break; case WM_KEYDOWN: if (msg.vkcode == VK_ESCAPE) //按Esc键返回封面 { start(); break; } } }//通关判断函数void Judge(){ //判断当前每张图片是否在对应位置 if (map[0][0] == 0 && map[0][1] == 1 && map[0][2] == 2 && map[1][0] == 3 && map[1][1] == 4 && map[1][2] == 5 && map[2][0] == 6 && map[2][1] ==7 && map[2][2] == 8 ) { //挑战成功之后将全图贴上 putimage(0, 0, &img[NUM++]); //四个关卡都胜利之后退出程序 if (NUM == 4) { MessageBox(GetHWnd(), L"挑战成功", L"Vectory", MB_OK); exit(0); return; } //每过一个关卡判断是否进入下一个关卡 if (MessageBox(GetHWnd(), L"是否进入下一关", L"Vectory", MB_YESNO) == IDYES) { //重新开始游戏 GameInit(); //游戏初始化 DrawMap(); //渲染地图 } //退出游戏 else exit(0); }}
以上是"如何使用C++语言实现拼图游戏"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!
图片
鼠标
空白
目标
音乐
函数
消息
关卡
按钮
绘图
地图
封面
所在
数据
位置
规则
j++
成功
图贴
游戏规则
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
软件开发用服费的账务处理
浙江什么是网络技术工程
试题库软件开发协议书
海南省网络安全攻防演练wp
架设导入数据库是什么意思
杭州华天网络技术有限公司
嵌入式软件开发 工作描述
手机版我的世界战墙服务器
浪潮云服务器世界排行
数据库 随机读写 顺序读写
搭建网络安全性
限定数据库查询个数的关键字
联想服务器厂家服务至上
监狱网络技术的是警察吗
建筑物最多的服务器
怎么入侵服务器
通达信手机版数据库安装
服务器主板没有声卡怎么出声
网络安全与执法体检
软件开发运营需要多少钱
建立网站需要几个服务器
java更新数据库记录
查看oracle数据库
竞选网络技术骨干稿
网络安全及隐私
软件开发师的专业倾向
广电网络技术员工个人总结
ourplay服务器链接错误
数据库和js交互
成都理工大学网络安全宿舍