数据结构课设 迷宫问题

迷宫是指一个m*n的方格,有些方格可以通过,有些方格为障碍而不能通过,假定有一只老鼠,指定其起始位置和目标位置,老鼠能自动寻找从起始位置到达目标位置的路径。老鼠的行进方向可以是4个或8个。迷宫问题的一个实例如下图所示。编程完成如下任务。
要求:
① 可任意指定迷宫的大小,随机产生可通和障碍方格;
② 可任意指定起始位置和目标位置;
③ 具有编辑迷宫功能,可修改当前迷宫的可通和障碍方格;
④ 计数据格式,用文件存储迷宫信息,从文件读取迷宫信息,然后寻径。
⑤ 编程求解走出迷宫的所有路径;
扩展要求:
⑥ 编程求解走出迷宫的最短路径,假定从一个方格到另一个方格的距离为都为1。

// 迷宫.cpp : 定义控制台应用程序的入口点。
//
#pragma warning(suppress : 4996) 

#include "stdafx.h"
#include <graphics.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>



//
// 定义全局变量
//
BYTE** g_aryMap = NULL;                            // 表示迷宫地图
SIZE    g_szMap;                                    // 迷宫地图的尺寸
SIZE    g_start;                                    //迷宫起点
SIZE    g_end;                                      //迷宫终点
IMAGE    g_imgSight(360, 280);                        // 表示游戏的视野
RECT    g_rtSight;                                    // 游戏的视野的范围
IMAGE    g_imgItem(180, 20);                            // 地图元素
IMAGE    g_imgGPS;                                    // 迷你地图,用于显示游戏者在地图中的位置
POINT    g_ptGPS;                                    // 迷你地图的显示位置
SIZE    g_szGPS;                                    // 迷你地图的尺寸
POINT    g_ptPlayer;                                    // 游戏者的位置
int path_x[1000][1000], path_y[1000][1000];         // 路径坐标
int length[1000];                                   // 路径搜索长度 
bool Maze[1000][1000];                              //求解路径矩阵
int count;                                          //路径的个数

// 枚举地图元素,兼做元素位置的 x 坐标
enum MAPITEM { MAP_WALL = 0, MAP_PLAYER = 20, MAP_GROUND = 40, MAP_MARKRED = 60, MAP_MARKGREEN = 80, MAP_MARKYELLOW = 100, MAP_ENTRANCE = 120, MAP_EXIT = 140, MAP_OUTSIDE = 160 };
// 枚举用户的控制命令
enum CMD { CMD_QUIT = 1, CMD_UP = 2, CMD_DOWN = 4, CMD_LEFT = 8, CMD_RIGHT = 16, CMD_UPWALL = 32, CMD_DOWNWALL = 64, CMD_LEFTWALL = 128, CMD_RIGHTWALL = 256, CMD_PATH = 512, CMD_SHORT = 1024 };



//
// 函数声明
//
void    Welcome();                                      // 绘制游戏界面
void    InitImage();                                  // 初始化游戏图片
void    InitGame();                                      // 初始化游戏数据
void TcharToChar(const TCHAR* tchar, char* _char);  //将TCHAR转为char 
void    GetMazeSize();                                  // 提示用户输入迷宫大小
void    MakeMaze(int width, int height);              // 生成迷宫:初始化(注:宽高必须是奇数)
void    TravelMaze(int x, int y);                      // 生成迷宫:遍历 (x, y) 四周
MAPITEM    GetMazeItem(int x, int y);                      // 获取指定坐标的迷宫元素
void    Paint();                                      // 绘制视野范围内的迷宫
int        GetCmd();                                      // 获取用户输入的命令
void    DispatchCmd(int cmd);                          // 处理用户输入的命令
void    OnUp();                                          // 向上移动
void    OnLeft();                                      // 向左移动
void    OnRight();                                      // 向右移动
void    OnDown();                                      // 向下移动
void    LeftWall();                                   // 向上编辑
void    RightWall();                                  // 向左编辑
void    UpWall();                                     // 向右编辑
void    DownWall();                                   // 向下编辑
void FindPath(int& count, int x, int y, int& lengtha);// 深度优先搜索迷宫路径   
void OutPutPath(int count);                           // 输出路径连线 
void    OUTPATH(int height, int wdith);                  //显示所有路径
void    OUTSHORTPATH();                               //显示最短路径
bool    CheckWin();                                      // 检查是否到出口
bool    Quit();                                          // 询问用户是否退出游戏



//
// 函数定义
//



// 绘制游戏界面
void Welcome()
{
    // 绘制渐变色外框
    for (int i = 0; i < 128; i++)
    {
        setlinecolor(RGB(0, 0, (127 - i) << 1));//线条颜色设置
        rectangle(149 - i, 109 - (i >> 1), 490 + i, 370 + (i >> 1));//画空心矩形 ,>> 右移运算符
    }

    // 设置字体样式
    settextcolor(WHITE);//设置字体颜色为白
    setbkmode(TRANSPARENT);//设置图案填充和文字输出时的背景模式,此时为透明

    // 绘制标题
    settextstyle(36, 0, _T("宋体"));//0表示自动调整位置,36表示字体高度,文字表示子体格式
    outtextxy(248, 40, _T("迷 宫"));//输出文本框

    // 绘制操作说明
    settextstyle(12, 0, _T("宋体"));
    outtextxy(50, 372, _T("控制说明:"));
    outtextxy(74, 390, _T("方向键:移动"));
    outtextxy(74, 408, _T("wsad:更改迷宫通道(如果原来为墙壁,则变为通道,反之变为墙壁)"));
    outtextxy(74, 426, _T("P:显示走出迷宫的所有路径"));
    outtextxy(74, 444, _T("L:显示最短路径(必须先执行P)"));
    outtextxy(74, 462, _T("ESC:退出程序"));
}


// 初始化游戏图片
void InitImage()
{
    // 预绘制游戏图片到 IMAGE 缓存(可以修改为加载图片以获得更好效果)
    loadimage(&g_imgItem, _T("text.jpg"));
    SetWorkingImage(&g_imgItem);
    cleardevice();//清除屏幕内容,用当前背景色清空屏幕,并将当前点移至 (0, 0)
    // 绘制 PLAYER
    setorigin(MAP_PLAYER, 0);
    setfillcolor(BLUE);//设置当前的填充颜色
    setlinecolor(YELLOW); //设置当前画线颜色
    fillellipse(2, 2, 17, 17);//画填充的椭圆(有边框)【左上x,y,右上x,y】
    setlinecolor(BLACK);//划线颜色
    line(7, 7, 7, 8);//划线
    line(12, 7, 12, 8);//划线
    arc(5, 6, 14, 14, 3.34, 6.08);//划椭圆
    // 绘制墙壁
    setorigin(MAP_WALL, 0);//设置坐标原点
    settextcolor(BROWN);//字体颜色
    setfillstyle((BYTE*)"\x20\x20\x20\xff\x04\x04\x04\xff");
    setlinecolor(BROWN);
    solidrectangle(1, 1, 18, 18);
    rectangle(0, 0, 19, 19);
    // 绘制入口
    setorigin(MAP_ENTRANCE, 0);//设置坐标原点
    setlinecolor(GREEN);
    settextstyle(12, 0, _T("宋体"));
    outtextxy(4, 4, _T("IN"));
    // 绘制出口
    setorigin(MAP_EXIT, 0);
    outtextxy(4, 4, _T("OUT"));
    // 绘制迷宫外面的空地
    setorigin(MAP_OUTSIDE, 0);
    settextcolor(GREEN);
    setfillstyle((BYTE*)"\x50\x55\x22\x20\x05\x55\x22\x02");
    solidrectangle(0, 0, 19, 19);//用于画填充矩形(无边框)
    // 恢复坐标系
    setorigin(0, 0);//函数作用设置坐标原点

    // 显示作者
    SetWorkingImage();
    settextcolor(BLUE);
    TCHAR author[] = _T("制作:李家乐");//Tchar为字符类型变量,可用于输出文字
    outtextxy(471, 4, author);
    outtextxy(471, 16, _T("时间:2021.6"));//在指定位置输出字符串
    settextcolor(LIGHTBLUE);//改变字符的颜色,产生字符特效
    outtextxy(470, 3, author);
    outtextxy(471, 15, _T("时间:2021.6"));//在指定位置输出字符串
}


// 初始化游戏数据
void InitGame()
{
    // 提示用户输入迷宫大小以及起点与终点
    GetMazeSize();

    // 初始化参数
    if (g_aryMap != NULL)
    {    // 清理迷宫地图占用的内存
        for (int x = 0; x < g_szMap.cx + 2; x++)
            delete[] g_aryMap[x];
        delete[] g_aryMap;
    }
    MakeMaze(g_szMap.cx, g_szMap.cy);        // 创建迷宫
    g_ptPlayer.x = g_start.cx;                    // 设置游戏者的位置
    g_ptPlayer.y = g_start.cy;
    // 设置视野范围
    if (g_start.cx + 15 < g_szMap.cx && g_start.cx - 2 > 1)
    {
        g_rtSight.left = g_start.cx - 2;
        g_rtSight.right = g_start.cx + 15;
    }
    else
    {
        g_rtSight.left = 0;
        g_rtSight.right = 17;
    }

    if (g_start.cy + 11 < g_szMap.cy && g_start.cy - 2 > 1)
    {
        g_rtSight.top = g_start.cy - 2;
        g_rtSight.bottom = g_start.cy + 11;
    }
    else
    {
        g_rtSight.top = 0;
        g_rtSight.bottom = 13;
    }

    // 设置 GPS 显示区
    setfillcolor(BLUE);
    solidrectangle(522, 368, 637, 471);//画填充矩形
    if (g_szMap.cx > g_szMap.cy) { g_szGPS.cx = 100; g_szGPS.cy = (int)(100.0 * g_szMap.cy / g_szMap.cx + 0.5); }
    else { g_szGPS.cy = 100; g_szGPS.cx = (int)(100.0 * g_szMap.cx / g_szMap.cy + 0.5); }
    Resize(&g_imgGPS, g_szGPS.cx, g_szGPS.cy);
    g_ptGPS.x = 530 + 50 - g_szGPS.cx / 2;
    g_ptGPS.y = 370 + 50 - g_szGPS.cy / 2;
    // 画迷你地图外框
    setlinecolor(RED);
    rectangle(g_ptGPS.x - 1, g_ptGPS.y - 1, g_ptGPS.x + g_szGPS.cx, g_ptGPS.y + g_szGPS.cy);

    // 绘制游戏区
    Paint();
}


//将TCHAR转为char    
//*tchar是TCHAR类型指针,*_char是char类型指针    
void TcharToChar(const TCHAR* tchar, char* _char)
{
    int iLength;
    //获取字节长度    
    iLength = WideCharToMultiByte(CP_ACP, 0, tchar, -1, NULL, 0, NULL, NULL);
    //将tchar值赋给_char     
    WideCharToMultiByte(CP_ACP, 0, tchar, -1, _char, iLength, NULL, NULL);
}

/*
//使用文件输入迷宫的大小与起、终点
void  GetMazeSize()
{
    g_szMap.cx = g_szMap.cy = g_start.cx = g_start.cy = g_end.cx = g_end.cy = 0;
    //获取文件名
    TCHAR s[20];
    char fileName[20];
    char str[1000];  //存放读出一行文本的字符串
    char strTemp[10]; //判断是否注释行
    FILE* pFile;     //定义文件指针
    do
    {
        InputBox(s, 20, _T("请输入迷宫信息位置\n"), _T("输入"), _T("F:\\"));
        TcharToChar(s, fileName);
        fopen_s(&pFile, fileName, "r");
    } while (!pFile);

    //读取数据
    fscanf_s(pFile, "%d", &g_szMap.cx);
    fscanf_s(pFile, "%d", &g_szMap.cy);
    fscanf_s(pFile, "%d", &g_start.cx);
    fscanf_s(pFile, "%d", &g_start.cy);
    fscanf_s(pFile, "%d", &g_end.cx);
    fscanf_s(pFile, "%d", &g_end.cy);


    fclose(pFile); //关闭文件

}*/


// 提示用户输入迷宫大小与起、终点
void GetMazeSize()
{
    g_szMap.cx = g_szMap.cy = g_start.cx = g_start.cy = g_end.cx = g_end.cy = 0;

    // 获取用户输入的宽高与起终点
    TCHAR s[4];
    while (g_szMap.cx < 20 || g_szMap.cx > 200)
    {
        InputBox(s, 4, _T("请输入迷宫的宽度\n范围:20~200"), _T("输入"), _T("25"));
        g_szMap.cx = _ttoi(s);
    }
    while (g_szMap.cy < 20 || g_szMap.cx > 200)
    {
        InputBox(s, 4, _T("请输入迷宫的高度\n范围:20~200"), _T("输入"), _T("25"));
        g_szMap.cy = _ttoi(s);
    }

    //输入起点
    while (g_start.cx <= 1 || g_start.cx >= g_szMap.cx)
    {
        InputBox(s, 4, _T("请输入迷宫的起点x坐标\n"), _T("输入"), _T("25"));
        g_start.cx = _ttoi(s);
    }
    while (g_start.cy <= 1 || g_start.cy >= g_szMap.cy)
    {
        InputBox(s, 4, _T("请输入迷宫的起点y坐标\n"), _T("输入"), _T("25"));
        g_start.cy = _ttoi(s);
    }

    //输入终点
    while (g_end.cx <= 1 || g_end.cx >= g_szMap.cx)
    {
        InputBox(s, 4, _T("请输入迷宫的终点x坐标\n"), _T("输入"), _T("25"));
        g_end.cx = _ttoi(s);
    }
    while (g_end.cy <= 1 || g_end.cy >= g_szMap.cy)
    {
        InputBox(s, 4, _T("请输入迷宫的终点y坐标\n"), _T("输入"), _T("25"));
        g_end.cy = _ttoi(s);
    }

    // 确保宽高为奇数
    if (g_szMap.cx % 2 != 1) g_szMap.cx++;
    if (g_szMap.cy % 2 != 1) g_szMap.cy++;
}


// 生成迷宫:初始化(注:宽高必须是奇数)
void MakeMaze(int width, int height)
{
    if (width % 2 != 1 || height % 2 != 1)
        return;

    int x, y;

    // 定义迷宫尺寸,并分配迷宫内存
    g_aryMap = new BYTE * [width + 2];
    for (x = 0; x < width + 2; x++)
    {
        g_aryMap[x] = new BYTE[height + 2];
        memset(g_aryMap[x], MAP_WALL, height + 2);
    }

    // 定义边界
    for (x = 0; x <= width + 1; x++)
        g_aryMap[x][0] = g_aryMap[x][height + 1] = MAP_GROUND;

    for (y = 1; y <= height; y++)
        g_aryMap[0][y] = g_aryMap[width + 1][y] = MAP_GROUND;

    // 定义入口和出口
    g_aryMap[g_start.cx][g_start.cy] = MAP_ENTRANCE;
    g_aryMap[g_end.cx][g_end.cy] = MAP_EXIT;

    // 从任意点开始遍历生成迷宫
    TravelMaze(((rand() % (width - 1)) & 0xfffe) + 2, ((rand() % (height - 1)) & 0xfffe) + 2);

    // 将边界标记为迷宫外
    for (x = 0; x <= width + 1; x++)
        g_aryMap[x][0] = g_aryMap[x][height + 1] = MAP_OUTSIDE;

    for (y = 1; y <= height; y++)
        g_aryMap[0][y] = g_aryMap[width + 1][y] = MAP_OUTSIDE;
}


// 生成迷宫:遍历 (x, y) 四周(深度搜索生成)
void TravelMaze(int x, int y)
{
    // 定义遍历方向
    int d[4][2] = { 0, 1, 1, 0, 0, -1, -1, 0 };

    // 将遍历方向乱序
    int n, t, i;
    for (i = 0; i < 4; i++)
    {
        n = rand() % 4;
        t = d[i][0], d[i][0] = d[n][0], d[n][0] = t;
        t = d[i][1], d[i][1] = d[n][1], d[n][1] = t;
    }

    // 尝试周围四个方向,随机分配是否有墙壁
    g_aryMap[x][y] = MAP_GROUND;
    for (i = 0; i < 4; i++)
        if (g_aryMap[x + 2 * d[i][0]][y + 2 * d[i][1]] == MAP_WALL || g_aryMap[x + 2 * d[i][0]][y + 2 * d[i][1]] == MAP_EXIT || g_aryMap[x + 2 * d[i][0]][y + 2 * d[i][1]] == MAP_ENTRANCE)
        {
            if (g_aryMap[x + d[i][0]][y + d[i][1]] != MAP_EXIT && g_aryMap[x + d[i][0]][y + d[i][1]] != MAP_ENTRANCE)
                g_aryMap[x + d[i][0]][y + d[i][1]] = MAP_GROUND;
            TravelMaze(x + d[i][0] * 2, y + d[i][1] * 2);        // 递归
        }
}


// 获取指定坐标的迷宫元素
MAPITEM GetMazeItem(int x, int y)
{
    return (MAPITEM)g_aryMap[x][y];
}


// 绘制视野范围内的迷宫
void Paint()
{
    int x1, y1;

    // 绘制视野内的迷宫
    SetWorkingImage(&g_imgSight);
    for (int x = g_rtSight.left; x <= g_rtSight.right; x++)
        for (int y = g_rtSight.top; y <= g_rtSight.bottom; y++)
        {
            x1 = (x - g_rtSight.left) * 20;
            y1 = (y - g_rtSight.top) * 20;
            putimage(x1, y1, 20, 20, &g_imgItem, GetMazeItem(x, y), 0);
        }


    // 绘制游戏者
    x1 = (g_ptPlayer.x - g_rtSight.left) * 20;
    y1 = (g_ptPlayer.y - g_rtSight.top) * 20;
    putimage(x1, y1, 20, 20, &g_imgItem, MAP_PLAYER, 0);

    // 绘制迷你地图
    SetWorkingImage(&g_imgGPS);
    cleardevice();
    int tx = (int)((g_ptPlayer.x - 1) * g_szGPS.cx / (double)(g_szMap.cx - 1) + 0.5);
    int ty = (int)((g_ptPlayer.y - 1) * g_szGPS.cy / (double)(g_szMap.cy - 1) + 0.5);
    setlinecolor(WHITE);
    circle(tx, ty, 1);

    // 画迷你地图入口和出口
    tx = (int)((g_end.cx - 1) * g_szGPS.cx / (double)(g_szMap.cx - 1) + 0.5);
    ty = (int)((g_end.cy - 1) * g_szGPS.cy / (double)(g_szMap.cy - 1) + 0.5);
    setlinecolor(YELLOW);
    circle(tx, ty, 1);
    tx = (int)((g_start.cx - 1) * g_szGPS.cx / (double)(g_szMap.cx - 1) + 0.5);
    ty = (int)((g_start.cy - 1) * g_szGPS.cy / (double)(g_szMap.cy - 1) + 0.5);
    setlinecolor(RED);
    circle(tx, ty, 1);

    // 更新到绘图窗口
    SetWorkingImage();
    putimage(150, 110, 340, 260, &g_imgSight, 10, 10);
    putimage(g_ptGPS.x, g_ptGPS.y, &g_imgGPS);
    BeginBatchDraw();//批量绘制,避免出现闪屏
    for (int x = 1; x <= g_szMap.cx; x++)
        for (int y = 1; y <= g_szMap.cy; y++)
        {
            int tx = (int)((x - 1) * g_szGPS.cx / (double)(g_szMap.cx - 1) + 0.5) + g_ptGPS.x;
            int ty = (int)((y - 1) * g_szGPS.cy / (double)(g_szMap.cy - 1) + 0.5) + g_ptGPS.y;
            putimage(tx, ty, 3, 3, &g_imgItem, GetMazeItem(x, y), 0);
        }
    EndBatchDraw();//结束批量绘制
}


// 获取用户输入的命令
int GetCmd()
{
    int c = 0;

    if (GetAsyncKeyState(VK_LEFT) & 0x8000)        c |= CMD_LEFT;//|=表示把a和b做按位或(|)操作,结果赋值给a
    if (GetAsyncKeyState(VK_RIGHT) & 0x8000)        c |= CMD_RIGHT;
    if (GetAsyncKeyState(VK_UP) & 0x8000)        c |= CMD_UP;
    if (GetAsyncKeyState(VK_DOWN) & 0x8000)        c |= CMD_DOWN;
    if (GetAsyncKeyState('A') & 0x8000)        c |= CMD_LEFTWALL;//使用asdw也可操作移动
    if (GetAsyncKeyState('D') & 0x8000)        c |= CMD_RIGHTWALL;
    if (GetAsyncKeyState('W') & 0x8000)        c |= CMD_UPWALL;
    if (GetAsyncKeyState('S') & 0x8000)        c |= CMD_DOWNWALL;
    if (GetAsyncKeyState(VK_ESCAPE) & 0x8000)        c |= CMD_QUIT;
    if (GetAsyncKeyState('P') & 0x8000)        c |= CMD_PATH;
    if (GetAsyncKeyState('L') & 0x8000)        c |= CMD_SHORT;

    return c;
}


// 处理用户输入的命令
void DispatchCmd(int cmd)
{
    if (cmd & CMD_UP)            OnUp();
    if (cmd & CMD_DOWN)            OnDown();
    if (cmd & CMD_LEFT)            OnLeft();
    if (cmd & CMD_RIGHT)        OnRight();
    if (cmd & CMD_LEFTWALL)        LeftWall();
    if (cmd & CMD_RIGHTWALL)    RightWall();
    if (cmd & CMD_UPWALL)        UpWall();
    if (cmd & CMD_DOWNWALL)        DownWall();
    if (cmd & CMD_PATH)         OUTPATH(g_szMap.cx, g_szMap.cy);
    if (cmd & CMD_SHORT)        OUTSHORTPATH();

}


// 向上移动
void OnUp()
{
    if (g_ptPlayer.y > 1 && GetMazeItem(g_ptPlayer.x, g_ptPlayer.y - 1) != MAP_WALL)
    {
        g_ptPlayer.y--;

        if (g_ptPlayer.y - g_rtSight.top < 4 && g_rtSight.top > 0)
        {
            g_rtSight.top--;
            g_rtSight.bottom--;
        }
    }
}


// 向左移动
void OnLeft()
{
    if (g_ptPlayer.x > 1 && GetMazeItem(g_ptPlayer.x - 1, g_ptPlayer.y) != MAP_WALL && GetMazeItem(g_ptPlayer.x - 1, g_ptPlayer.y) != MAP_ENTRANCE)
    {
        g_ptPlayer.x--;

        if (g_ptPlayer.x - g_rtSight.left < 5 && g_rtSight.left > 0)
        {
            g_rtSight.left--;
            g_rtSight.right--;
        }
    }
}


// 向右移动
void OnRight()
{
    if (g_ptPlayer.x < g_szMap.cx && GetMazeItem(g_ptPlayer.x + 1, g_ptPlayer.y) != MAP_WALL)
    {
        g_ptPlayer.x++;

        if (g_rtSight.right - g_ptPlayer.x < 5 && g_rtSight.right <= g_szMap.cx)
        {
            g_rtSight.left++;
            g_rtSight.right++;
        }
    }
}


// 向下移动
void OnDown()
{
    if (g_ptPlayer.y < g_szMap.cy && GetMazeItem(g_ptPlayer.x, g_ptPlayer.y + 1) != MAP_WALL)
    {
        g_ptPlayer.y++;

        if (g_rtSight.bottom - g_ptPlayer.y < 4 && g_rtSight.bottom <= g_szMap.cy)
        {
            g_rtSight.top++;
            g_rtSight.bottom++;
        }
    }
}

//变成墙壁
void UpWall()
{
    if (GetMazeItem(g_ptPlayer.x, g_ptPlayer.y - 1) != MAP_WALL)
        g_aryMap[g_ptPlayer.x][g_ptPlayer.y - 1] = MAP_WALL;
    else
        g_aryMap[g_ptPlayer.x][g_ptPlayer.y - 1] = MAP_GROUND;
}

void LeftWall()
{
    if (GetMazeItem(g_ptPlayer.x - 1, g_ptPlayer.y) != MAP_WALL)
        g_aryMap[g_ptPlayer.x - 1][g_ptPlayer.y] = MAP_WALL;
    else
        g_aryMap[g_ptPlayer.x - 1][g_ptPlayer.y] = MAP_GROUND;
}

void RightWall()
{
    if (GetMazeItem(g_ptPlayer.x + 1, g_ptPlayer.y) != MAP_WALL)
        g_aryMap[g_ptPlayer.x + 1][g_ptPlayer.y] = MAP_WALL;
    else
        g_aryMap[g_ptPlayer.x + 1][g_ptPlayer.y] = MAP_GROUND;
}

void DownWall()
{
    if (GetMazeItem(g_ptPlayer.x, g_ptPlayer.y + 1) != MAP_WALL)
        g_aryMap[g_ptPlayer.x][g_ptPlayer.y + 1] = MAP_WALL;
    else
        g_aryMap[g_ptPlayer.x][g_ptPlayer.y + 1] = MAP_GROUND;
}


// 深度优先搜索迷宫路径  
void FindPath(int& count, int x, int y, int& lengtha)
{
    // 置路径  
    Maze[x][y] = 0;
    path_x[count][lengtha] = x;
    path_y[count][lengtha] = y;
    lengtha++;
    // 搜索到目的地  
    if (x == g_end.cx && y == g_end.cy)
    {
        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[x][y + 1] == 1) { FindPath(count, x, y + 1, lengtha); Maze[x][y + 1] = 1; lengtha--; }
        if (Maze[x + 1][y] == 1) { FindPath(count, x + 1, y, lengtha); Maze[x + 1][y] = 1; lengtha--; }
        if (Maze[x][y - 1] == 1) { FindPath(count, x, y - 1, lengtha); Maze[x][y - 1] = 1; lengtha--; }
        if (Maze[x - 1][y] == 1) { FindPath(count, x - 1, y, lengtha); Maze[x - 1][y] = 1; lengtha--; }
    }

}

// 输出路径连线  
void OutPutPath(int count)
{
    for (int x = 0; x < count; x++)
    {
        Paint();
        for (int i = 0; i < length[x] - 1; i++)
        {
            setcolor(RED);
            setlinecolor(YELLOW);
            int x1 = (int)((path_x[x][i] - 1) * g_szGPS.cx / (double)(g_szMap.cx - 1) + 0.5) + g_ptGPS.x - 1;
            int x2 = (int)((path_x[x][i + 1] - 1) * g_szGPS.cx / (double)(g_szMap.cx - 1) + 0.5) + g_ptGPS.x - 1;
            int y1 = (int)((path_y[x][i] - 1) * g_szGPS.cy / (double)(g_szMap.cy - 1) + 0.5) + g_ptGPS.y - 1;
            int y2 = (int)((path_y[x][i + 1] - 1) * g_szGPS.cy / (double)(g_szMap.cy - 1) + 0.5) + g_ptGPS.y - 1;
            line(x1, y1, x2, y2);
        }
        system("pause");
    }
}


void  OUTPATH(int height, int wdith)
{


    for (int x = 0; x < height + 2; x++)
        for (int y = 0; y < wdith + 2; y++)
        {
            if (GetMazeItem(x, y) != MAP_WALL)
                Maze[x][y] = 1;
            else
                Maze[x][y] = 0;
        }
    // 定义边界
    for (int x = 0; x <= wdith + 1; x++)
        Maze[x][0] = Maze[x][height + 1] = 0;

    for (int y = 1; y <= height; y++)
        Maze[0][y] = Maze[wdith + 1][y] = 0;
    int lengtha = 0;
    count = 0;

    FindPath(count, g_ptPlayer.x, g_ptPlayer.y, lengtha);

    OutPutPath(count);
}

//显示最短路径
void    OUTSHORTPATH()
{
    int s = 0;
    for (int x = 0; x < count; x++)
    {
        if (length[s] > length[x])
            s = x;
    }
    Paint();
    for (int i = 0; i < length[s] - 1; i++)
    {
        setcolor(RED);
        setlinecolor(YELLOW);
        int x1 = (int)((path_x[s][i] - 1) * g_szGPS.cx / (double)(g_szMap.cx - 1) + 0.5) + g_ptGPS.x - 1;
        int x2 = (int)((path_x[s][i + 1] - 1) * g_szGPS.cx / (double)(g_szMap.cx - 1) + 0.5) + g_ptGPS.x - 1;
        int y1 = (int)((path_y[s][i] - 1) * g_szGPS.cy / (double)(g_szMap.cy - 1) + 0.5) + g_ptGPS.y - 1;
        int y2 = (int)((path_y[s][i + 1] - 1) * g_szGPS.cy / (double)(g_szMap.cy - 1) + 0.5) + g_ptGPS.y - 1;
        line(x1, y1, x2, y2);
    }
    system("pause");
}

// 检查是否到出口
bool CheckWin()
{
    if (g_ptPlayer.x == g_end.cx && g_ptPlayer.y == g_end.cy)
    {
        HWND hwnd = GetHWnd();// 获取绘图窗口句柄(HWND)
        if (MessageBox(hwnd, _T("恭喜,成功走出迷宫!\n想再来一局吗?"), _T("恭喜"), MB_YESNO | MB_ICONQUESTION) == IDYES)
        {
            InitGame();
            return false;
        }
        else
            return true;
    }

    return false;
}


// 询问用户是否退出游戏
bool Quit()
{
    HWND hwnd = GetHWnd();
    return (MessageBox(hwnd, _T("您确定要退出游戏吗?"), _T("询问"), MB_OKCANCEL | MB_ICONQUESTION) == IDOK);//如果选择了是,则退出
}

//将迷宫信息存储到文件中
void save()
{
    FILE* fp;
    fopen_s(&fp, "d:\\test.txt", "wb");
    for (int i = 0; i < g_szMap.cx; i++)
        for (int j = 0; j < g_szMap.cy; j++)
        {
            fprintf(fp, "%d %d %d \n \r", i, j, g_aryMap[g_szMap.cx][g_szMap.cy]);
            fprintf(fp, "\n");
        }

    fclose(fp);
}


int _tmain(int argc, _TCHAR* argv[])
{
    // 初始化
    initgraph(640, 480);            // 创建绘图窗口
    srand((unsigned)time(NULL));    // 设置随机种子

    // 显示主界面
    Welcome();

    // 初始化
    InitImage();
    InitGame();

    // 游戏过程
    int c;
    while (!(((c = GetCmd()) & CMD_QUIT) && Quit()))
    {
        Paint();
        DispatchCmd(c);
        if (CheckWin())
            break;

        // 延时
        Sleep(100);
    }

    save();

    // 清理迷宫地图占用的内存
    for (int x = 0; x < g_szMap.cx + 2; x++)
        delete[] g_aryMap[x];
    delete[] g_aryMap;

    // 关闭图形模式
    closegraph();
    return 0;
}

头文件如下

// stdafx.h : include file for standard system include files,
//  or project specific include files that are used frequently, but
//      are changed infrequently
//

#if !defined(AFX_STDAFX_H__4607A810_33E2_483D_80D8_BE41F0D473D5__INCLUDED_)
#define AFX_STDAFX_H__4607A810_33E2_483D_80D8_BE41F0D473D5__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000


// Insert your headers here
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#define DLLEXPORT __declspec(dllexport)
#define	DLLIMPORT __declspec(dllimport)

#include "stdio.h"
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>

#pragma comment(lib,"ws2_32.lib")

// TODO: reference additional headers your program requires here
void Msg(char *szFormat, ...);
void dbMsg(char *szFormat, ...);
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_STDAFX_H__4607A810_33E2_483D_80D8_BE41F0D473D5__INCLUDED_)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值