如何使用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安全错误
数据库的锁怎样保障安全
网络安全教案幼儿园小班
教育部发布的网络安全
东西湖网络安全学院招聘
南通凌科网络技术
软件开发退出壁垒
浙江筱满互联网科技
网络安全语 句
系统学习数据库需要什么书
达梦数据库 字段更新成当前时间
计算机网络技术专业专升本
服务器运营商设置
r320服务器风扇拆卸
我的世界网易版土豆服务器
迪士尼数据库疑泄露
百行智学院网络安全
自由职客北京网络技术
黑龙江新一代网络技术推广
湖北仓储生鲜配送软件开发
丽水制造软件开发教程
网络安全手册歌
东南融通数据库工程师
access数据库加密
吉林省创意网络技术有限公司
软件开发谈判策略
软件开发选取适宜的开发模型
软件开发vt测试
河北联通沧州dns服务器地址
南京大学网络安全学院排名
思科网络安全章节考试
同一个网段两个dhcp服务器