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