#include <stdio.h>
#include <iostream>
#include <conio.h>
#include <windows.h>
#include <time.h>
#include<bits/stdc++.h>
using namespace std;
#define Wall 1 //用1表示墙
#define Road 0 //用0表示路
#define Start 2
#define End 3
#define up 72
#define down 80
#define left 75
#define right 78
#define flag 5
int Height=0,Width=0,N;
int x=2,y=1; //玩家当前位置,刚开始在入口处
bool visited[100][100];
class Migong
{
public:
int difficulty;
int map[100][100];
void gotoxy(int x,int y); //移动坐标的函数声明
void shengcheng(int x,int y); //随机生成迷宫的函数声明
void display(int x,int y); //显示迷宫的函数声明
void chushi(); //初始化迷宫的函数声明
void setDifficulty(int diff);
void setExit(); // 新增设置出口位置的函数声明
};
class Wanjia:public Migong //玩家类由迷宫类派生来
{
public:
void gonglue(int x,int y);
void shang(int x,int y);
void xia(int x,int y);
void zuo(int x,int y);
void you(int x,int y);
void game(); //游戏运行包括移动的函数声明
};
void Migong::setExit() {
// 出口默认放置在迷宫的右下角
map[Height - 1][Width] = End;
// 可以在这里添加逻辑来根据难度或其他因素调整出口的位置
}
void Migong::gotoxy(int x,int y) //移动坐标 这是使光标 到(x,y)这个位置的函数.调用 COORD 需要#include.
{
COORD coord;
coord.X=x;
coord.Y=y;
SetConsoleCursorPosition( GetStdHandle( STD_OUTPUT_HANDLE ), coord );
}
void Migong::shengcheng(int x,int y) //随机生成迷宫
{
int c[4][2]={0,1,1,0,0,-1,-1,0}; //四个方向 //数组c 0 1 向右
// 1 0 向下
// -1 0 向上
// 0 -1 向左
int i,j,t;
//将方向打乱
for(i=0;i<4;i++)
{
j=rand()%4; //随机生成j
t=c[i][0];c[i][0]=c[j][0];c[j][0]=t; //将c[i][0]和c[j][0]交换
t=c[i][1];c[i][1]=c[j][1];c[j][1]=t; //类似上
}
map[x][y]=Road; //当前位置设为路
for(i=0;i<4;i++) //沿四个方向设置
if(map[x+2*c[i][0]][y+2*c[i][1]]==Wall) //沿c[i][0]、c[i][1]方向前2步如果是墙
{
map[x+c[i][0]][y+c[i][1]]=Road; //让该方向前一步设为路
shengcheng(x+2*c[i][0],y+2*c[i][1]); //在该方向前两步继续生成地图 因为这里是递归函数,当执行到最后一点发现都不能走的时候,
//会返回到上一个函数,也就是上一个点,再次判断是否可以产生地图 ,知道地图上所有点被遍历完。
}
}
void Migong::setDifficulty(int diff) {
// 根据难度设置墙的比例
int wallRatio;
switch (diff) {
case 1: wallRatio = 2; break; // 简单难度
case 2: wallRatio = 40; break; // 中等难度
case 3: wallRatio = 60; break; // 困难难度
default: wallRatio = 20; break;
}
// 根据墙的比例初始化迷宫
for (int i = 1; i <= Height; i++) {
for (int j = 1; j <= Width; j++) {
if (rand() % 100 < wallRatio) {
map[i][j] = Wall;
} else {
map[i][j] = Road;
}
}
}
// 确保入口和出口是路
map[1][1] = Start;
map[Height - 1][Width] = End;
}
void Migong::display(int x,int y) //显示迷宫
{
gotoxy(2*y-2,x-1);
switch(map[x][y])
{
case Start:
cout<<"入";break; //显示入口
case End:
cout<<"出";break; //显示出口
case Wall:
cout<<"■";break; //显示墙
case Road:
cout<<" ";break; //显示路
case up:
cout<<"↑";break; //在攻略中的标记 下同
case down:
cout<<"↓";break;
case left:
cout<<"←";break;
case right:
cout<<"→";break;
case flag:
cout<<" ";break; //标记,防止攻略遍历时候无线循环
}
}
void shuru()
{
cout<<"请输入您想创建的迷宫的N*N大小:"<<endl;
cin>>N;
}
void Migong::chushi() {
int i, j;
srand((unsigned)time(NULL)); // 初始化随机种子
for (i = 1; i <= Height + 1; i++)
for (j = 1; j <= Width + 1; j++)
if (i == 0 || i == Height + 1 || j == 0 || j == Width + 1) // 初始化迷宫 默认四周是路
map[i][j] = Road;
else map[i][j] = Wall;
shengcheng(2 * (rand() % (Height / 2) + 1), 2 * (rand() % (Width / 2) + 1)); // 从随机一个点开始生成迷宫,该点行列都为偶数
for (i = 0; i <= Height + 1; i++) // 边界处理 把最开始默认为路的堵上,以免跑出迷宫
{
map[i][0] = Wall;
map[i][Width + 1] = Wall;
}
for (j = 0; j <= Width + 1; j++) // 边界处理
{
map[0][j] = Wall;
map[Height + 1][j] = Wall;
}
map[2][1] = Start; // 给定入口
setExit(); // 设置出口位置
for (i = 1; i <= Height; i++) // i初始为1,结束为height,以免画出外围
{
for (j = 1; j <= Width; j++) // 画出迷宫 同上
{
display(i, j);
}
}
}
void Wanjia::game()
{
int x=2,y=1; //玩家当前位置,刚开始在入口处
int c; //用来接收按键
int score = 0; // 初始化得分
clock_t startTime = clock();
while(1)
{
gotoxy(2*y-2,x-1);
cout << "☆"; //画出玩家当前位置
if(map[x][y] == End) //判断是否到达出口
{
gotoxy(2*N-2, N-1); //到达此坐标
cout << "恭喜你!成功走出迷宫!" << endl;
switch(difficulty)
{
case 1: score = 10; break; // 简单难度
case 2: score = 20; break; // 中等难度
case 3: score = 30; break; // 困难难度
}
cout << "你的得分是:" << score <<"分!"<< endl;
clock_t endTime = clock();
double gameDuration = double(endTime - startTime) / CLOCKS_PER_SEC;
// 输出游戏用时
cout << "游戏用时: " << gameDuration << " 秒" << endl;
cout << "是否要打印走过的路径进行复盘?(Y/N): ";
char choice;
cin >> choice;
if(choice == 'Y' || choice == 'y') {
// 打印玩家走过的路径
for(int i=1;i<=Height;i++) //i初始为1,结束为height,以免画出外围
{ for(int j=1;j<=Width;j++) //画出迷宫 同上
{if(visited[i][j]) {
gotoxy(2*j-2,i-1);
cout << "*"; // 打印走过的位置
}
else{
gotoxy(2*j-2,i-1);
switch(map[i][j])
{
case Start:
cout<<"入";break; //显示入口
case End:
cout<<"出";break; //显示出口
case Wall:
cout<<"■";break; //显示墙
case Road:
cout<<" ";break; //显示路
case up:
cout<<"↑";break; //在攻略中的标记 下同
case down:
cout<<"↓";break;
case left:
cout<<"←";break;
case right:
cout<<"→";break;
case flag:
cout<<" ";break; //标记,防止攻略遍历时候无线循环
}
}
}
}}
getch();
exit(0);
break;
}
if(c != -32)
{
c = getch();
switch(c)
{
case 72: // 向上走
if(map[x-1][y] != Wall)
{
display(x, y);
x--;
}
break;
case 80: // 向下走
if(map[x+1][y] != Wall)
{
display(x, y);
x++;
}
break;
case 75: // 向左走
if(map[x][y-1] != Wall)
{
display(x, y);
y--;
}
break;
case 77: // 向右走
if(map[x][y+1] != Wall)
{
display(x, y);
y++;
}
break;
case 112: // 按下P
gonglue(2,1);break; //如果按下P执行攻略函数
}
}
visited[x][y] = 1;
}
}
void Wanjia::shang(int x,int y)
{
if(map[x][y]==End) //判断是否到达出口
{
gotoxy(2*N-2,N-1); //到达此坐标
cout<<"到达终点,按任意键结束";
getch();
exit(0);
}
if(map[x-1][y]!=Wall&&map[x-1][y]!=up&&map[x-1][y]!=down&&map[x-1][y]!=left&&map[x-1][y]!=right&&map[x-1][y]!=flag)
{ //当移动后的下一个位置没有被走过且不是墙
map[x][y]=up;
display(x,y);
x--;
gonglue(x,y); //递归,攻略下一个点
}
}
void Wanjia::xia(int x,int y)
{
if(map[x][y]==End) //判断是否到达出口
{
gotoxy(2*N-2,N-1); //到达此坐标
getch();
exit(0);
}
if(map[x+1][y]!=Wall&&map[x+1][y]!=up&&map[x+1][y]!=down&&map[x+1][y]!=left&&map[x+1][y]!=right&&map[x+1][y]!=flag) //当移动后的下一个位置没有被走过且不是墙
{
map[x][y]=down;
display(x,y);
x++;
gonglue(x,y); //递归,攻略下一个点
}
}
void Wanjia::zuo(int x,int y)
{
if(map[x][y]==End) //判断是否到达出口
{
gotoxy(2*N-2,N-1); //到达此坐标
cout<<"到达终点,按任意键结束";
getch();
exit(0);
}
if(map[x][y-1]!=Wall&&map[x][y-1]!=up&&map[x][y-1]!=down&&map[x][y-1]!=left&&map[x][y-1]!=right&&map[x][y-1]!=flag) //当移动后的下一个位置没有被走过且不是墙
{
map[x][y]=left;
display(x,y);
y--;
gonglue(x,y); //递归,攻略下一个点
}
}
void Wanjia::you(int x,int y)
{
if(map[x][y]==End) //判断是否到达出口
{
gotoxy(2*N-2,N-1); //到达此坐标
cout<<"到达终点,按任意键结束";
getch();
exit(0);
}
if(map[x][y+1]!=Wall&&map[x][y+1]!=up&&map[x][y+1]!=down&&map[x][y+1]!=left&&map[x][y+1]!=right&&map[x][y+1]!=flag) //当移动后的下一个位置没有被走过且不是墙
{
map[x][y]=right;
display(x,y);
y++;
gonglue(x,y); //递归,攻略下一个点
}
}
void Wanjia::gonglue (int x,int y)
{
gotoxy(2*y-2,x-1);
cout<<"☆"; //画出玩家当前位置
if(map[x][y]==End) //判断是否到达出口
{
gotoxy(2*N-2,N-1); //到达此坐标
cout<<"到达终点,按任意键结束";
getch();
exit(0);
}
shang(x,y); //上下左右
xia(x,y);
zuo(x,y);
you(x,y);
map[x][y]=flag; //当上下左右都无法走的时候,即为死路,因为递归函数开始向后,所以讲死路点值置为flag,变成无形之墙。
display(x,y);
}
int main()
{Migong a;
cout<<" 移动迷宫 "<<endl;
cout<<"--------------------"<<endl;
cout<<"欢迎来到移动迷宫游戏"<<endl;
cout<<"--------------------"<<endl;
cout<<"游戏说明:给定一出口和入口"<<endl;
cout<<"玩家控制一个五角星(☆)从入口走到出口"<<endl;
cout<<"系统会记录你所走的步数"<<endl;
cout<<"按回车进入游戏";
cout<<"(按下P键可以获得攻略。)";
getch();
system("cls"); //清屏函数 ,清除开始界面
Wanjia w1;
cout << "请选择难度等级(1-简单,2-中等,3-困难): ";
cin >> w1.difficulty;
shuru();
Width=N;
Height=N;
a.map[N][N];
system("cls"); // 清屏,清除开始界面
w1.chushi();
w1.game(); //开始游戏
// w1.gonglue(2,1); //功略显示
getch();
return 0;
}
可实现难度选择,迷宫大小的创建:
走过路径的打印:
以及攻略的获取(按p键即可):