如何使用C++语言实现拼图游戏
发表于:2025-01-18 作者:千家信息网编辑
千家信息网最后更新 2025年01月18日,小编给大家分享一下如何使用C++语言实现拼图游戏,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!开发环境:Visual St
千家信息网最后更新 2025年01月18日如何使用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安全错误
数据库的锁怎样保障安全
08服务器怎么管理
登陆数据库提示无监听程序
家用计算机网络安全
连接管理服务器
网络安全44条规定是什么
南宁1.5u服务器散热器批发商
齐云服务器
重庆钢板套料软件开发商
高埗软件开发
stme连接服务器
web服务器 空间服务器
武大网络安全学院考研复试名单
分离数据库怎么分离
zigbee用什么软件开发
用数字揭穿网络安全误区
网络安全融资2021
合肥途秀网络技术有限公司
文件如何进入数据库
x86 服务器和 小型机
欧洲杯时间表软件开发
clash服务器端
学习后端服务器需要多久技术
2019军工加网络安全龙头
机关强调网络安全
如何查看服务器共享密码
csgo选不了服务器怎么办
游戏服务器聊天系统
网页mysql数据库
靖江环保网络技术多少钱
网络安全宣传视频教程