数据结构(迷宫求解c++)

#include "sqstack.h"

Status InitStack(Stack &S)
{	
	S.top = 0 ; 
	for( int i = 0 ; i < MaxSize ; i++ ) 
	{ 
		S.data[i].di = 0 ; 
		S.data[i].ord = 0 ; 
		S.data[i].seat.c = 0; 
		S.data[i].seat.r = 0; 
	} 
return true; 	
}
Status DestroyStack(Stack &S)
{
	S.top = 0 ; 
	return true;
}
Status StackEmpty(Stack &S)
{
	if (S.top==0)
	return true; 
	else
	return false;
}
Status Push(Stack &S,SElemType &e)
{
	if(S.top<MaxSize){
		S.top++;
	S.data[S.top]=e;	
	return true;
	}
	else 
	return false;
	
}
Status Pop(Stack &S,SElemType &e)
{
	if(S.top>0){
		e=S.data[S.top];		
		S.top--;
	return true;
	}else 
	return false;
	
}




迷宫求解小游戏共三个头文件三个源文件,

下面先列出头文件再列出源文件:

#include <SDKDDKVer.h>
#pragma once
#define Status bool
#define TRUE true
#define FALSE false
struct PosType 
{
	int r,c;             //行列 or xy
};

typedef struct
{
	int ord;            //通道块在路径上的序号
	PosType seat;       //通道块在迷宫中的坐标位置
	int di;             //从此通道块走向下一通道块的方向
}SElemType;
extern bool drawflag;   //全局变量外部声明


 

#include <SDKDDKVer.h>
#pragma once
#define Status bool
#define TRUE true
#define FALSE false
struct PosType 
{
	int r,c;             //行列 or xy
};

typedef struct
{
	int ord;            //通道块在路径上的序号
	PosType seat;       //通道块在迷宫中的坐标位置
	int di;             //从此通道块走向下一通道块的方向
}SElemType;
extern bool drawflag;   //全局变量外部声明


 

#include <SDKDDKVer.h>
#include "selemtype.h"
#include "sqstack.h"
//#include "linkstack.h"
//迷宫大小
#define N 15
#define M 22
//分割块占总空间比例
#define V 0.4
typedef struct ElemType
{
	int x,y;
	char c;
}ElemType;
typedef struct MazeType
{
	ElemType arr[N][M];	
}MazeType;

Status Pass(MazeType &MyMaze, PosType CurPos);
void FootPrint(MazeType &MyMaze, PosType CurPos);
void MarkPrint(MazeType &MyMaze, PosType CurPos);
PosType NextPos(PosType CurPos, int Dir);

Status MazePath(MazeType &maze, PosType start, PosType end);
/*------------------------------------------------
    走迷宫算法v1.0
N            迷宫行数
M            迷宫列数
V            分割块占总空间比例
ElemType     迷宫元素类型
MazeType     迷宫类型

函数MazePath   走迷宫算法
函数Pass       判断当前位置是否可通过
函数FootPrint  留下足迹
函数MarkPrint  留下不能再走的标记
函数NextPos    计算下一位置
-------------------------------------------------*/
#include <iostream>
#include "MazePath.h"
Status MazePath(MazeType &maze, PosType start, PosType end)
{
	// 算法3.3
	// 若迷宫maze中从入口 start到出口 end的通道,则求得一条存放在栈中
	// (从栈底到栈顶),并返回TRUE;否则返回FALSE	    
	int curste=0;//记录所走的布数	
	Stack S;//定义一个栈
	InitStack(S);//实例化栈
	PosType curpos=start;//定义当前位置为开始位置
	SElemType e;
			
	do{	
		curste++;//探索下一步 
		if (Pass(maze,curpos)){//如果可以通过
			FootPrint(maze,curpos);//li留下已走过的印记
			e.di=1;
			e.ord=curste;
			e.seat=curpos;
			Push(S,e);//如果当前位置可以通过,入栈
			if (curpos.c==end.c&&curpos.r==end.r){//当前位置如果是终点
			return true;			
			}
			curpos=NextPos(curpos,1);//下一位置是但前位置的东临
			//curste++;//探索下一步 
		}else{//当前位置不能通过			
			if(!StackEmpty(S) ){
			    Pop(S,e);
				while(e.di==4&&!StackEmpty(S)){
				MarkPrint(maze,e.seat) ;//标记当前位置不能通过
				Pop(S,e);//出栈
				}
				if(e.di<4){
					e.di++;//换下一个方向探索					
					Push(S,e);
					curpos=NextPos(e.seat,e.di);//把当前位置的下一个方向作为探索下一目标					
				}
			
			}
		}
	
	}while(!StackEmpty(S));
	return false;
} // MazePath

Status Pass( MazeType &MyMaze,PosType CurPos) 
{
	if (MyMaze.arr[CurPos.r][CurPos.c].c==' ')
		return 1;     // 如果当前位置是可以通过,返回1
	else return 0;  // 其它情况返回0
}

void FootPrint(MazeType &MyMaze,PosType CurPos) 
{
	//循环是判断全局线程互斥变量的值,等待走步,
	//值为false,迷宫走步,并重新设为true,交给
	//主线程绘制,子线程等待
	while(drawflag)
		;
	drawflag=true;
	MyMaze.arr[CurPos.r][CurPos.c].c='*';
	
}

void MarkPrint(MazeType &MyMaze,PosType CurPos) 
{
	//循环是判断全局线程互斥变量的值,等待走步,
	//值为false,迷宫走步,并重新设为true,交给
	//主线程绘制,子线程等待
	while(drawflag)
		;
	drawflag=true;
	MyMaze.arr[CurPos.r][CurPos.c].c='!';
}

PosType NextPos(PosType CurPos, int Dir) 
{
	PosType ReturnPos; 
	switch (Dir) 
	{
    case 1:
        ReturnPos.r=CurPos.r;
        ReturnPos.c=CurPos.c+1;
        break;
    case 2:
        ReturnPos.r=CurPos.r+1;
        ReturnPos.c=CurPos.c;
        break;
    case 3:
        ReturnPos.r=CurPos.r;
        ReturnPos.c=CurPos.c-1;
        break;
    case 4:
        ReturnPos.r=CurPos.r-1;
        ReturnPos.c=CurPos.c;
        break;
	}
	return ReturnPos;
}


 

#include <iostream>
using namespace std;
#include "graphics.h"
#include <time.h>
#include "mazepath.h"
/*------------------------------------------------
    走迷宫游戏v1.0
屏幕大小:   640*480
Width        每个小方块宽度
Space        每个小方块间隔
Step         每块占据象素

drawflag     线程互斥全局变量,为true画图,
             为false走迷宫
threadflag   判断线程是否结束的全局变量,为false
             线程结束,程序结束
maze;        迷宫全局对象
start,mymyend    迷宫起终点全局变量


函数InitMaze        初始化迷宫
函数RandmMaze       随机生成迷宫
函数DrawMaze        绘制迷宫
函数ThreadMazePath  子线程函数,调用走迷宫函数修
                    改迷宫对象数据
    算法设计思想
数据结构:     迷宫每个元素由位置坐标x,y和是否可走
               的状态c构成,x、y代表画块的左上角坐
			   标,c为#是障碍,为空格是空位,为!
			   是已走过且不能再走,为*是走过且还有
			   选择;
基本操作:     栈的初始化、销毁、入栈、出栈等;
绘制迷宫操作: 在主线程中绘制,根据元素值c选择不同
               颜色绘制,根据元素值x、y,确定绘制
			   位置;
走迷宫操作:   在子线程中计算迷宫对象走动的每一步,
               修改迷宫对象的值,但不绘制迷宫,通
			   过修改互斥变量drawflag的值,在两个
			   线程中交替进行绘制和走步。				
-------------------------------------------------*/
#define Width 24
#define Space 2
#define Step  (Width + Space)

bool drawflag=true;
MazeType maze;
PosType mymyend;
PosType start;

bool threadflag=true;

void InitMaze(MazeType &maze)
{
	//初始化迷宫,将二维数组的每个元素计算出屏幕坐标
	int i,j;
	for(i=0;i<N;i++)
		for(j=0;j<M;j++)
		{
			maze.arr[i][j].x=30+j*Step;
			maze.arr[i][j].y=30+i*Step;
		}
}
void RandmMaze(MazeType &maze,PosType start,PosType mymyend)
{
	//随机生成迷宫,在二维数组内除起终点外其余位置随
	//机生成障碍,障碍数量按比例V计算
	int i,j,k,num;
	//边界和空位初始化
	for(i=0;i<N;i++)
	{
		maze.arr[i][0].c='#';
		maze.arr[i][M-1].c='#';		

		if(i!=0&&i!=N-1)
		{
			for(j=1;j<M-1;j++)
			{
				maze.arr[i][j].c=' ';
			}
		}
	}
	for(i=1;i<M-1;i++)
	{
		maze.arr[0][i].c='#';
		maze.arr[N-1][i].c='#';
	}

	//按分割块占总空间比例随机生成迷宫
	num=(N-2)*(M-2)*V;   //计算需要的分割块数量

	maze.arr[start.r][start.c].c='#'; //为了随机生成分割块不占用起始和终止位置
	maze.arr[mymyend.r][mymyend.c].c='#';

	k=num; 
	while(k>1)
	{
		i=rand()%(N-2)+1;j=rand()%(M-2)+1;
		if(maze.arr[i][j].c==' ')
			maze.arr[i][j].c='#';
		k--;
	}
	maze.arr[start.r][start.c].c=' ';
	maze.arr[mymyend.r][mymyend.c].c=' ';	

}
void DrawMaze(MazeType &maze)
{
	//绘制迷宫,按不同状态绘制不同颜色方块
	int i,j;
		
	for(i=0;i<N;i++)
	{
		for(j=0;j<M;j++)
		{
			switch(maze.arr[i][j].c)
			{
			case '#':   //障碍块
				setfillstyle(SOLID_FILL,LIGHTBLUE);
				break;
			case '!':   //已走过且无路可走的块
				setfillstyle(SOLID_FILL,LIGHTRED);
				break;
			case '*':   //走过的块
				setfillstyle(SOLID_FILL,LIGHTGREEN);
				break;
			case ' ':   //空闲块
				setfillstyle(SOLID_FILL,BLACK);
				break;
			}
			bar(maze.arr[i][j].x,maze.arr[i][j].y,maze.arr[i][j].x+Width,maze.arr[i][j].y+Width);
		}
		//cout<<mymyendl;
	}

}

DWORD WINAPI ThreadMazePath(LPVOID plParameter)
{
	//子线程函数,调用走迷宫函数修改迷宫对象数据
	//迷宫无解再生成新迷宫,直到有解
	int k=1;
	srand(time(0));
	RandmMaze(maze,start,mymyend); //随机生成迷宫

	while(!MazePath(maze,start,mymyend))
	{		
		cout<<"第"<<k<<"个迷宫无解!"<<endl;
		
		getchar();
		RandmMaze(maze,start,mymyend);k++;		
	}
	cout<<"第"<<k<<"个迷宫有解!"<<endl;
	
	setfillstyle(SOLID_FILL,BLACK);
	bar(100,450,500,480);
	setcolor(YELLOW);
	SetFont(16,16,0,0,0,FALSE,FALSE,FALSE,"宋体"); //文字设为宋体
	outtextxy(100,450,"此迷宫有通路!");

	threadflag=false;  //线程结束标记
	return 0;
}
void main()
{
	//初始化图形界面
	initgraph(640,480);
	//清屏
	cleardevice();

	//默认全局变量为true
	drawflag=true;   
	threadflag=true;

	
	InitMaze(maze);     //初始化迷宫对象
	
	start.r=start.c=1;  //初始化起终点
	mymyend.r=N-2;mymyend.c=M-2;

	//创建走迷宫数据计算子线程
	HANDLE hThread1=CreateThread(NULL,
        0,ThreadMazePath,NULL,0,NULL);
	

	while(threadflag)   //子线程未结束
	{
		Sleep(100);
		if(drawflag)     //线程互斥变量为真,画图,否则等待迷宫走完一步
		{
			DrawMaze(maze);	
			drawflag=false;  //画完一步,置为假,迷宫数据计算子线程走下一步
		}
	}

	
	//结束前任意键暂停
	getchar();
	//关闭图形界面
	closegraph();

}



 

原文地址:https://www.cnblogs.com/lixingle/p/3313019.html