千家信息网

如何使用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++语言实现拼图游戏"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

0