迷宫是指一个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_)