走迷宫(未实现通关版)

本文改编自原作者:

【C / EasyX】随机迷宫生成和路径搜索(DFS)_easyx 路径搜索-CSDN博客

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <graphics.h>
using  namespace std;
clock_t Start_time;
clock_t End_time;
//以下是 宏定义参数 //
#define WIDTH 1280                      // 窗体宽度
#define HEIGHT 720                      // 窗体高度
#define MAZE_WIDTH 30*40                    // 迷宫宽度
#define MAZE_HEIGHT 40*40                   // 迷宫高度
#define B_WIDTH 10                          // 格子宽度
#define X 55                                // 迷宫列数 
#define Y 26                                // 迷宫行数 
#define N X*2+1                             // 迷宫数组列数 
#define M Y*2+1                             // 迷宫数组行数 
#define L (N-1)*(M-1)                       // 迷宫路径长度
#define LX 80                               // 起点坐标X
#define LY 50                               // 起点坐标Y
#define BLOCK RGB(255,194,76)             // 墙壁颜色
#define GRAY RGB(123,72,55)               // 阴影颜色
#define GROUND RGB(50,50,50)              // 地面颜色
#define ROOT RGB(235,51,36)             // 路径颜色
#define LINE WHITE        // 路径线颜色
//以下是  函数声明  //
float GetFPS();                             // 计算画面FPS(每秒帧数)
void Delay(DWORD ms);                       // 绝对延时
bool IsInRect(int x, int y, RECT r);          // 是否在矩形内
void InitMaze();                            // 初始化迷宫数组
void OutputMaze();                          // 输出迷宫
void CopyScreenBuffer();                    // 复制屏幕到缓存
void DrawScreenBuffer();                    // 绘制缓存到屏幕
void OutPutPath();                          // 输出路径连线
void DrawFPS();                             // 输出帧数
int Move(int d, int x, int y);                // 向指定方向移动,返回是否成功移动
void DFS_CreateMaze(int x, int y);           // 深度优先生成迷宫
void FindPath(int i, int j);                 // 深度优先搜索迷宫路径
void CreateMaze();                          // 创建迷宫
void DrawMenuItems();                       // 绘制菜单按钮
//以下是全局变量定义//
DWORD* p_Screen;                                // 显存指针
DWORD buff_Screen[WIDTH * HEIGHT];        // 显示缓存
int isShowFPS = 1;                                // 是否显示帧数
int isShowMazePath = 0;                           // 显示迷宫路径
int Maze[M][N];                                 // 迷宫数组   0 普通通路 1 墙 2 路径点 3 起点 4 终点
int path_x[10000][L], path_y[10000][L];            // 路径坐标
int length[L];                                  // 路径搜索长度
int lengtha, count;                              // 搜索计数
int mouseX;                                     // 鼠标位置坐标X
int mouseY;                                     // 鼠标位置坐标Y
bool isMouseDown;                               // 鼠标按下
int start_x, start_y, end_x, end_y;                // 起点坐标 终点坐标
int temp_d;                                     // 上一步走的方向
int Move_flag;                                  // 移动标记
int time_1;
char str[1000];
//以下是辅助功能函数
// 计算画面FPS(每秒帧数)
float GetFPS()
{
#define FPS_COUNT 8
    static int num = 0;
    static DWORD oldTime = GetTickCount();
    static float fps;
    if (num > FPS_COUNT)
    {
        num = 0;
        int newTime = GetTickCount();
        int elapsedTime = newTime - oldTime;
        fps = FPS_COUNT / (elapsedTime / 1000.0f);
        oldTime = newTime;
    }
    num++;
    return fps;
}

// 绝对延时
void Delay(DWORD ms)
{
    static DWORD oldTime = GetTickCount();
    while (GetTickCount() - oldTime < ms)
        Sleep(1);
    oldTime = GetTickCount();
}

// 是否在矩形内
bool IsInRect(int x, int y, RECT r)
{
    if ((x >= r.left && x <= r.right) && (y >= r.top && y <= r.bottom)) return true;
    else return false;
}

// 初始化迷宫数组 
void InitMaze() {
    for (int i = 0; i < M; i++) {
        for (int j = 0; j < N; j++) {
            Maze[i][j] = 1;
        }
    }
    // 设置起点和终点
    Maze[1][0] = 3;
    Maze[M - 2][N - 1] = 4;
}

// 输出迷宫 
void OutputMaze() {
    // 清屏
    setcolor(RGB(255, 255, 255));
    setfillcolor(RGB(255, 255, 255));
    fillrectangle(0, 0, WIDTH, HEIGHT);
    for (int i = 0; i < M; i++) {
        for (int j = 0; j < N; j++) {
            int xx = LX + j * B_WIDTH;
            int yy = LY + i * B_WIDTH;
            switch (Maze[i][j]) {
            case 0:
                setcolor(GROUND);
                setfillcolor(GROUND);
                fillrectangle(xx, yy, xx + B_WIDTH, yy + B_WIDTH);
                break;
            case 1:
                setcolor(BLOCK);
                setfillcolor(BLOCK);
                fillrectangle(xx, yy, xx + B_WIDTH, yy + B_WIDTH);
                if (Maze[i][j] == 1 && (i == M - 1 || Maze[i + 1][j] != 1))
                {
                    setcolor(GRAY);
                    setfillcolor(GRAY);
                    fillrectangle(xx, yy + B_WIDTH / 2, xx + B_WIDTH, yy + B_WIDTH);
                }
                break;
            case 2:
                setcolor(GROUND);
                setfillcolor(GROUND);
                fillrectangle(xx, yy, xx + B_WIDTH, yy + B_WIDTH);
                break;
            case 3:
                setcolor(GROUND);
                setfillcolor(GROUND);
                fillrectangle(xx, yy, xx + B_WIDTH, yy + B_WIDTH);
                break;
            case 4:
                setcolor(GROUND);
                setfillcolor(GROUND);
                fillrectangle(xx, yy, xx + B_WIDTH, yy + B_WIDTH);
                break;
            }
        }
    }


}

// 复制屏幕到缓存
void CopyScreenBuffer()
{
    for (int i = 0; i < WIDTH * HEIGHT; i++)
    {
        buff_Screen[i] = p_Screen[i];
    }
}

// 绘制缓存到屏幕
void DrawScreenBuffer()
{
    for (int i = 0; i < WIDTH * HEIGHT; i++)
    {
        p_Screen[i] = buff_Screen[i];
    }
    //计时器
    End_time = clock();
    time_1 = (int)((End_time - Start_time) / CLOCKS_PER_SEC);
    settextstyle(50, 0, "黑体");
    setcolor(BLACK);
    sprintf_s(str, "游戏时间:%d s", time_1);
    outtextxy(10, 10, str);


}

// 输出帧数
void DrawFPS()
{
    //输出帧数
    if (isShowFPS)
    {
        setcolor(RED);
        settextstyle(15, 0, _T("黑体"));
        TCHAR  s[5];
#if _MSC_VER > 1200
        _stprintf_s(s, _T("%.1f"), GetFPS());
#else
        _stprintf(s, _T("%.1f"), GetFPS());
#endif
        outtextxy(4, 2, _T("FPS:"));
        outtextxy(34, 2, s);
    }
}

// 输出路径连线
void OutPutPath()
{
    if (isShowMazePath)
    {
        for (int i = 0; i < length[0] - 1; i++)
        {
            setcolor(LINE);
            int x1 = path_x[0][i] * B_WIDTH + B_WIDTH / 2 + LX;
            int x2 = path_x[0][i + 1] * B_WIDTH + B_WIDTH / 2 + LX;
            int y1 = path_y[0][i] * B_WIDTH + B_WIDTH / 2 + LY;
            int y2 = path_y[0][i + 1] * B_WIDTH + B_WIDTH / 2 + LY;
            line(x1, y1, x2, y2);
        }
    }
}

// 向指定方向移动,返回是否成功移动
int Move(int d, int x, int y)
{
    switch (d)
    {
        // 向上
    case 0: {
        if (Maze[y - 3][x] > 0 && Maze[y - 2][x - 1] > 0 && Maze[y - 2][x + 1] > 0 && y - 2 > 0)
        {
            Maze[y - 2][x] = 0;
            Maze[y - 1][x] = 0;
            Move_flag = 1;
            temp_d = 0;
            DFS_CreateMaze(x, y - 2);
        }
        break;
    }
          // 向下
    case 1: {
        if (Maze[y + 3][x] > 0 && Maze[y + 2][x - 1] > 0 && Maze[y + 2][x + 1] > 0 && y + 2 < M)
        {
            Maze[y + 2][x] = 0;
            Maze[y + 1][x] = 0;
            Move_flag = 1;
            temp_d = 1;
            DFS_CreateMaze(x, y + 2);
        }
        break;
    }
          // 向左
    case 2: {
        if (Maze[y][x - 3] > 0 && Maze[y - 1][x - 2] > 0 && Maze[y + 1][x - 2] > 0 && x - 2 > 0)
        {
            Maze[y][x - 1] = 0;
            Maze[y][x - 2] = 0;
            Move_flag = 1;
            temp_d = 2;
            DFS_CreateMaze(x - 2, y);
        }
        break;
    }
          // 向右
    case 3: {
        if (Maze[y][x + 3] > 0 && Maze[y - 1][x + 2] > 0 && Maze[y + 1][x + 2] > 0 && x + 2 < N)
        {
            Maze[y][x + 1] = 0;
            Maze[y][x + 2] = 0;
            Move_flag = 1;
            temp_d = 3;
            DFS_CreateMaze(x + 2, y);
        }
        break;
    }
    }
    return Move_flag;
}// 深度优先生成迷宫
// 深度优先生成迷宫
void DFS_CreateMaze(int x, int y)
{
    //置通路
    Maze[y][x] = 0;
    //随机方向
    int d = rand() % 4;
    int direct = temp_d;
    int t[4] = { 0,0,0,0 };// 已走方向标记
    Move_flag = 0;// 重置移动标记
    // 保证随机性的同时走满地图
    while (t[0] != 1 || t[1] != 1 || t[2] != 1 || t[3] != 1)
    {
        int i = rand() % 4;
        if (t[i] != 1)
        {
            t[i] = 1;
            Move(i, x, y);
        }
    }
}
// 深度优先搜索迷宫路径
void FindPath(int x, int y)
{
    // 置路径
    Maze[y][x] = 2;
    path_x[count][lengtha] = x;
    path_y[count][lengtha] = y;
    lengtha++;
    // 搜索到目的地
    if (x == end_x && y == end_y)
    {
        //success=1;
        length[count] = lengtha;
        count++;
        if (count > 0)
        {
            // 复制上一次的路径到下一次待搜索路径中
            for (int i = 0; i < length[count - 1]; i++)
            {
                path_x[count][i] = path_x[count - 1][i];
                path_y[count][i] = path_y[count - 1][i];
            }
        }
    }
    else
    {
        // 搜索并回溯
        if (Maze[y][x + 1] == 0) { FindPath(x + 1, y); Maze[y][x + 1] = 0; lengtha--; }
        if (Maze[y + 1][x] == 0) { FindPath(x, y + 1); Maze[y + 1][x] = 0; lengtha--; }
        if (Maze[y][x - 1] == 0) { FindPath(x - 1, y); Maze[y][x - 1] = 0; lengtha--; }
        if (Maze[y - 1][x] == 0) { FindPath(x, y - 1); Maze[y - 1][x] = 0; lengtha--; }
    }
    //if(success!=1)
    //return success;
}
// 创建迷宫
void CreateMaze()
{
    // 初始化迷宫数组
    InitMaze();
    isShowMazePath = 0;
    // 从终点开始逆向生成迷宫
    start_x = 1;
    start_y = 1;
    end_x = N - 2;
    end_y = M - 2;
    DFS_CreateMaze(end_x, end_y);
    // 搜索路径
    lengtha = 0;
    count = 0;
    FindPath(start_x, start_y);
    // 结果路径复制到地图
    for (int i = 0; i < length[0]; i++)
    {
        Maze[path_y[0][i]][path_x[0][i]] = 2;
    }
}
// 绘制菜单按钮
void DrawMenuItems()
{
    RECT r;
    r.left = 860;
    r.top = 610;
    r.right = r.left + 90;
    r.bottom = r.top + 38;
    setcolor(RGB(50, 50, 50));
    if (IsInRect(mouseX, mouseY, r))
    {
        setfillcolor(RGB(220, 220, 220));
        // 生成迷宫按键响应
        if (isMouseDown)
        {
            // 创建迷宫
            CreateMaze();
            // 绘制一次到屏幕并复制到缓存
            OutputMaze();
            CopyScreenBuffer();
            isMouseDown = 0;
        }
    }
    else setfillcolor(RGB(240, 240, 240));
    fillrectangle(r.left, r.top, r.right, r.bottom);
    settextstyle(25, 9, _T("Verdana"));
    setcolor(RGB(60, 60, 60));
    outtextxy(r.left + 5, r.top + 5, _T(" 生成迷宫"));
    r.left = 1020;
    r.top = 610;
    r.right = r.left + 90;
    r.bottom = r.top + 38;
    setcolor(RGB(50, 50, 50));
    if (IsInRect(mouseX, mouseY, r))
    {
        setfillcolor(RGB(220, 220, 220));
        // 显示/隐藏路径
        if (isMouseDown)
        {
            isShowMazePath = !isShowMazePath;
            isMouseDown = 0;
        }
    }
    else setfillcolor(RGB(240, 240, 240));
    fillrectangle(r.left, r.top, r.right, r.bottom);
    settextstyle(25, 9, _T("Verdana"));
    setcolor(RGB(60, 60, 60));
    if (isShowMazePath) outtextxy(r.left + 5, r.top + 5, _T(" 隐藏路径"));
    else outtextxy(r.left + 5, r.top + 5, _T(" 显示路径"));
}
// 主函数
int main() {
    // 置随机数种子 
    srand(unsigned(time(NULL)));
    // 初始化设备,加载图片
    initgraph(WIDTH, HEIGHT);
    // 设置窗口标题
    SetWindowText(GetHWnd(), _T("Maze v0.9 By:ls9512"));
    cleardevice();
    // 设置黑色背景
    setbkmode(TRANSPARENT);
    settextcolor(BLACK);
    // 开启双缓冲,防止闪屏
    BeginBatchDraw();
    // 鼠标消息变量
    MOUSEMSG mmsg;
    // 获取显存指针
    p_Screen = GetImageBuffer();
    // 创建迷宫
    CreateMaze();
    // 绘制一次到屏幕并复制到缓存
    OutputMaze();
    CopyScreenBuffer();
    // 主循环
    Start_time = clock();
    while (true)
    {
        
        //处理鼠标消息
        while (MouseHit())
        {
            mmsg = GetMouseMsg();
            switch (mmsg.uMsg)
            {
            case WM_MOUSEMOVE:  mouseX = mmsg.x; mouseY = mmsg.y; break;
            case WM_LBUTTONDOWN: isMouseDown = true; break;
            case WM_LBUTTONUP: isMouseDown = false; break;
            }

        }
        
        // 绘制,将缓存数据复制到屏幕提速
        DrawScreenBuffer();
        OutPutPath();
        DrawMenuItems();
        DrawFPS();
      
        // 显示缓存的绘制内容
        FlushBatchDraw();
        // 延迟,帧数控制
        Sleep(5);
    }
    // 关闭
    EndBatchDraw();
    system("pause");
    return 0;
}

  • 13
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值