数据结构迷宫破解

MazePath.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);
sqstack.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);
selemtype.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;   //全局变量外部声明

linkstack.h的源代码:

#include "selemtype.h"
#define MaxSize 1000
typedef struct StackNode
{
	SElemType data;
	struct StackNode *next;
}*Stack;

Status InitStack(Stack &S);
Status DestroyStack(Stack &S);
Status StackEmpty(Stack &S);
Status Push(Stack &S,SElemType &e);
Status Pop(Stack &S,SElemType &e);

sqstack.cpp的源代码:
#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.data[S.top] = e ;  
        S.top++;  
       return true ;  
    } 
	else
       return false;  
}
Status Pop(Stack &S,SElemType &e)
{
    if(S.top > 0)  
    {  
        S.top--;  
        e = S.data[S.top] ;  
        return true ;   
          
    } 
	else
        return false;  
}

linkstack.cpp的源代码:
#include <iostream>
using namespace std;
#include "linkstack.h"

Status InitStack(Stack &S)
{
	return true;
}
Status DestroyStack(Stack &S)
{
	return true;
}
Status StackEmpty(Stack &S)
{
	return true;
}
Status Push(Stack &S,SElemType &e)
{
	return true;
}
Status Pop(Stack &S,SElemType &e)
{
	return true;
}

MazePath.cpp的源代码:

/*------------------------------------------------
    走迷宫算法v1.0
N            迷宫行数
M            迷宫列数
V            分割块占总空间比例
ElemType     迷宫元素类型
MazeType     迷宫类型

函数MazePath   走迷宫算法
函数Pass       判断当前位置是否可通过
函数FootPrint  留下足迹
函数MarkPrint  留下不能再走的标记
函数NextPos    计算下一位置
-------------------------------------------------*/
#include "MazePath.h"
Status MazePath(MazeType &maze, PosType start, PosType End)
{
	// 算法3.3
	// 若迷宫maze中从入口 start到出口 end的通道,则求得一条存放在栈中
	// (从栈底到栈顶),并返回TRUE;否则返回FALSE	
	Stack stack;   //定义一个栈  
    InitStack(stack);  //初始化该栈  
    int count = 0 ;   //用来记录通道块的序号  
    PosType nextPos = start,curPos = start;  
    SElemType e,pe;  
    pe.di = 0;  
    int di = 0 ;  
    bool judger = true ;  
    bool uu = true;  
    while(true)  
    {  
          
        for(int i = 1 ; i <= 4 ; i++ )  
        {  
                nextPos = NextPos(curPos,i);  
                if(Pass(maze,nextPos))  
                {  
  
                    count++;  
                    e.seat = curPos ;  
                    e.ord = count;  
                    e.di = i ;  
                    FootPrint(maze,curPos);  
                    Push(stack, e);  
                    curPos = nextPos ;  
                    judger = true ;  
                    if(curPos.c==End.c&&curPos.r==End.r)  
                    {  
                        count++;  
                        e.seat = curPos ;  
                        e.ord = count;  
                        e.di = i ;  
                        FootPrint(maze,curPos);  
                        Push(stack, e);  
                        return true ;  
                    }  
                    break;  
                }  
            if(i == 4)  
            {  
                if(judger)  //走投无路时将最后一个通道块压入栈  
                {  
  
                    count++;  
                    e.seat = curPos ;  
                    e.ord = count;  
                    e.di = i ;  
                    FootPrint(maze,curPos);  
                    Push(stack, e);   
                    judger = false;  
                    if(curPos.c==End.c&&curPos.r==End.r)  
                        return true ;  
                }  
                Pop(stack , pe);   //出栈  
                curPos = pe.seat ;  
                MarkPrint(maze , pe.seat);    //标记为走过且不可走  
                if(stack.top == 0)  
                    return false;  
                break;  
            }  
              
        }  
    }  
  
  
	return TRUE;
} // 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;
}

main.cpp的源代码:
#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,end    迷宫起终点全局变量 
 
 
函数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 start,End;  
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 end)  
{  
    //随机生成迷宫,在二维数组内除起终点外其余位置随  
    //机生成障碍,障碍数量按比例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[end.r][end.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[end.r][end.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<<endl;  
    }  
  
}  
  
DWORD WINAPI ThreadMazePath(LPVOID plParameter)  
{  
    //子线程函数,调用走迷宫函数修改迷宫对象数据  
    //迷宫无解再生成新迷宫,直到有解  
    int k=1;  
    srand(time(0));  
    RandmMaze(maze,start,End); //随机生成迷宫  
  
    while(!MazePath(maze,start,End))  
    {         
        cout<<"第"<<k<<"个迷宫无解!"<<endl;  
          
        getchar();  
        InitMaze(maze);  
        RandmMaze(maze,start,End);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;  //初始化起终点  
    End.r=N-2;End.c=M-2;  
  
    //创建走迷宫数据计算子线程  
    HANDLE hThread1=CreateThread(NULL,  
        0,ThreadMazePath,NULL,0,NULL);  
  
    while(threadflag)   //子线程未结束  
    {  
        Sleep(100);  
        if(drawflag)     //线程互斥变量为真,画图,否则等待迷宫走完一步  
        {  
            DrawMaze(maze);   
            drawflag=false;  //画完一步,置为假,迷宫数据计算子线程走下一步  
        }  
    }  
  
    //结束前任意键暂停  
    getchar();  
    //关闭图形界面  
    closegraph();  
  
}  


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值