#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(); }