在好例子网,分享、交流、成长!
您当前所在位置:首页C/C++ 开发实例C/C++游戏开发 → 四邻游戏(拼图)

四邻游戏(拼图)

C/C++游戏开发

下载此实例
  • 开发语言:C/C++
  • 实例大小:0.03M
  • 下载次数:0
  • 浏览次数:14
  • 发布时间:2025-06-09
  • 实例类别:C/C++游戏开发
  • 发 布 人:zlzfc
  • 文件格式:.zip
  • 所需积分:0
 相关标签: 游戏

实例介绍

【实例简介】

 每块拼图分割成上下左右四个部分,要求相邻两块拼图对应的上下或左右部分的数字
 颜色一致,边缘不考虑,最后完整拼接。
 开发环境 vs2022 easyx
 项目->属性->高级->字符集 该成多字节字符集
 制作日期 2025年6月8日
 技巧 黑色的数字位置是在地图的边缘的。

【实例截图】

【核心代码】

// 四邻游戏,玩法是数字拼图,
// 每块拼图分割成上下左右四个部分,要求相邻两块拼图对应的上下或左右部分的数字
// 颜色一致,边缘不考虑,最后完整拼接。
// 开发环境 vs2022 easyx
// 项目->属性->高级->字符集 该成多字节字符集
// 制作日期 2025年6月8日
// 技巧 黑色的数字位置是在地图的边缘的。
#include <graphics.h>
#include <conio.h>
#include <time.h>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
int mapsize = 4; //地图尺寸
IMAGE memImage;
// 定义颜色常量
const int COLORS[5] = { BLACK, RED, GREEN, BLUE, LIGHTMAGENTA };
const int COLOR_COUNT = 5;
const int  mtop=50,mbuttom=50;//地图四边留白
//自定义按钮类
class Button
{
public:
    Button(int a,   const char *t) : x(a)
    {
        // 计算字符串长度
        int len = _tcslen(t) 1;
        // 分配内存并复制字符串
        text = new TCHAR[len];
        _tcscpy_s(text, len, t);
    }
    ~Button()
    {
        // 释放内存
        delete[] text;
    }
    bool isClicked(int mx, int my) {
        int y = mtop mapsize  * 100 mbuttom/2;
        return (mx >= x - 30 && mx <= x 30 && my >= y - 20 && my <= y 20);
    }
    void mousemove(int mx, int my) {
        int y = mtop mapsize * 100 mbuttom/2;
        selected= (mx >= x - 30 && mx <= x 30 && my >= y - 20 && my <= y 20);
    }
    void draw()
    {
        int y =mtop mapsize * 100 mbuttom/2;
        setlinecolor(BLACK);
        if (selected) {
            setfillcolor(LIGHTGRAY);
            settextcolor(RED);
        }
        else {
            setfillcolor(WHITE);
            settextcolor(BLUE);
        }
        fillrectangle(x -30, y - 20, x 30, y 20);
        outtextxy(x-20, y-15 , text);
    }
 
public:
    int x; // 按钮的X坐标 Y坐标通过计算得出
    LPTSTR text; // 按钮文本
    bool selected=false; // 是否被选中
};


// 拼图块类
class PuzzlePiece {
public:
    int top, right, bottom, left;  // 上右下左四个方向的数字颜色索引
    int x, y;                      // 拼图块在屏幕上的位置
    int gridX, gridY;              // 拼图块在网格中的位置
    bool isPlaced;                 // 是否已经放置在正确位置
    bool mousemove = false;        // 是否有鼠标划过
public:
    PuzzlePiece(int t, int r, int b, int l, int gx, int gy)
        : top(t), right(r), bottom(b), left(l), gridX(gx), gridY(gy) {
        x = gx * 100 50;
        y = gy * 100 50 mtop;
        isPlaced = false;
    }

    // 绘制拼图块
    void draw(bool selected = false) {
        // 绘制边框
        if (selected) {
            setfillcolor(LIGHTGREEN);
        }
        else if (mousemove) {
            setfillcolor(LIGHTGRAY);
        }
        else if (isPlaced) {
            setfillcolor(LIGHTCYAN);
        }
        else {
            setfillcolor(WHITE);
        }
        // 绘制四个方向的数字
        setbkmode(TRANSPARENT); // 设置字体背景为透明
        settextstyle(24, 0, _T("黑体")); // 设置字体
        setlinecolor(BLACK);
        setlinestyle(PS_SOLID, 3);
        fillrectangle(x - 45, y - 45, x 45, y 45);
        // 绘制四个方向的数字
        settextcolor(COLORS[top]);
        outtextxy(x, y - 30, '0' top 1);

        settextcolor(COLORS[right]);
        outtextxy(x 30, y, '0' right 1);

        settextcolor(COLORS[bottom]);
        outtextxy(x, y 20, '0' bottom 1);

        settextcolor(COLORS[left]);
        outtextxy(x - 30, y, '0' left 1);

    }

  
};

// 游戏类
class PuzzleGame {
private:
    PuzzlePiece ** pieces;     // 拼图块集合
    int rows, cols;                 // 网格行数和列数
    int selectedIndex;              // 当前选中的拼图块索引
    bool isWin;                  // 游戏是否结束
    int moves;                      // 移动次数
public:

    PuzzleGame(int r, int c) : rows(r), cols(c), selectedIndex(-1), isWin(false), moves(0) 
    {
        initPieces();
        shufflePieces();
    }
    ~PuzzleGame(){
        for (int i = 0; i < rows * cols; i) {
            delete pieces[i];  // 释放每行
        }
        delete[] pieces;
    }
  
    // 初始化拼图块
    void initPieces() {
        // 创建正确的拼图
        pieces = new PuzzlePiece*[rows*cols];
        for (int y = 0; y < rows; y ) {
            for (int x = 0; x < cols; x ) {
                // 计算四个方向的颜色索引
                int top = (y == 0) ? 0 : (1 rand() % (COLOR_COUNT - 1));  // -1表示边缘
                int right = (x == cols - 1) ? 0 : (1 rand() % (COLOR_COUNT - 1));
                int bottom = (y == rows - 1) ? 0 : (1 rand() % (COLOR_COUNT - 1));
                int left = (x == 0) ? 0 : (1 rand() % (COLOR_COUNT - 1));
                pieces[y * cols x] = new PuzzlePiece(top, right, bottom, left, x, y);
                // 确保相邻块颜色匹配
                if (x > 0) {
                    pieces[y * cols x ]->left = pieces[y * cols x - 1]->right;
                }
                if (y > 0) {
                    pieces[y* cols x]->top = pieces[(y - 1) * cols x]->bottom;
                }
              
            }
            
        }

    }

    // 打乱拼图块位置
    void shufflePieces() {
       
        for (int y = 0; y < rows; y ) {
            for (int x = 0; x < cols; x ) {
                int r = rand() % (rows*cols);
                swapPieces(y*cols x,r);
            }
        }
       
    }

    // 绘制游戏界面
    void draw() 
    {
        // 绘制标题
        settextcolor(BLACK);
        settextstyle(24, 0, _T("宋体"));
        outtextxy(10, 10, _T("数字拼图游戏"));
        char info[50];
        sprintf_s(info, "移动次数: %d", moves);
        outtextxy(200, 10,(LPCTSTR)info);

        // 绘制所有拼图块
        for (size_t i = 0; i < rows*cols; i ) 
        {
            pieces[i]->draw(i == selectedIndex);
        }

        // 游戏结束提示
        if (isWin) 
        {
            setfillcolor(RGB(0, 128, 0));
            fillrectangle(100, 100, 400, 200);
            settextcolor(WHITE);
            settextstyle(36, 0, _T("宋体"));
            outtextxy(150, 130, _T("恭喜完成!"));
            settextstyle(24, 0, _T("黑体"));
        }
    }
    // 鼠标移动到该方块颜色变成灰色
    void mousemove(int mx, int my) 
    {
        int gx = mx / 100;
        int gy = (my - mtop) / 100;
        int gx1 = mx % 100;
        int gy1 = (my - mtop) % 100;
        // 检查是否点击了拼图块
        for (int i = 0; i < rows * cols; i ) pieces[i]->mousemove = false;
        if (gx >= 0 && gx < rows && gy >= 0 && gy < cols && gx1 > 5 && gx1 < 95 && gy1>5 && gy1 < 95)
        {
               int r = gy * cols gx;
                pieces[r]->mousemove = true;
        }
           
    }

    // 处理鼠标点击方块 选中后颜色变成绿色
    void handleClick(int mx, int my) {
        if (isWin) return;
        int gx = mx/ 100;
        int gy = (my-mtop)/ 100;
        int gx1 = mx %100;
        int gy1 = (my - mtop) % 100;
        // 检查是否点击了拼图块
        if (gx >= 0 && gx < rows && gy >= 0 && gy < cols && gx1>5&&gx1<95 && gy1>5 && gy1 < 95)
        {
            int r = gy * cols gx;
            if (selectedIndex == -1) {
                // 如果没有选中的拼图块,选中当前点击的
                selectedIndex = r;
            }
            else if (selectedIndex != (int)r) {
                // 如果已经有选中的拼图块,尝试交换位置
                swapPieces(selectedIndex, r);
                selectedIndex = -1;
                moves ;
                checkWin();
            }
            return;
        }
        else
        // 如果点击了空白处,取消选择
        selectedIndex = -1;
        return;
    }

    // 交换两个拼图块的位置
    void swapPieces(int i, int j) 
    {
        int top = pieces[i]->top ;  // -1表示边缘
        int right = pieces[i]->right;
        int bottom = pieces[i]->bottom;
        int left = pieces[i]->left;
        pieces[i]->top = pieces[j]->top;
        pieces[i]->bottom = pieces[j]->bottom;
        pieces[i]->left = pieces[j]->left;
        pieces[i]->right = pieces[j]->right;
        pieces[j]->top = top;
        pieces[j]->bottom = bottom;
        pieces[j]->left =left;
        pieces[j]->right =right;
      
    }

    // 检查拼图块是否放置正确, 正确放置的方块变成蓝色
    void checkPiecePlacement(int index) {
        PuzzlePiece * piece = pieces[index];
        int gx = piece->gridX;
        int gy = piece->gridY;
        // 检查周围四个方向的拼图块
        bool match = true;

        // 上方
        if (gy > 0) {
            if (!(pieces[index-cols]->bottom== pieces[index]->top))
            {
                match = false;
                goto enn;
            }
            
        }
        // 下方
        if (gy < rows - 1) 
        {
            if (!(pieces[index cols]->top == pieces[index]->bottom))
            {
                match = false;
                goto enn;
            }
        }
        // 左方
        if (gx > 0) {
            if (!(pieces[index -1]->right == pieces[index]->left))
            {
                match = false;
                goto enn;
            }
        }
        // 右方
        if (gx < cols - 1) {
            if (!(pieces[index 1]->left == pieces[index]->right))
            {
                match = false;
                goto enn;
            }
        }
    enn:
        piece->isPlaced = match;
    }

    // 检查游戏是否获胜
    bool checkWin() {
        isWin = true;
        for (size_t i = 0; i < cols*rows; i ) {
            checkPiecePlacement(i);
            if (!pieces[i]->isPlaced)
            {
                isWin = false;
            }
        }
        return isWin;
    }

    // 重新开始游戏
    void restart(int size) 
    {
        for (int i = 0; i < rows*cols; i) {
            delete pieces[i];  // 释放每行
        }
        delete[] pieces;
        rows=cols=mapsize = size;
        closegraph();
        initgraph(mapsize * 100, mapsize * 100 mtop mbuttom);
        memImage.Resize(mapsize* 100, mapsize * 100 mtop mbuttom);
        selectedIndex = -1;
        isWin = false;
        moves = 0;
        initPieces();
        shufflePieces();
        checkWin();
    }
};

WNDPROC g_OriginWndProc = NULL;
bool gameover=false;
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    if (uMsg == WM_CLOSE) {
        gameover = true;
    }
    else {
        LRESULT result = CallWindowProc((WNDPROC)g_OriginWndProc, hwnd, uMsg, wParam, lParam);
        return result;
    }
}

int main() {
    // 初始化随机数种子
    srand((unsigned)time(NULL));
    // 创建游戏窗口
    HWND hwnd=initgraph(mapsize*100, mapsize* 100 mtop mbuttom);
    // 创建内存画布,用于双缓冲绘图
    memImage.Resize(mapsize * 100, mapsize * 100 mtop mbuttom);
    //为了能通过点窗口的X号关闭窗口
    g_OriginWndProc = (WNDPROC)GetWindowLongPtr(hwnd, GWLP_WNDPROC);
    SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)WindowProc);

    // 创建游戏对象 (4x4 拼图)
    PuzzleGame game(mapsize, mapsize);
    game.checkWin();
    Button  s4(100, "4X4");
    Button  s5(200,  "5X5");
    Button  s6(300,  "退出");
    auto print = [&]()
    {
        SetWorkingImage(&memImage); // 设置当前绘图设备为内存画布
        setbkcolor(RGB(240, 240, 240));
        cleardevice();  // 清内存画布
        setbkcolor(RGB(240, 240, 240));   // 在内存画布上绘制游戏界面
        game.draw();       // 设置当前绘图设备回屏幕
        s4.draw();s5.draw(); s6.draw();
        SetWorkingImage();       // 将内存画布上的内容一次性复制到屏幕上
        putimage(0, 0, &memImage);
        Sleep(1); // 延时
    };
    print();
    // 游戏循环
    ExMessage msg;
    while (!gameover)
    {
        int i = -1;
        // 处理消息
        if (peekmessage(&msg, EM_MOUSE | EM_KEY)) {
            switch (msg.message) {
            case WM_LBUTTONDOWN:
                game.handleClick(msg.x, msg.y);
                if(s4.isClicked(msg.x, msg.y))game.restart(4);
                if(s5.isClicked(msg.x, msg.y))game.restart(5);
                if (s6.isClicked(msg.x, msg.y))
                {
                    closegraph();
                    return 0;
                }
                print();
                break;
            case  WM_MOUSEMOVE:
                game.mousemove(msg.x, msg.y);
                s4.mousemove(msg.x, msg.y);
                s5.mousemove(msg.x, msg.y);
                s6.mousemove(msg.x, msg.y);
                print();
                break;
            case WM_KEYDOWN:
                if (msg.vkcode == VK_ESCAPE) {
                    return 0;  // 退出游戏
                }
                break;
            case WM_CLOSE:  // 检测到关闭窗口消息
                closegraph();  // 关闭图形窗口
                return 0;      // 退出程序
            }
        }

    }
    // 关闭图形窗口
    closegraph();
    return 0;
}

标签: 游戏

实例下载地址

四邻游戏(拼图)

不能下载?内容有错? 点击这里报错 + 投诉 + 提问

好例子网口号:伸出你的我的手 — 分享

网友评论

发表评论

(您的评论需要经过审核才能显示)

查看所有0条评论>>

小贴士

感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。

  • 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
  • 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
  • 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
  • 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。

关于好例子网

本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明

;
报警