随机迷宫算法
‘壹’ c++ 迷宫 如何使大小随机
用户输入迷宫规模,行数m,列数n。
随机生成一个m*n的迷宫。
如果满足要求,输出迷宫和可行路径。
否则继续随机生成。
如果n和m比较大的话,程序跑的比较慢。
‘贰’ 数据结构:用什么算法可以走出迷宫
算法应该很多的,循环的,递归的,还有用栈的我有两个可以看看,第一个是网络上下的,后面的是我自己编的和修改的
1.
//////////////////////////////////////////////////////////////////////
//文件名 :Maze.cpp
//功能 : 线性表的应用——迷宫求解
//创建 : 2007.6.20
//修改日期 : 2007.6.20
//作者 :
////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <iostream>
#include <stdio.h>
#include<time.h>
//#include "format.h"
//#include "stack.h"
using namespace std;
#define OK 0
#define ERR -1
#define UP '↑' //用于存储方向的常量
#define DOWN '↓'
#define LEFT '→'
#define RIGHT '←'
#define Rank 20
#define File 63
#define Rand 16
char Maze[Rank][File]; //定义存储迷宫用的字符型二维数组
char mark=1; //标记
char Bar=2; //地图
char Player=12; //游戏者
typedef struct SNode
{
int data;
struct SNode *next;
}SNode;
typedef struct
{
int length;
SNode *top;
}STACK;
void InitStack(STACK *S)
{
S->top=NULL;
S->length=0;
}
/*元素e入栈*/
int Push(STACK *S,int e)
{
SNode *p;
p=new SNode[sizeof(SNode)];
if(!p) return ERR;
p->data=e;
p->next=S->top;
S->top=p;
S->length++;
return OK;
}
/*栈顶元素出栈,e带回栈顶元数*/
int Pop(STACK *S,int *e)
{
SNode *p;
if(S->top==NULL) return ERR;
p=S->top;
*e=p->data;
S->top=p->next;
S->length--;
delete p;
return OK;
}
/*判断S是否为空栈*/
int Empty(STACK S)
{
if(S.top==NULL) return OK;
return ERR;
}
void ShowMaze();
void InitMaze();
void RunMaze();
int main()
{
int i=1;
system("color 1E");
while(i==1)
{
RunMaze();
cout<<"\t\t ‘选择:Prsss 1:再来一次 Else:退出程序’\n";
cin>>i;
}
return 0;
}
void ShowMaze()
{
int i,j;
system("cls");
cout<<"\n\t\t\t ‘迷 宫 求 解’"<<"\n";
cout<<"\t\t ‘注:"<<Player<<"为游戏者"<<Bar<<"为地图障碍"<<mark<<"为所留印记’"<<endl;
for(i=0;i<Rank;i++)
{
cout<<"\t"<<Bar;
for(j=0;j<File;j++)
cout<<Maze[i][j];
cout<<Bar<<"\n";
}
}
void InitMaze()
{
int i,j;
for(i=0;i<Rank;i++)
for(j=0;j<File;j++)
Maze[i][j]=Bar;
srand((unsigned)time(NULL));
int n;
cout<<"请输入数字选图";
cin>>n;
for(i=1;i<Rank-1;i++) //for开始
for(j=1;j<File;j++)
{
//n=rand()%Rand; //随机函数
//if(n<Rand*2/3) Maze[i][j]=' ';
if (((n^i+4*j^3))%11!=5)Maze[i][j]=' ';
} //for结束
Maze[1][0]=' '; //给迷宫留入口
Maze[1][1]=' ';
Maze[1][2]=' ';
Maze[1][3]=' ';
Maze[Rank-2][File-4]=' '; //给迷宫留出口
Maze[Rank-2][File-3]=' ';
Maze[Rank-2][File-2]=' ';
Maze[Rank-2][File-1]=' ';
}
void RunMaze()
{
int path,i=1,j=0,speed=0;
time_t Start,End;
STACK S; //定义一个用于存储走过的路线的栈
time(&Start);
InitMaze(); //随机成生迷宫
InitStack(&S); //初始化栈
Maze[1][0]=Player; //初始化位置
ShowMaze(); //显示迷宫
cout<<"\n\t\t\t‘请选择速度:1 快速 2 较慢 ’"<<endl;
while(speed!=1 && speed!=2) cin>>speed;
while(i>=0 && i<Rank && j>=0 && j<File)//开始遍历迷宫
{
ShowMaze(); //显示迷宫
if(speed==2) //选择2较慢时进入空循环延时
Sleep(100);
if(i==Rank-2&&j==File-1) //判断是否到达出口
{
time(&End);
cout<<"\n\t\t‘恭喜成功走出!所用的步数为:"<<S.length<<" 所用时间:"<<End-Start<<" 秒’"<<endl;
return;
}
if(Maze[i][j+1]==' ') //向右走一步
{
char dir=26;
Maze[i][j]=dir;
j=j+1;
Maze[i][j]=Player;
Push(&S,RIGHT);
}
else
{
if(Maze[i+1][j]==' ') //向下走一步
{
char dir=25;
Maze[i][j]=dir;
i=i+1;
Maze[i][j]=Player;
Push(&S,DOWN);
}
else
{
if(Maze[i-1][j]==' ') //向上走一步
{
char dir=24;
Maze[i][j]=dir;
i=i-1;
Maze[i][j]=Player;
Push(&S,UP);
}
else
{
if(Maze[i][j-1]==' ') //向左走一步
{
char dir=27;
Maze[i][j]=dir;
j=j-1;
Maze[i][j]=Player;
Push(&S,LEFT);
}
else //遇到障碍往回走一步
{
if(Empty(S)==OK) //判断是否回到起点了,是则退出程序
{
time(&End);
cout<<"\n\t\t\t‘迷宫没有出路! 所用时间:"<<End-Start<<"秒’\n";
return;
}
else
{
if(Pop(&S,&path)==OK) //判断能否取回上一步路径
{
switch(path)
{
case LEFT:
Maze[i][j]=mark;
j=j+1;
Maze[i][j]=Player;
break;
case UP:
Maze[i][j]=mark;
i=i+1;
Maze[i][j]=Player;
break;
case DOWN:
Maze[i][j]=mark;
i=i-1;
Maze[i][j]=Player;
break;
case RIGHT:
Maze[i][j]=mark;
j=j-1;
Maze[i][j]=Player;
break;
} //结束分支语句switch
} //结束判断能否取回上一步路径
}
}
}
}
}
} //结束while循环
}
第二个。
#include <windows.h>
#include <iostream>
#include <stdio.h>
#include<time.h>
//#include "format.h"
//#include "stack.h"
using namespace std;
//#define OK 0
//#define ERR -1
//#define UP '↑' //用于存储方向的常量
//#define DOWN '↓'
//#define LEFT '→'
//#define RIGHT '←'
#define Rank 17
#define File 63
#define Rand 16
char Maze[Rank][File]; //定义存储迷宫用的字符型二维数组
char mark=1; //标记
char Bar=2; //地图
char Player=12; //游戏者
void ShowMaze();
void InitMaze();
void RunMaze();
int main()
{
int i=1;
system("color 1E");
while(i==1)
{
RunMaze();
cout<<"\t\t ‘选择:Prsss 1:再来一次 Else:退出程序’\n";
cin>>i;
}
return 0;
}
void ShowMaze()
{
int i,j;
system("cls");
cout<<"\n\t\t\t ‘迷 宫 求 解’"<<"\n";
cout<<"\t\t ‘注:"<<Player<<"为游戏者"<<Bar<<"为地图障碍"<<mark<<"为所留印记’"<<endl;
for(i=0;i<Rank;i++)
{
cout<<"\t"<<Bar;
for(j=0;j<File;j++)
cout<<Maze[i][j];
cout<<Bar<<"\n";
}
}
void InitMaze()
{
int i,j;
for(i=0;i<Rank;i++)
for(j=0;j<File;j++)
Maze[i][j]=Bar;
srand((unsigned)time(NULL));
int n=5;
cout<<"请输入数字选图";
cin>>n;
for(i=1;i<Rank-1;i++) //for开始
for(j=1;j<File;j++)
{
//n=rand()%Rand; //随机函数
//if(n<Rand*2/3) Maze[i][j]=' ';
if (((n^i+4*j^3))%5!=1)Maze[i][j]=' ';
} //for结束
Maze[1][0]=' '; //给迷宫留入口
Maze[1][1]=' ';
Maze[1][2]=' ';
Maze[1][3]=' ';
Maze[Rank-2][File-4]=' '; //给迷宫留出口
Maze[Rank-2][File-3]=' ';
Maze[Rank-2][File-2]=' ';
Maze[Rank-2][File-1]=' ';
}
void RunMaze()
{ int a=2;
int i=1,j=1,speed=0;
time_t Start,End;
//STACK S; //定义一个用于存储走过的路线的栈
time(&Start);
InitMaze(); //随机成生迷宫
//InitStack(&S); //初始化栈
//Maze[1][0]=Player; //初始化位置
ShowMaze(); //显示迷宫
cout<<"\n\t\t\t‘请选择速度:1 快速 2 较慢 ’"<<endl;
while(speed!=1 && speed!=2) cin>>speed;
while(i>=0 && i<Rank && j>=0 && j<File)//开始遍历迷宫
{
ShowMaze(); //显示迷宫
if(speed==2) //选择2较慢时进入空循环延时
Sleep(100);
if(i==Rank-2&&j==File-1) //判断是否到达出口
{
time(&End);
cout<<"\n\t\t‘恭喜成功走出!"<<" 所用时间:"<<End-Start<<" 秒’"<<endl;
return ;
}
else
{
switch(a)
{
case 1:if (Maze[i-1][j]==' '||Maze[i-1][j]==26)
{i=i-1;
a=-2;
Maze[i][j]=26;
break;
}
else
if (Maze[i][j+1]==' '||Maze[i][j+1]==26)
{j=j+1;
a=1;
Maze[i][j]=26;
break;
}else
if (Maze[i+1][j]==' '||Maze[i+1][j]==26)
//if(Maze[i+1]][j]==' '||Maze[i+1][j]==26)
{i=i+1;
a=2;
Maze[i][j]=26;
break;
}
else
{
Maze[i][j]=26;
a=-a;
break;
}
case 2:if(Maze[i][j+1]==' '||Maze[i][j+1]==26)
{
j=j+1;
a=1;
Maze[i][j]=26;
break;
}
else
if(Maze[i+1][j]==' '||Maze[i+1][j]==26)
{
i=i+1;
a=2;
Maze[i][j]=26;
break;
}
else
if(Maze[i][j-1]==' '||Maze[i][j-1]==26)
{
j=j-1;
a=-1;
Maze[i][j]=26;
break;
}
else
{
Maze[i][j]=26;
a=-a;
break;
}
case -1:if (Maze[i+1][j]==' '||Maze[i+1][j]==26)
{i=i+1;
a=2;
Maze[i][j]=26;
break;
}
else
if (Maze[i][j-1]==' '||Maze[i][j-1]==26)
{j=j-1;
a=-1;
Maze[i][j]=26;
break;
}
else
if (Maze[i-1][j]==' '||Maze[i-1][j]==26)
{i=i-1;
a=-2;
Maze[i][j]=26;
break;
}
else
{
a=-a;
Maze[i][j]=26;
break;
}
case -2:if (Maze[i][j-1]==' '||Maze[i][j-1]==26)
{j=j-1;
a=-1;
Maze[i][j]=26;
break;
}
else
if (Maze[i-1][j]==' '||Maze[i-1][j]==26)
{i=i-1;
a=-2;
Maze[i][j]=26;
break;
}
else
if (Maze[i][j+1]==' '||Maze[i][j+1]==26)
{j=j+1;
a=1;
Maze[i][j]=26;
break;
}
else
{
Maze[i][j]=26;
a=-a;
break;
}
}
if (i==1&&j==1)
{
time(&End);
cout<<"迷宫没有出路"<<"所用时间"<<End-Start<<endl;
return;
}
}
} //结束while循环
}
‘叁’ 数据结构与算法作业:用c语言编程随机生成一个迷宫,然后找出从入口到出口的路线图。急!
几点说明:
1.本程序是动态的,运行后自动寻找迷宫出路
2.本程序对C语言刚学完的有很大的意义.
3.四周是墙,坐标(1,1)是入口,右下脚是出口
声明:本程序用VC调试是无法通过的需要修改
本程序调试工具是TC.....................
#include "graphics.h"
#include "dos.h"
#include "stdlib.h"
#include "process.h"
#define MAX_COL 14/*定义迷宫大小*/
#define MAX_ROW 14
typedef struct
{ int vert;
int horiz;
}offsets;
mapture(int i,int j,int k);/*标记迷宫,(i,j)标记为k模式*/
initmaze();/*初始化迷宫数组*/
findmaze(int i,int j);/*找到了(i,j)可走,标记*/
mapmaze();/*画出原始迷宫*/
int findpath(int row,int col);/*递归函数,找出迷宫路径*/
mapbar();/*画出方格*/
initgrap();/*初始化VGA*/
print();/*迷宫走完后,输出是否成功 */
int startx=50,starty=50;/*画图的屏幕坐标*/
int maze[MAX_ROW][MAX_COL];
offsets move[8]={{0,1},{1,1},{-1,1},{1,0},{-1,0},{0,-1},{1,-1},{-1,-1}}; /*8个方向寻找*/
initmaze()/*初始化迷宫数组 */
{ int i,j;
for(i=0;i<MAX_ROW;i++)/*迷宫四周设置为1 代表墙*/
{ maze[i][0]=1;
maze[i][MAX_COL-1]=1;
}
for(i=0;i<MAX_COL;i++)
{ maze[0][i]=1;
maze[MAX_ROW-1][i]=1;
}
randomize();
for(i=1;i<MAX_ROW-1;i++)/*迷宫图形随机产生 1表示不通 0表示可行*/
for(j=1;j<MAX_COL-1;j++)
{
maze[i][j]=random(2);
}
}
findmaze(int i,int j)/*找到 (i,j)可走*/
{
mapture(j,i,2);/*在图形上标记*/
sleep(1);
}
returnmaze(int i,int j)/*找到(i,j)可走 ,但下一步无路走则标记*/
{
mapture(j,i,3);/*在图形上标记*/
sleep(1);
}
print(int i)/*迷宫走完后,输出是否成功*/
{ settextstyle(1,0,5);
if(i==1)
outtextxy(340,400,"Ture path!");
else if(i==2)
outtextxy(340,400,"No path!");
}
int findpath(int row,int col)/*用递归法找迷宫*/
{ int direct,next_row,next_col;
direct=0;
maze[1][1]=2;
mapture(1,1,2);
sleep(1);
while(direct<8)/*8个方向寻找*/
{ next_row=row+move[direct].vert;/*设置下一步坐标*/
next_col=col+move[direct].horiz;
if(maze[next_row][next_col]==0) /*可走,便标记*/
{ maze[next_row][next_col]=2;
findmaze(next_row,next_col) ;
if(next_row==(MAX_ROW-2)&&next_col==(MAX_COL-2))/*找到出口退出程序*/
{ print(1);
getch();
exit(0);
}
else
findpath(next_row,next_col);/*没有到出口继续递归*/
maze[next_row][next_col]=3;
returnmaze(next_row,next_col);
}
direct++;
}
return(row);
}
TC调试良好
‘肆’ 如何用c语言编写迷宫游戏
#include <graphics.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <dos.h>
#define N 20/*
迷宫的大小,可改变
*/
int oldmap[N][N];/*
递归用的数组
,
用全局变量节约时间
*/
int yes=0;/*yes
是判断是否找到路的标志
,1
找到,
0
没找到
*/
int way[100][2],wayn=0;/*way
数组是显示路线用的
,wayn
是统计走了几个格
子
*/
void Init(void);/*
图形初始化
*/
void Close(void);/*
图形关闭
*/
void DrawPeople(int *x,int *y,int n);/*
画人工探索物图
*/
void PeopleFind(int (*x)[N]);/*
人工探索
*/
void
WayCopy(int
(*x)[N],int
(*y)[N]);/*
为了
8
个方向的递归,把旧迷宫图
拷贝给新数组
*/
int FindWay(int (*x)[N],int i,int j);/*
自动探索函数
*/
void MapRand(int (*x)[N]);/*
随机生成迷宫函数
*/
void PrMap(int (*x)[N]);/*
输出迷宫图函数
*/
void Result(void);/*
输出结果处理
*/
void Find(void);/*
成功处理
*/
void NotFind(void);/*
失败处理
*/
void main(void)/*
主函数
*/
{
int map[N][N]; /*
迷宫数组
*/
char ch;
clrscr();
printf("\n Please select hand(1) else auto\n");/*
选择探索方式
*/
scanf("%c",&ch);
Init(); /*
初始化
*/
MapRand(map);/*
生成迷宫
*/
PrMap(map);/*
显示迷宫图
*/
if(ch=='1')
PeopleFind(map);/*
人工探索
*/
else
FindWay(map,1,1);/*
系统自动从下标
1,1
的地方开始探索
*/
Result();/*
输出结果
*/
Close();
}
void Init(void)/*
图形初始化
*/
{
int gd=DETECT,gm;
initgraph(&gd,&gm,"c:\\tc"); }
void DrawPeople(int *x,int *y,int n)/*画人工控制图*/ {/*如果将以下两句注释掉,则显示人工走过的路径,*/
setfillstyle(SOLID_FILL,WHITE); /*设置白色实体填充样式*/ bar(100+(*y)*15-6,50+(*x)*15-6,100+(*y)*15+6,50+(*x)*15+6); /*恢复原通路*/
switch(n)/*判断x,y的变化,8个方向的变化*/ {
case 1: (*x)--;break; /*上*/
case 2: (*x)--;(*y)++;break /*右上*/ case 3: (*y)++;break; /*右*/
case 4: (*x)++;(*y)++;break; /*右下*/ case 5: (*x)++;break; /*下*/
case 6: (*x)++;(*y)--;break; /*左下*/ case 7: (*y)--;break; /*左*/
case 8: (*x)--;(*y)--;break; /*左上*/ }
setfillstyle(SOLID_FILL,RED);/*新位置显示探索物*/
bar(100+(*y)*15-6,50+(*x)*15-6,100+(*y)*15+6,50+(*x)*15+6); }
void PeopleFind(int (*map)[N])/*人工手动查找*/ {
int x,y;
char c=0;/*接收按键的变量*/ x=y=1;/*人工查找的初始位置*/ setcolor(11);
line(500,200,550,200); outtextxy(570,197,"d"); line(500,200,450,200); outtextxy(430,197,"a"); line(500,200,500,150); outtextxy(497,130,"w"); line(500,200,500,250); outtextxy(497,270,"x"); line(500,200,450,150); outtextxy(445,130,"q"); line(500,200,550,150); outtextxy(550,130,"e"); line(500,200,450,250); outtextxy(445,270,"z"); line(500,200,550,250);
outtextxy(550,270,"c");/*以上是画8个方向的控制介绍*/
setcolor(YELLOW);
outtextxy(420,290,"Press 'Enter' to end");/*压回车键结束*/ setfillstyle(SOLID_FILL,RED);
bar(100+y*15-6,50+x*15-6,100+y*15+6,50+x*15+6);/*入口位置显示*/ while(c!=13)/*如果按下的不是回车键*/ {
c=getch();/*接收字符后开始各个方向的探索*/ if(c=='w'&&map[x-1][y]!=1) DrawPeople(&x,&y,1);/*上*/ else if(c=='e'&&map[x-1][y+1]!=1) DrawPeople(&x,&y,2);/*右上*/ else if(c=='d'&&map[x][y+1]!=1) DrawPeople(&x,&y,3);/*右*/ else if(c=='c'&&map[x+1][y+1]!=1) DrawPeople(&x,&y,4);/*右下*/ else if(c=='x'&&map[x+1][y]!=1) DrawPeople(&x,&y,5);/*下*/ else if(c=='z'&&map[x+1][y-1]!=1) DrawPeople(&x,&y,6); /*左下*/ else if(c=='a'&&map[x][y-1]!=1) DrawPeople(&x,&y,7); /*左*/ else if(c=='q'&&map[x-1][y-1]!=1) DrawPeople(&x,&y,8); /*左上*/ }
setfillstyle(SOLID_FILL,WHITE); /*消去红色探索物,恢复原迷宫图*/ bar(100+y*15-6,50+x*15-6,100+y*15+6,50+x*15+6); if(x==N-2&&y==N-2)/*人工控制找成功的话*/ yes=1; /*如果成功标志为1*/ }
void WayCopy(int (*oldmap)[N],int (*map)[N])/*拷贝迷宫数组 */ {
int i,j;
for(i=0;i<N;i++) for(j=0;j<N;j++) oldmap[i][j]=map[i][j]; }
int FindWay(int (*map)[N],int i,int j)/*递归找路*/ {
if(i==N-2&&j==N-2)/*走到出口*/ {
yes=1;/*标志为1,表示成功*/ return; }
map[i][j]=1;/*走过的地方变为1*/ WayCopy(oldmap,map); /*拷贝迷宫图*/
if(oldmap[i+1][j+1]==0&&!yes)/*判断右下方是否可走*/ {
FindWay(oldmap,i+1,j+1); if(yes)/*如果到达出口了,再把值赋给显示路线的way数组,也正是这个原因,所以具体路线是从最后开始保存*/ { way[wayn][0]=i; way[wayn++][1]=j; return; } }
WayCopy(oldmap,map);
if(oldmap[i+1][j]==0&&!yes)/*判断下方是否可以走,如果标志yes已经是1也不用找下去了*/ {
FindWay(oldmap,i+1,j); if(yes) { way[wayn][0]=i; way[wayn++][1]=j; return; } }
WayCopy(oldmap,map);
if(oldmap[i][j+1]==0&&!yes)/*判断右方是否可以走*/ {
FindWay(oldmap,i,j+1); if(yes) { way[wayn][0]=i; way[wayn++][1]=j; return; } }
WayCopy(oldmap,map);
if(oldmap[i-1][j]==0&&!yes)/*判断上方是否可以走*/ {
FindWay(oldmap,i-1,j); if(yes) { way[wayn][0]=i; way[wayn++][1]=j; return; } }
WayCopy(oldmap,map);
if(oldmap[i-1][j+1]==0&&!yes)/*判断右上方是否可以走*/ {
FindWay(oldmap,i-1,j+1); if(yes) { way[wayn][0]=i; way[wayn++][1]=j; return; } }
WayCopy(oldmap,map);
if(oldmap[i+1][j-1]==0&&!yes)/*判断左下方是否可以走*/ {
FindWay(oldmap,i+1,j-1); if(yes) { way[wayn][0]=i; way[wayn++][1]=j; return; } }
WayCopy(oldmap,map);
if(oldmap[i][j-1]==0&&!yes)/*判断左方是否可以走*/ {
FindWay(oldmap,i,j-1); if(yes) { way[wayn][0]=i; way[wayn++][1]=j; return; } }
WayCopy(oldmap,map);
if(oldmap[i-1][j-1]==0&&!yes)/*判断左上方是否可以走*/ {
FindWay(oldmap,i-1,j-1); if(yes) { way[wayn][0]=i; way[wayn++][1]=j; return; } }
return; }
void MapRand(int (*map)[N])/*开始的随机迷宫图*/ {
int i,j;
cleardevice();/*清屏*/
randomize(); /*随机数发生器*/ for(i=0;i<N;i++) {
for(j=0;j<N;j++) { if(i==0||i==N-1||j==0||j==N-1)/*最外面一圈为墙壁*/ map[i][j]=1; else if(i==1&&j==1||i==N-2&&j==N-2)/*出发点与终点表示为可走的*/ map[i][j]=0; else map[i][j]=random(2);/*其它的随机生成0或1*/ } } }
void PrMap(int (*map)[N])/*输出迷宫图*/ {
int i,j;
for(i=0;i<N;i++) for(j=0;j<N;j++) if(map[i][j]==0) { setfillstyle(SOLID_FILL,WHITE);/*白色为可走的路*/ bar(100+j*15-6,50+i*15-6,100+j*15+6,50+i*15+6); } else { setfillstyle(SOLID_FILL,BLUE);/*蓝色为墙壁*/ bar(100+j*15-6,50+i*15-6,100+j*15+6,50+i*15+6);
} }
void Find(void)/*找到通路*/ {
int i;
setfillstyle(SOLID_FILL,RED);/*红色输出走的具体路线*/ wayn--;
for(i=wayn;i>=0;i--) {
bar(100+way[i][1]*15-6,50+way[i][0]*15-6,100+ way[i][1]*15+6,50+way[i][0]*15+6); sleep(1);/*控制显示时间*/ }
bar(100+(N-2)*15-6,50+(N-2)*15-6,100+ (N-2)*15+6,50+(N-2)*15+6); /*在目标点标红色*/ setcolor(GREEN);
settextstyle(0,0,2);/*设置字体大小*/ outtextxy(130,400,"Find a way!"); }
void NotFind(void)/*没找到通路*/ {
setcolor(GREEN);
settextstyle(0,0,2);/*设置字体大小*/ outtextxy(130,400,"Not find a way!"); }
void Result(void)/*结果处理*/ {
if(yes)/*如果找到*/ Find();
else/*没找到路*/ NotFind(); getch(); }
void Close(void)/*图形关闭*/ {
closegraph(); }
‘伍’ c语言程序设计的迷宫
这个可行的
/*4.3.3源程序*/
#include
<graphics.h>
#include
<stdlib.h>
#include
<stdio.h>
#include
<conio.h>
#include
<dos.h>
#define
N
20/*迷宫的大小,可改变*/
int
oldmap[N][N];/*递归用的数组,用全局变量节约时间*/
int
yes=0;/*yes是判断是否找到路的标志,1找到,0没找到*/
int
way[100][2],wayn=0;/*way数组是显示路线用的,wayn是统计走了几个格子*/
void
Init(void);/*图形初始化*/
void
Close(void);/*图形关闭*/
void
DrawPeople(int
*x,int
*y,int
n);/*画人工探索物图*/
void
PeopleFind(int
(*x)[N]);/*人工探索*/
void
WayCopy(int
(*x)[N],int
(*y)[N]);/*为了8个方向的递归,把旧迷宫图拷贝给新数组*/
int
FindWay(int
(*x)[N],int
i,int
j);/*自动探索函数*/
void
MapRand(int
(*x)[N]);/*随机生成迷宫函数*/
void
PrMap(int
(*x)[N]);/*输出迷宫图函数*/
void
Result(void);/*输出结果处理*/
void
Find(void);/*成功处理*/
void
NotFind(void);/*失败处理*/
void
main(void)/*主函数*/
{
int
map[N][N];
/*迷宫数组*/
char
ch;
clrscr();
printf("\n
Please
select
hand(1)
else
auto\n");/*选择探索方式*/
scanf("%c",&ch);
Init();
/*初始化*/
MapRand(map);/*生成迷宫*/
PrMap(map);/*显示迷宫图*/
if(ch=='1')
PeopleFind(map);/*人工探索*/
else
FindWay(map,1,1);/*系统自动从下标1,1的地方开始探索*/
Result();/*输出结果*/
Close();
}
void
Init(void)/*图形初始化*/
{
int
gd=DETECT,gm;
initgraph(&gd,&gm,"c:\\tc");
}
void
DrawPeople(int
*x,int
*y,int
n)/*画人工控制图*/
{/*如果将以下两句注释掉,则显示人工走过的路径,*/
setfillstyle(SOLID_FILL,WHITE);
/*设置白色实体填充样式*/
bar(100+(*y)*15-6,50+(*x)*15-6,100+(*y)*15+6,50+(*x)*15+6);
/*恢复原通路*/
switch(n)/*判断x,y的变化,8个方向的变化*/
{
case
1:
(*x)--;break;
/*上*/
case
2:
(*x)--;(*y)++;break
;/*右上*/
case
3:
(*y)++;break;
/*右*/
case
4:
(*x)++;(*y)++;break;
/*右下*/
case
5:
(*x)++;break;
/*下*/
case
6:
(*x)++;(*y)--;break;
/*左下*/
case
7:
(*y)--;break;
/*左*/
case
8:
(*x)--;(*y)--;break;
/*左上*/
}
setfillstyle(SOLID_FILL,RED);/*新位置显示探索物*/
bar(100+(*y)*15-6,50+(*x)*15-6,100+(*y)*15+6,50+(*x)*15+6);
}
void
PeopleFind(int
(*map)[N])/*人工手动查找*/
{
int
x,y;
char
c=0;/*接收按键的变量*/
x=y=1;/*人工查找的初始位置*/
setcolor(11);
line(500,200,550,200);
outtextxy(570,197,"d");
line(500,200,450,200);
outtextxy(430,197,"a");
line(500,200,500,150);
outtextxy(497,130,"w");
line(500,200,500,250);
outtextxy(497,270,"x");
line(500,200,450,150);
outtextxy(445,130,"q");
line(500,200,550,150);
outtextxy(550,130,"e");
line(500,200,450,250);
outtextxy(445,270,"z");
line(500,200,550,250);
outtextxy(550,270,"c");/*以上是画8个方向的控制介绍*/
setcolor(YELLOW);
outtextxy(420,290,"Press
'Enter'
to
end");/*压回车键结束*/
setfillstyle(SOLID_FILL,RED);
bar(100+y*15-6,50+x*15-6,100+y*15+6,50+x*15+6);/*入口位置显示*/
while(c!=13)/*如果按下的不是回车键*/
{
c=getch();/*接收字符后开始各个方向的探索*/
if(c=='w'&&map[x-1][y]!=1)
DrawPeople(&x,&y,1);/*上*/
else
if(c=='e'&&map[x-1][y+1]!=1)
DrawPeople(&x,&y,2);/*右上*/
else
if(c=='d'&&map[x][y+1]!=1)
DrawPeople(&x,&y,3);/*右*/
else
if(c=='c'&&map[x+1][y+1]!=1)
DrawPeople(&x,&y,4);/*右下*/
else
if(c=='x'&&map[x+1][y]!=1)
DrawPeople(&x,&y,5);/*下*/
else
if(c=='z'&&map[x+1][y-1]!=1)
DrawPeople(&x,&y,6);
/*左下*/
else
if(c=='a'&&map[x][y-1]!=1)
DrawPeople(&x,&y,7);
/*左*/
else
if(c=='q'&&map[x-1][y-1]!=1)
DrawPeople(&x,&y,8);
/*左上*/
}
setfillstyle(SOLID_FILL,WHITE);
/*消去红色探索物,恢复原迷宫图*/
bar(100+y*15-6,50+x*15-6,100+y*15+6,50+x*15+6);
if(x==N-2&&y==N-2)/*人工控制找成功的话*/
yes=1;
/*如果成功标志为1*/
}
void
WayCopy(int
(*oldmap)[N],int
(*map)[N])/*拷贝迷宫数组
*/
{
int
i,j;
for(i=0;i<N;i++)
for(j=0;j<N;j++)
oldmap[i][j]=map[i][j];
}
int
FindWay(int
(*map)[N],int
i,int
j)/*递归找路*/
{
if(i==N-2&&j==N-2)/*走到出口*/
{
yes=1;/*标志为1,表示成功*/
return;
}
map[i][j]=1;/*走过的地方变为1*/
WayCopy(oldmap,map);
/*拷贝迷宫图*/
if(oldmap[i+1][j+1]==0&&!yes)/*判断右下方是否可走*/
{
FindWay(oldmap,i+1,j+1);
if(yes)/*如果到达出口了,再把值赋给显示路线的way数组,也正是这个原因,所以具体路线是从最后开始保存*/
{
way[wayn][0]=i;
way[wayn++][1]=j;
return;
}
}
WayCopy(oldmap,map);
if(oldmap[i+1][j]==0&&!yes)/*判断下方是否可以走,如果标志yes已经是1也不用找下去了*/
{
FindWay(oldmap,i+1,j);
if(yes)
{
way[wayn][0]=i;
way[wayn++][1]=j;
return;
}
}
WayCopy(oldmap,map);
if(oldmap[i][j+1]==0&&!yes)/*判断右方是否可以走*/
{
FindWay(oldmap,i,j+1);
if(yes)
{
way[wayn][0]=i;
way[wayn++][1]=j;
return;
}
}
WayCopy(oldmap,map);
if(oldmap[i-1][j]==0&&!yes)/*判断上方是否可以走*/
{
FindWay(oldmap,i-1,j);
if(yes)
{
way[wayn][0]=i;
way[wayn++][1]=j;
return;
}
}
WayCopy(oldmap,map);
if(oldmap[i-1][j+1]==0&&!yes)/*判断右上方是否可以走*/
{
FindWay(oldmap,i-1,j+1);
if(yes)
{
way[wayn][0]=i;
way[wayn++][1]=j;
return;
}
}
WayCopy(oldmap,map);
if(oldmap[i+1][j-1]==0&&!yes)/*判断左下方是否可以走*/
{
FindWay(oldmap,i+1,j-1);
if(yes)
{
way[wayn][0]=i;
way[wayn++][1]=j;
return;
}
}
WayCopy(oldmap,map);
if(oldmap[i][j-1]==0&&!yes)/*判断左方是否可以走*/
{
FindWay(oldmap,i,j-1);
if(yes)
{
way[wayn][0]=i;
way[wayn++][1]=j;
return;
}
}
WayCopy(oldmap,map);
if(oldmap[i-1][j-1]==0&&!yes)/*判断左上方是否可以走*/
{
FindWay(oldmap,i-1,j-1);
if(yes)
{
way[wayn][0]=i;
way[wayn++][1]=j;
return;
}
}
return;
}
void
MapRand(int
(*map)[N])/*开始的随机迷宫图*/
{
int
i,j;
cleardevice();/*清屏*/
randomize();
/*随机数发生器*/
for(i=0;i<N;i++)
{
for(j=0;j<N;j++)
{
if(i==0||i==N-1||j==0||j==N-1)/*最外面一圈为墙壁*/
map[i][j]=1;
else
if(i==1&&j==1||i==N-2&&j==N-2)/*出发点与终点表示为可走的*/
map[i][j]=0;
else
map[i][j]=random(2);/*其它的随机生成0或1*/
}
}
}
void
PrMap(int
(*map)[N])/*输出迷宫图*/
{
int
i,j;
for(i=0;i<N;i++)
for(j=0;j<N;j++)
if(map[i][j]==0)
{
setfillstyle(SOLID_FILL,WHITE);/*白色为可走的路*/
bar(100+j*15-6,50+i*15-6,100+j*15+6,50+i*15+6);
}
else
{
setfillstyle(SOLID_FILL,BLUE);/*蓝色为墙壁*/
bar(100+j*15-6,50+i*15-6,100+j*15+6,50+i*15+6);
}
}
void
Find(void)/*找到通路*/
{
int
i;
setfillstyle(SOLID_FILL,RED);/*红色输出走的具体路线*/
wayn--;
for(i=wayn;i>=0;i--)
{
bar(100+way[i][1]*15-6,50+way[i][0]*15-6,100+
way[i][1]*15+6,50+way[i][0]*15+6);
sleep(1);/*控制显示时间*/
}
bar(100+(N-2)*15-6,50+(N-2)*15-6,100+
(N-2)*15+6,50+(N-2)*15+6);
/*在目标点标红色*/
setcolor(GREEN);
settextstyle(0,0,2);/*设置字体大小*/
outtextxy(130,400,"Find
a
way!");
}
void
NotFind(void)/*没找到通路*/
{
setcolor(GREEN);
settextstyle(0,0,2);/*设置字体大小*/
outtextxy(130,400,"Not
find
a
way!");
}
void
Result(void)/*结果处理*/
{
if(yes)/*如果找到*/
Find();
else/*没找到路*/
NotFind();
getch();
}
void
Close(void)/*图形关闭*/
{
closegraph();
}
‘陆’ 谁有C语言,生成随机迷宫的代码
#include<stdio.h>
#include<conio.h>
#include<windows.h>
#include<time.h>
#defineHeight31//迷宫的高度,必须为奇数
#defineWidth25//迷宫的宽度,必须为奇数
#defineWall1
#defineRoad0
#defineStart2
#defineEnd3
#defineEsc5
#defineUp1
#defineDown2
#defineLeft3
#defineRight4
intmap[Height+2][Width+2];
voidgotoxy(intx,inty)//移动坐标
{
COORDcoord;
coord.X=x;
coord.Y=y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),coord);
}
voidhidden()//隐藏光标
{
HANDLEhOut=GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFOcci;
GetConsoleCursorInfo(hOut,&cci);
cci.bVisible=0;//赋1为显示,赋0为隐藏
SetConsoleCursorInfo(hOut,&cci);
}
voidcreate(intx,inty)//随机生成迷宫
{
intc[4][2]={0,1,1,0,0,-1,-1,0};//四个方向
inti,j,t;
//将方向打乱
for(i=0;i<4;i++)
{
j=rand()%4;
t=c[i][0];c[i][0]=c[j][0];c[j][0]=t;
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)
{
map[x+c[i][0]][y+c[i][1]]=Road;
create(x+2*c[i][0],y+2*c[i][1]);
}
}
intget_key()//接收按键
{
charc;
while(c=getch())
{
if(c==27)returnEsc;//Esc
if(c!=-32)continue;
c=getch();
if(c==72)returnUp;//上
if(c==80)returnDown;//下
if(c==75)returnLeft;//左
if(c==77)returnRight;//右
}
return0;
}
voidpaint(intx,inty)//画迷宫
{
gotoxy(2*y-2,x-1);
switch(map[x][y])
{
caseStart:
printf("入");break;//画入口
caseEnd:
printf("出");break;//画出口
caseWall:
printf("※");break;//画墙
caseRoad:
printf("");break;//画路
}
}
voidgame()
{
intx=2,y=1;//玩家当前位置,刚开始在入口处
intc;//用来接收按键
while(1)
{
gotoxy(2*y-2,x-1);
printf("☆");//画出玩家当前位置
if(map[x][y]==End)//判断是否到达出口
{
gotoxy(30,24);
printf("到达终点,按任意键结束");
getch();
break;
}
c=get_key();
if(c==Esc)
{
gotoxy(0,24);
break;
}
switch(c)
{
caseUp://向上走
if(map[x-1][y]!=Wall)
{
paint(x,y);
x--;
}
break;
caseDown://向下走
if(map[x+1][y]!=Wall)
{
paint(x,y);
x++;
}
break;
caseLeft://向左走
if(map[x][y-1]!=Wall)
{
paint(x,y);
y--;
}
break;
caseRight://向右走
if(map[x][y+1]!=Wall)
{
paint(x,y);
y++;
}
break;
}
}
}
intmain()
{
inti,j;
srand((unsigned)time(NULL));//初始化随即种子
hidden();//隐藏光标
for(i=0;i<=Height+1;i++)
for(j=0;j<=Width+1;j++)
if(i==0||i==Height+1||j==0||j==Width+1)//初始化迷宫
map[i][j]=Road;
elsemap[i][j]=Wall;
create(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;//给定入口
map[Height-1][Width]=End;//给定出口
for(i=1;i<=Height;i++)
for(j=1;j<=Width;j++)//画出迷宫
paint(i,j);
game();//开始游戏
getch();
return0;
}
‘柒’ 怎样生成随机迷宫
首先,必须保证有一条可以通过的路。
大概思路:从数组的任一边界开始将数组值设为0,然后利用随机值设置随机方向,如果方向上已有0,则继续随机,只到找到边界为止。
生成可以通行的路之后,其它的就比较随意了,看你喜欢怎么处理了。
‘捌’ 在进行深度优先遍历随机创建迷宫时,怎么寻找某一个单元格的邻接单元格
变量 head 和 tail 是队头和队尾指针, head 总是指向队头, tail 总是指向队尾的下一个元素。每个点的 predecessor 成员也是一个指针,指向它的前趋在 queue 数组中的位置。如下图所示:
广度优先是一种步步为营的策略,每次都从各个方向探索一步,将前线推进一步,图中的虚线就表示这个前线,队列中的元素总是由前线的点组成的,可见正是队列先进先出的性质使这个算法具有了广度优先的特点。广度优先搜索还有一个特点是可以找到从起点到终点的最短路径,而深度优先搜索找到的不一定是最短路径。
#include <stdio.h>
#define MAX_ROW 5
#define MAX_COL 5
struct point { int row, col, predecessor; } queue[512];
int head = 0, tail = 0;
void enqueue(struct point p)
{
queue[tail++] = p;
}
struct point dequeue(void)
{
return queue[head++];
}
int is_empty(void)
{
return head == tail;
}
int maze[MAX_ROW][MAX_COL] = {
0, 1, 0, 0, 0,
0, 1, 0, 1, 0,
0, 0, 0, 0, 0,
0, 1, 1, 1, 0,
0, 0, 0, 1, 0,
};
void print_maze(void)
{
int i, j;
for (i = 0; i < MAX_ROW; i++) {
for (j = 0; j < MAX_COL; j++)
printf("%d ", maze[i][j]);
putchar('\n');
}
printf("*********\n");
}
void visit(int row, int col)
{
struct point visit_point = { row, col, head-1 };
maze[row][col] = 2;
enqueue(visit_point);
}
int main(void)
{
struct point p = { 0, 0, -1 };
maze[p.row][p.col] = 2;
enqueue(p);
while (!is_empty()) {
p = dequeue();
if (p.row == MAX_ROW - 1 /* goal */
&& p.col == MAX_COL - 1)
break;
if (p.col+1 < MAX_COL /* right */
&& maze[p.row][p.col+1] == 0)
visit(p.row, p.col+1);
if (p.row+1 < MAX_ROW /* down */
&& maze[p.row+1][p.col] == 0)
visit(p.row+1, p.col);
if (p.col-1 >= 0 /* left */
&& maze[p.row][p.col-1] == 0)
visit(p.row, p.col-1);
if (p.row-1 >= 0 /* up */
&& maze[p.row-1][p.col] == 0)
visit(p.row-1, p.col);
print_maze();
}
if (p.row == MAX_ROW - 1 && p.col == MAX_COL - 1)
{
printf("(%d, %d)\n", p.row, p.col);
while (p.predecessor != -1) {
p = queue[p.predecessor];
printf("(%d, %d)\n", p.row, p.col);
}
} else
printf("No path!\n");
return 0;
}
‘玖’ 随机迷宫
#define OVERFLOW -2
#define ERROR 0
#define NULL 0
#define true 1
#define TRUE 1
#define false 0
#define FALSE 0
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
#include <stdio.h>
#include <stdlib.h>
/*
初始化迷宫,1表示通道,0表示墙
*/
int maze[8][8] = {
1,1,0,1,1,1,0,1,
1,1,0,1,1,1,0,1,
1,1,1,1,0,0,1,1,
1,0,0,0,1,1,1,1,
1,1,1,0,1,1,1,1,
1,0,1,1,1,0,1,1,
1,0,0,0,1,0,0,1,
0,1,1,1,1,1,1,1
};
//定义栈元素类型
typedef struct MStackElem
{
int x;//x坐标
int y;//y坐标
int val;//maze[x][y]的值
}MStackElem;
//定义栈
typedef struct {
MStackElem * base;
MStackElem * top;
int stackSize;
}MStack;
//=============Stack的实现========================
//初始化栈-------构造一个空栈
void initStack(MStack *s) {
s->base = (MStackElem *)malloc(STACK_INIT_SIZE * sizeof(MStackElem));
if (!s->base) {
printf("in initStack()...Failed to initalize the MStack ,no enough space! exit now. ");
exit(OVERFLOW);//存储分配失败
}
s->top = s->base;
s->stackSize = STACK_INIT_SIZE;
}
//向栈中添加元素
void push(MStack *s,MStackElem e) {
//向栈中添加元素前先判断栈是否还有空间容纳新元素
if (s->top - s->base >= s->stackSize) { //栈满,追加元素
s->base = (MStackElem *)realloc(s->base, (STACK_INIT_SIZE+STACKINCREMENT) * sizeof(MStackElem));
if (!s->base) {
printf("in push()...Failed to realloc the MStack ,no enough space! exit now. ");
exit(OVERFLOW);//存储分配失败
}
s->top = s->base + s->stackSize; //因为是重新分配了空间,所以base的值其实已经改变,所以top的值也就相应的改变,才能指向新的迷宫栈
s->stackSize += STACKINCREMENT;
}
//将新元素加到栈顶
*(s->top++) = e;
}
//获得栈顶元素
MStackElem getTop(MStack *s) {
if (s->top == s->base) {
printf("in getTop(),empty stack! exit now. ");
exit(ERROR);
}
else {
return *(s->top - 1);
}
}
//删除栈顶元素
void pop(MStack *s) {
//若栈不为空,则删除s的栈顶元素
if (s->top == s->base) {
printf("in pop(),empty stack! exit now. ");
exit(ERROR);
}
else {
--(s->top);
}
}
//=====================================求解迷宫的相关操作=====================//
//构造两个栈,一个用来保存探索中的全部路径,一个用来保存有效路径
MStack realPath,path;
//判断当前位置是否走过
int unPass(MStack path,MStackElem cur) {//这里不能传path的地址,否则在遍历过程中它的top值就真的被改了 !!
int flag = 1;
while(path.top != path.base)
{
MStackElem e = *(path.top - 1);
if (e.x == cur.x&& e.y == cur.y)
{
flag = 0;
}
//每循环一次令头指针下移一个位置
(path.top)--;
}
return flag;
}
//获得东面相邻的位置
MStackElem getEast(MStackElem cur) {
if(cur.y != 7) {//当y==7时已到了迷宫右边界,不能再向东(右)行了
cur.y += 1;
cur.val = maze[cur.x][cur.y];
}
return cur;// 当y==7时返回的是它本身
}
//获得南面相邻的位置
MStackElem getSouth(MStackElem cur) {
if(cur.x != 7) {//当x==7时已到了迷宫下边界,不能再向南(下)行了
cur.x += 1;
cur.val = maze[cur.x][cur.y];
}
return cur;// 当x==7时返回的是它本身
}
//获得西面相邻的位置
MStackElem getWest(MStackElem cur) {
if(cur.y != 0) {//当y==0时已到了迷宫左边界,不能再向西(左)行了
cur.y -= 1;
cur.val = maze[cur.x][cur.y];
}
return cur;// 当y==0时返回的是它本身
}
//获得北面相邻的位置
MStackElem getNorth(MStackElem cur) {
if(cur.x != 0) {//当cur.x==0时表示在迷宫的上边界,不能再向北(上)行了
cur.x -= 1;
cur.val = maze[cur.x][cur.y];
}
return cur;// 当cur.x==0时返回的还是它本身
}
//获得下一个可通行的位置,按东南西北的方向试探
MStackElem getNext(MStackElem cur) {
MStackElem next;
next.x = next.y=next.val = -1;
if(getEast(cur).val != 0 && unPass(path,getEast(cur))) {
next = getEast(cur);
}
else if(getSouth(cur).val != 0 && unPass(path,getSouth(cur))) {
next = getSouth(cur);
}
else if(getWest(cur).val != 0 && unPass(path,getWest(cur))) {
next = getWest(cur);
}
else if(getNorth(cur).val != 0 && unPass(path,getNorth(cur))) {
next = getNorth(cur);
}
//如果当前位置的四面或为墙或已走过,则返回的next的val值为-1
return next;
}
int getMazePath(){//获得迷宫路径的函数
MStackElem start,end,cur;
start.x = 0;
start.y = 0;
start.val = maze[start.x][start.y];
end.x = 7;
end.y = 7;
end.val = maze[end.x][end.y];
cur = start; //设定当前为位置为"入口位置"
//没有重载=运算符,可以这样用吗,结果对吗?试试吧:
/*
printf("%d",cur.x);
printf("%d",cur.y);
printf("%d",cur.val);
*/
//恩,结果是正确的,即可以通过cur=start来把start的值赋给cur.
//对了,想起来了,记得以前在学C++的复制构造函数时书上好像说过, 用=(等号)复制类对象时系统会调用由系统提供的复制的构造函数什么的,
//唉,记不清了,还是基础不扎实啊,以后可不能轻视基础了@_@ ...
do
{
if (unPass(path,cur)) {//如果当前位置未曾走到过
push(&realPath,cur);
push(&path,cur);
cur = getNext(cur);
if (cur.x == end.x && cur.y == end.y) { //到达出口了,则跳出循环,并返回true
//把出口结点放入路径中
push(&realPath,cur);
push(&path,cur);
//直接跳出函数(而不只是跳出这个循环 )
return true;
}
else if(cur.val == -1) {//当前位置的四面或为墙或已走过
//删除真实路径的栈顶元素
pop(&realPath);
cur = getTop(&realPath);//令cur指向栈顶元素
}
}
else {//如果当前位置已经走过,说明原来测试的方向不对,现在尝试其它方向
cur = getNext(cur);
if (cur.val == -1) {//仍不通,删除真实路径的栈顶元素
pop(&realPath);
cur = getTop(&realPath);//令cur指向栈顶元素
}
}
} while (cur.x != end.x || cur.y != end.y);
}
//打印迷宫路径
void printMazePath(MStack *s) {//为了安全,这里不传MStack的地址,以防在遍历的过程中把它们的top或base的值也修改了
/*注:这种方法实际是倒序打印出路径,让人看着别扭,所以我用下面的方法"倒序遍历这个栈 '
while (s->top != s->base) {
MStackElem e = *(s->top-1);
printf("maze[%d][%d]----->",e.x,e.y);
(s->top)--;
}
*/
MStackElem e;
while (s->base < (s->top-1)) {
e = *(s->base);//先指向栈底元素,以后依次向上增1
printf("maze[%d][%d]----->",e.x,e.y);
(s->base)++;
}
//最后一个结点没有后继,所以不再输出"------>"
e = *(s->base);
printf("maze[%d][%d]",e.x,e.y);
}
main(){
//初始化栈
initStack(&realPath);
initStack(&path);
getMazePath();
printf("The path of through the maze is:\n\n");
printMazePath(&realPath);
getchar();
}
‘拾’ 用数据结构解迷宫
#include <graphics.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <dos.h>
#define N 20/*迷宫的大小,可改变*/
int oldmap[N][N];/*递归用的数组,用全局变量节约时间*/
int yes=0;/*yes是判断是否找到路的标志,1找到,0没找到*/
int way[100][2],wayn=0;/*way数组是显示路线用的,wayn是统计走了几个格子*/
void Init(void);/*图形初始化*/
void Close(void);/*图形关闭*/
void DrawPeople(int *x,int *y,int n);/*画人工探索物图*/
void PeopleFind(int (*x)[N]);/*人工探索*/
void WayCopy(int (*x)[N],int (*y)[N]);/*为了8个方向的递归,把旧迷宫图拷贝给新数组*/
int FindWay(int (*x)[N],int i,int j);/*自动探索函数*/
void MapRand(int (*x)[N]);/*随机生成迷宫函数*/
void PrMap(int (*x)[N]);/*输出迷宫图函数*/
void Result(void);/*输出结果处理*/
void Find(void);/*成功处理*/
void NotFind(void);/*失败处理*/
void main(void)/*主函数*/
{
int map[N][N]; /*迷宫数组*/
char ch;
clrscr();
printf("\n Please select hand(1) else auto\n");/*选择探索方式*/
scanf("%c",&ch);
Init(); /*初始化*/
MapRand(map);/*生成迷宫*/
PrMap(map);/*显示迷宫图*/
if(ch=='1')
PeopleFind(map);/*人工探索*/
else
FindWay(map,1,1);/*系统自动从下标1,1的地方开始探索*/
Result();/*输出结果*/
Close();
}
void Init(void)/*图形初始化*/
{
int gd=DETECT,gm;
initgraph(&gd,&gm,"c:\\tc");
}
void DrawPeople(int *x,int *y,int n)/*画人工控制图*/
{/*如果将以下两句注释掉,则显示人工走过的路径,*/
setfillstyle(SOLID_FILL,WHITE); /*设置白色实体填充样式*/
bar(100+(*y)*15-6,50+(*x)*15-6,100+(*y)*15+6,50+(*x)*15+6);
/*恢复原通路*/
switch(n)/*判断x,y的变化,8个方向的变化*/
{
case 1: (*x)--;break; /*上*/
case 2: (*x)--;(*y)++;break ;/*右上*/
case 3: (*y)++;break; /*右*/
case 4: (*x)++;(*y)++;break; /*右下*/
case 5: (*x)++;break; /*下*/
case 6: (*x)++;(*y)--;break; /*左下*/
case 7: (*y)--;break; /*左*/
case 8: (*x)--;(*y)--;break; /*左上*/
}
setfillstyle(SOLID_FILL,RED);/*新位置显示探索物*/
bar(100+(*y)*15-6,50+(*x)*15-6,100+(*y)*15+6,50+(*x)*15+6);
}
void PeopleFind(int (*map)[N])/*人工手动查找*/
{
int x,y;
char c=0;/*接收按键的变量*/
x=y=1;/*人工查找的初始位置*/
setcolor(11);
line(500,200,550,200);
outtextxy(570,197,"d");
line(500,200,450,200);
outtextxy(430,197,"a");
line(500,200,500,150);
outtextxy(497,130,"w");
line(500,200,500,250);
outtextxy(497,270,"x");
line(500,200,450,150);
outtextxy(445,130,"q");
line(500,200,550,150);
outtextxy(550,130,"e");
line(500,200,450,250);
outtextxy(445,270,"z");
line(500,200,550,250);
outtextxy(550,270,"c");/*以上是画8个方向的控制介绍*/
setcolor(YELLOW);
outtextxy(420,290,"Press 'Enter' to end");/*压回车键结束*/
setfillstyle(SOLID_FILL,RED);
bar(100+y*15-6,50+x*15-6,100+y*15+6,50+x*15+6);/*入口位置显示*/
while(c!=13)/*如果按下的不是回车键*/
{
c=getch();/*接收字符后开始各个方向的探索*/
if(c=='w'&&map[x-1][y]!=1)
DrawPeople(&x,&y,1);/*上*/
else
if(c=='e'&&map[x-1][y+1]!=1)
DrawPeople(&x,&y,2);/*右上*/
else
if(c=='d'&&map[x][y+1]!=1)
DrawPeople(&x,&y,3);/*右*/
else
if(c=='c'&&map[x+1][y+1]!=1)
DrawPeople(&x,&y,4);/*右下*/
else
if(c=='x'&&map[x+1][y]!=1)
DrawPeople(&x,&y,5);/*下*/
else
if(c=='z'&&map[x+1][y-1]!=1)
DrawPeople(&x,&y,6); /*左下*/
else
if(c=='a'&&map[x][y-1]!=1)
DrawPeople(&x,&y,7); /*左*/
else if(c=='q'&&map[x-1][y-1]!=1)
DrawPeople(&x,&y,8); /*左上*/
}
setfillstyle(SOLID_FILL,WHITE); /*消去红色探索物,恢复原迷宫图*/
bar(100+y*15-6,50+x*15-6,100+y*15+6,50+x*15+6);
if(x==N-2&&y==N-2)/*人工控制找成功的话*/
yes=1; /*如果成功标志为1*/
}
void WayCopy(int (*oldmap)[N],int (*map)[N])/*拷贝迷宫数组 */
{
int i,j;
for(i=0;i<N;i++)
for(j=0;j<N;j++)
oldmap[i][j]=map[i][j];
}
int FindWay(int (*map)[N],int i,int j)/*递归找路*/
{
if(i==N-2&&j==N-2)/*走到出口*/
{
yes=1;/*标志为1,表示成功*/
return;
}
map[i][j]=1;/*走过的地方变为1*/
WayCopy(oldmap,map); /*拷贝迷宫图*/
if(oldmap[i+1][j+1]==0&&!yes)/*判断右下方是否可走*/
{
FindWay(oldmap,i+1,j+1);
if(yes)/*如果到达出口了,再把值赋给显示路线的way数组,也正是这个原因,所以具体路线是从最后开始保存*/
{
way[wayn][0]=i;
way[wayn++][1]=j;
return;
}
}
WayCopy(oldmap,map);
if(oldmap[i+1][j]==0&&!yes)/*判断下方是否可以走,如果标志yes已经是1也不用找下去了*/
{
FindWay(oldmap,i+1,j);
if(yes)
{
way[wayn][0]=i;
way[wayn++][1]=j;
return;
}
}
WayCopy(oldmap,map);
if(oldmap[i][j+1]==0&&!yes)/*判断右方是否可以走*/
{
FindWay(oldmap,i,j+1);
if(yes)
{
way[wayn][0]=i;
way[wayn++][1]=j;
return;
}
}
WayCopy(oldmap,map);
if(oldmap[i-1][j]==0&&!yes)/*判断上方是否可以走*/
{
FindWay(oldmap,i-1,j);
if(yes)
{
way[wayn][0]=i;
way[wayn++][1]=j;
return;
}
}
WayCopy(oldmap,map);
if(oldmap[i-1][j+1]==0&&!yes)/*判断右上方是否可以走*/
{
FindWay(oldmap,i-1,j+1);
if(yes)
{
way[wayn][0]=i;
way[wayn++][1]=j;
return;
}
}
WayCopy(oldmap,map);
if(oldmap[i+1][j-1]==0&&!yes)/*判断左下方是否可以走*/
{
FindWay(oldmap,i+1,j-1);
if(yes)
{
way[wayn][0]=i;
way[wayn++][1]=j;
return;
}
}
WayCopy(oldmap,map);
if(oldmap[i][j-1]==0&&!yes)/*判断左方是否可以走*/
{
FindWay(oldmap,i,j-1);
if(yes)
{
way[wayn][0]=i;
way[wayn++][1]=j;
return;
}
}
WayCopy(oldmap,map);
if(oldmap[i-1][j-1]==0&&!yes)/*判断左上方是否可以走*/
{
FindWay(oldmap,i-1,j-1);
if(yes)
{
way[wayn][0]=i;
way[wayn++][1]=j;
return;
}
}
return;
}
void MapRand(int (*map)[N])/*开始的随机迷宫图*/
{
int i,j;
cleardevice();/*清屏*/
randomize(); /*随机数发生器*/
for(i=0;i<N;i++)
{
for(j=0;j<N;j++)
{
if(i==0||i==N-1||j==0||j==N-1)/*最外面一圈为墙壁*/
map[i][j]=1;
else
if(i==1&&j==1||i==N-2&&j==N-2)/*出发点与终点表示为可走的*/
map[i][j]=0;
else
map[i][j]=random(2);/*其它的随机生成0或1*/
}
}
}
void PrMap(int (*map)[N])/*输出迷宫图*/
{
int i,j;
for(i=0;i<N;i++)
for(j=0;j<N;j++)
if(map[i][j]==0)
{
setfillstyle(SOLID_FILL,WHITE);/*白色为可走的路*/
bar(100+j*15-6,50+i*15-6,100+j*15+6,50+i*15+6);
}
else
{
setfillstyle(SOLID_FILL,BLUE);/*蓝色为墙壁*/
bar(100+j*15-6,50+i*15-6,100+j*15+6,50+i*15+6);
}
}
void Find(void)/*找到通路*/
{
int i;
setfillstyle(SOLID_FILL,RED);/*红色输出走的具体路线*/
wayn--;
for(i=wayn;i>=0;i--)
{
bar(100+way[i][1]*15-6,50+way[i][0]*15-6,100+
way[i][1]*15+6,50+way[i][0]*15+6);
sleep(1);/*控制显示时间*/
}
bar(100+(N-2)*15-6,50+(N-2)*15-6,100+
(N-2)*15+6,50+(N-2)*15+6); /*在目标点标红色*/
setcolor(GREEN);
settextstyle(0,0,2);/*设置字体大小*/
outtextxy(130,400,"Find a way!");
}
void NotFind(void)/*没找到通路*/
{
setcolor(GREEN);
settextstyle(0,0,2);/*设置字体大小*/
outtextxy(130,400,"Not find a way!");
}
void Result(void)/*结果处理*/
{
if(yes)/*如果找到*/
Find();
else/*没找到路*/
NotFind();
getch();
}
void Close(void)/*图形关闭*/
{
closegraph();
}
另外一个,是数据结构的:
#include<stdio.h>
#define NUM 10/* 定义物品总数*/
#define CONTENT 10 /*定义包的容量*/
void knapsack(int v[NUM],int w[NUM],int c,int m[NUM ][CONTENT])
{
int n=NUM-1;
int i,j;
int jMax;
if((w[n]-1)< c)
jMax = w[n]-1;
else
jMax = c;
/* 初始化m[n][j] */
for(j = 0; j <= jMax; j++)
m[n][j] = 0;
for(j = jMax +1; j <= c; j++)
m[n][j] = v[n];
/*使用非递归的算法来求解m[i][j] */
for(i = n-1; i > 0; i--)
{
if((w[i]-1)< c)
jMax = w[i]-1;
else
jMax = c;
for(j = 0; j <= jMax; j++)
m[i][j] = m[i+1][j] ;
for(j = jMax +1; j <= c; j++)
{
if(m[i+1][j] >= (m[i+1][j-w[i]]+v[i]))
m[i][j] = m[i+1][j] ;
else
m[i][j] = m[i+1][j-w[i]]+v[i];
}
}
if(c>w[0])
{
if(m[1][c] >= (m[1][c-w[0]]+v[0]))
m[0][c]= m[1][c];
else
m[0][c]= m[1][c-w[0]]+v[0];
}
else
m[0][c]= m[1][c];
}
/*寻找最优解*/
void traceback(int flag[NUM],int w[NUM],int m[NUM][CONTENT])
{
int n = NUM -1;
int i;
int c = CONTENT;
for(i = 0; i < n; i++)
{
if(m[i][c] == m[i+1][c])
flag[i] = 0;
else
{
flag[i] = 1;
c-=w[i];
}
}
if(m[n][c] >0)
flag[n] = 1;
else
flag[n] = 0;
}
/* 打印最优解*/
void printResult(int flag[NUM],int w[NUM],int v[NUM],int m[NUM][CONTENT])
{
int i;
printf("the knapsack should contain:\n");
printf(" num weight value \n");
for(i = 0;i < NUM; i++)
{
if(flag[i] == 1)
printf(" %d %d %d\n",i,w[i],v[i]);
}
printf("the max value in the knapsack is: %d\n",m[0][CONTENT]);
}
int main()
{
int value[NUM]={5,2,3,4,3,6,5,7,8,2};
int weight[NUM]={2,1,3,2,4,3,5,6,2,2};
int c = CONTENT;
int maxvalue[NUM][CONTENT];
int flag[NUM]={0,0,0,0,0,0,0,0,0,0};
clrscr();
printf("****************************************\n");
printf("* this program will solve *\n");
printf("* the problem of 0-1knapsack *\n");
printf("****************************************\n");
/*计算最优值*/
knapsack(value,weight,c,maxvalue);
/*构造最优解*/
traceback(flag,weight,maxvalue);
/*打印程序的结果*/
printResult(flag,weight,value,maxvalue);
getch();
return 0;
}