数字迷宫思考-上

 

数字迷宫思考-

                                                        ----用栈的方法实现

 

数字迷宫游戏,可以用递归和栈的方法来实现穷举搜索通往出口的路径。实现的过程中,需要建立一个表示迷宫的二维数组,数组中的每个元素用01表示,0为此节点是通路,1表示断路,不能继续前行。迷宫的四周都是1表示的墙,只有一个入口和一个出口,每个结点都有八个方向可以搜索。游戏开始的时候,从入口进入,按“北->东北->…->西北”的逆时针方向依次搜索路径,当d方向的下一结点是0,则将当前节点入栈,并将当前节点标记为“1”走过,防止向前搜索失败回溯时再重复。当搜索到某个节点时,不能再继续向下,即进入了死胡同时,就需要回溯,将上一个节点出栈,并在上一节点的下一个方向上搜索,若8个方向都遍历完还没找到前进节点,则继续回溯如果栈为空时,表示回到出发点,没有到达出口的路径。

在实现这个过程的时候,可以用顺序栈,也可以用链式栈。但是,如果顺序栈定义为模板类的时候,将路径节点入栈的时候,其过程是值入栈,而结构体又包含横纵坐标值和方向值,这样一来就会导致出栈时得到的是某一节点的横坐标值或纵坐标值或方向值(根据结构体的定义顺序而已,也即是结构体中最后定义的那个元素)。如果,路径是朝入口处开始搜索的方向(北向)不变一直走到出口(即没有出栈操作),能找到出口,但却不能正常显示走过的路径节点信息。因此,用入栈地址的方式更加合理,即采用链式栈的方式。

由于栈的元素是先进后出,因此,在显示路径信息的时候,是从出口到入口的顺序。为了按入口到出口的顺序显示路径信息,需要将栈进行逆向排列。然而,栈是用模板类进行定义的,当结构体作为一种元素类型入栈时,模板类栈事先是不知道其具体类型的(即结构体包含多少元素信息),因此,在定义链式栈时将栈顶指针设为公有,这多少有些违背了类隐藏的原则。因此,最好的办法还是不要用模板类链栈的定义。下面附上实现数字迷宫的c++源代码。

 

/**********************************************************

Copyright@2009-2011 by hank(SiChuan University)

***********************************************************/

//Node.h

#ifndef NODE_H

#define NODE_H

//数组元素节点类定义

#include<string.h>

#include<cstdlib>

struct offset

{

       int a;

       int   b;

};

 

struct item

{

       int x;

       int   y;

       int   dir;

};

#endif

/**********************************************************

Copyright@2009-2011 by hank(SiChuan University)

***********************************************************/

//ItStack.h

#ifndef LINKEDSTACK_H

#define LINKEDSTACK_H

//链式栈的类定义

#include<cstdlib>

#include<cassert>

template<class T>

struct LinkNode

{

       T data;

       LinkNode<T>* link;

       LinkNode(LinkNode<T>* ptr=NULL):link(ptr){}

       LinkNode(T item,LinkNode<T>* ptr=NULL):data(item),link(ptr){}

};

 

template<class T>

class LinkedStack

{

      

public:

       LinkNode<T>* top;//暂时这样,方便后面的输出

       LinkedStack(){top=NULL/*new LinkNode<T>*/;}//默认构造函数,初始化为NULL,怎么能是开辟空间呢!

       //LinkedStack(LinkedStack<T>& LS);//拷贝构造函数,暂时不用,需要先逆转再逐个复制

       ~LinkedStack(){makeEmpty();delete top;}//析构函数

 

       void makeEmpty();//清空栈,仅剩下栈头

       int Length();//获取栈长度

 

       LinkNode<T>* topPointer(){return top;}//取栈头指针

       bool IsEmpty()const{return top==NULL?true:false;}//空否?

       void push(T& x);//入栈

       bool pop(/*const*/ T& x);//出栈

       bool getTop(T& x)const;//取栈顶元素

       void output();//显示栈元素

       voidReverse();//逆转栈

};

#endif

/**********************************************************

Copyright@2009-2011 by hank(SiChuan University)

***********************************************************/

// ItStack.cpp

#include"ItStack.h"

//清空栈,仅剩下栈头

template<class T>

void LinkedStack<T>::makeEmpty()

{

       LinkNode<T>* del;

       while(top!=NULL)

       {

              del=top;

              top=top->link;

              delete /*top*/del;//怎么搞的哦,把topdelete

       }

}

 

/*************************************************/

//入栈,只要能开辟空间就能入栈,不存在栈慢的情况

template<class T>

void LinkedStack<T>::push(T& x)

{

       LinkNode<T>* newNode;

       newNode=new LinkNode<T>(x);

       assert(newNode!=NULL);

       newNode->link=top;

       top=newNode;

}

/*************************************************/

//出栈,需要考虑空栈的情况

template<class T>

bool LinkedStack<T>::pop(/*const*/ T& x)//此处不宜const,因为后面元素要出栈,

{                                                                    //且出栈后需要进行修改

       if(IsEmpty())

              return false;

       LinkNode<T>* del=top;

       x=del->data;

       top=del->link;

       delete del;

       return true;

}

/*************************************************/

//取栈顶元素

template<class T>

bool LinkedStack<T>::getTop(T& x)const

{

       if(IsEmpty())

              return false;

       x=top->data;

       return true;

}

 

/*************************************************/

//获取栈长度

template<class T>

int LinkedStack<T>::Length()

{

       LinkNode<T>* current=top;

       int count=0;

       while(current!=NULL)

       {

              count++;

              current=current->link;

       }

       return count;

}

/*************************************************/

//显示栈元素,先进后出

template<class T>

void LinkedStack<T>::output()

{

       LinkNode<T>* current=top;

       if(IsEmpty())

       {

              cout<<"空栈!没有显示的元素!"<<endl;

              return;

       }

       cout<<"链式栈的元素是:"<<endl;

       while(current!=NULL)

       {

              cout<<current->data<<" ";

              current=current->link;

       }

       cout<<endl;

}

/*************************************************/

//逆转栈

 

template<class T>

void/*LinkedStack<T>* */LinkedStack<T>::Reverse()

{

       LinkNode<T>* p=top,*q,*r;

       q=p->link;

       p->link=NULL;

       while(q!=NULL)

       {

              r=q->link;

              q->link=p;

              p=q;

              q=r;

       }

       top=p;

 

}

/**********************************************************

Copyright@2009-2011 by hank(SiChuan University)

***********************************************************/

//Maze.h

#ifndef MAZE_H

#define MAZE_H

#include"Node.h"

 

#include"ItStack.h"

//迷宫寻找路径

bool pathSearch(int qr,int qc,int Maze[10][10],int Mark[10][10]);

//显示走过的路径

void MarkGet(int Mark[10][10]);

#endif

/**********************************************************

Copyright@2009-2011 by hank(SiChuan University)

***********************************************************/

//Maze.cpp

#include"Maze.h"

#include"ItStack.cpp"

#include<iostream>

using namespace std;

//迷宫寻找路径

bool pathSearch(int qr,int qc,int Maze[10][10],int Mark[10][10])

{

       offset move[8]={{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1}};

       char dirN[8][3]={"N","NE","E","SE","S","SW","W","NW"};

       int m=10,

              p=10;

       Mark[1][0]=1;

       LinkedStack<item> st;

       item it;

       it.x=1;it.y=0;it.dir=0;

       st.push(it);

       int i,j,g,h,d;

       while(!st.IsEmpty()/*==false*/)

       {

              st.pop(it);

              i=it.x; j=it.y; d=it.dir;

              while(d<8)

              {

                     g=i+move[d].a;

                     h=j+move[d].b;

                     if(g==qr && h==qc)

                     {

                            it.x=/*g*/i;it.y=/*h*/j;it.dir=d;

                            st.push(it);

                            it.x=g;it.y=h;it.dir=4;//出口点的dir默认为0

                            Mark[g][h]=1;

                            st.push(it);

                            st.Reverse();

                            cout<<"恭喜,成功到达出口!"<<endl;

                            //cout<<"栈长"<<st.Length()<<endl;

                            //cout<<"出口是: ("<<g<<","<<h<<")"<<endl;

                            /*******************************************/

                            //这一段其实不是很好,只是为了显示才将top设为public,实际上违反了隐蔽性原则

                            LinkNode<item>* current=st.topPointer();

                            int k=0;

                            cout<<"**************唯一路径为**************"<<endl;

                            while(current!=NULL)

                            {

                                   int od=current->data.dir;

                                   cout<<"("<<current->data.x<<","<<current->data.y<<","<<dirN[od]<<")"<<" ";

                                   k++;

                                   if((k%3==0))

                                          cout<<endl;

                                   current=current->link;

                            }

                            cout<<"/n************迷宫路径探索图************"<<endl;

                            /**********************************************/

                            MarkGet(Mark);

                            return true;

                     }

                     else if(Maze[g][h]==0 && Mark[g][h]==0)

                     {

                            Mark[g][h]=1;

                            it.x=i; it.y=j;it.dir=d;

                            st.push(it);

                            i=g; j=h; d=0;

                     }

                     else

                            d++;

              }

 

       }

       cout<<"没有到达出口的路径!"<<endl;

       return false;

}

/*************************************************/

//显示走过的路径

void MarkGet(int Mark[10][10])

{

       for(int i=0;i<10;i++)

       {

              for(int j=0;j<10;j++)

                     cout<<Mark[i][j];

              cout<<endl;

       }

}

 

/**********************************************************

Copyright@2009-2011 by hank(SiChuan University)

***********************************************************/

//main.cpp

#include"Maze.h"

#include<iostream>

using namespace std;

 

int main()

{

       //offset move[8]={{-1,0},{-1,1},{0,1},{1,0},{1,-1},{0,-1},{-1,-1}};

       int m=10,

              p=10;

       int Mark[10][10];

       for(int i=0;i<10;i++)

              for(int j=0;j<10;j++)

                     Mark[i][j]=0;

             

       int Maze[10][10]={{1,1,1,1,1,1,1,1,1,1},

       {0,0,0,1,1,0,1,1,0,1},{1,1,1,0,0,1,1,0,1,1},{1,1,0,1,1,0,0,1,1,1},

       {1,0,1,1,0,1,1,0,1,1},{1,1,0,1,1,1,1,1,0,1},{1,0,1,1,0,1,1,1,1,1},

       {1,0,1,0,1,1,1,1,1,1},{1,1,0,1,0,0,0,1,1,1},{1,1,1,1,1,1,1,0,1,1}};

       cout<<"***************迷宫阵型图**************"<<endl;

       for(int ii=0;ii<10;ii++)

       {

              for(int jj=0;jj<10;jj++)

                     cout<<Maze[ii][jj]<<" ";

              cout<<endl;

       }

       int qr=9,

              qc=7;

       bool out=pathSearch(qr,qc,Maze,Mark);

       return 0;

}

 

附结果图如下:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,生成迷宫可以采用随机生成的方法,具体实现可以按照以下步骤: 1. 定义一个二维数组表示迷宫,其中 0 表示通路,1 表示墙壁; 2. 初始化迷宫,将所有元素都赋值为 1,表示全部为墙壁; 3. 从起点开始,随机选择一个方向(上、下、左、右),并将其邻居元素(即相邻的上下左右四个元素)设置为通路(即将其值设为 0); 4. 重复步骤 3,直到迷宫中存在通路连接起点和终点。 下面是一份示例代码,仅供参考: ```c #include <stdio.h> #include <stdlib.h> #include <time.h> #define ROW 10 // 迷宫行数 #define COL 10 // 迷宫列数 // 随机生成一个 0 或 1 的整数 int rand_int() { return rand() % 2; } // 打印迷宫 void print_maze(int maze[][COL]) { for (int i = 0; i < ROW; i++) { for (int j = 0; j < COL; j++) { if (maze[i][j] == 0) { printf(" "); // 通路 } else { printf("■"); // 墙壁 } } printf("\n"); } } int main() { srand((unsigned)time(NULL)); // 初始化随机数种子 int maze[ROW][COL]; // 初始化迷宫,全部为墙壁 for (int i = 0; i < ROW; i++) { for (int j = 0; j < COL; j++) { maze[i][j] = 1; } } // 设置起点和终点 maze[0][0] = 0; // 起点 maze[ROW - 1][COL - 1] = 0; // 终点 // 生成迷宫 int i = 0, j = 0; while (maze[ROW - 1][COL - 1] == 1) { // 直到终点可以到达 int dir = rand() % 4; // 随机选择一个方向(上、下、左、右) int new_i = i, new_j = j; switch (dir) { case 0: // 上 if (i > 0) { new_i--; } break; case 1: // 下 if (i < ROW - 1) { new_i++; } break; case 2: // 左 if (j > 0) { new_j--; } break; case 3: // 右 if (j < COL - 1) { new_j++; } break; } if (maze[new_i][new_j] == 1) { // 如果邻居是墙壁,将其设置为通路 maze[new_i][new_j] = 0; i = new_i; j = new_j; } } // 打印迷宫 print_maze(maze); return 0; } ``` 这份代码生成的迷宫可能会比较简单,如果想增加难度,可以调整迷宫的大小、调整随机选择方向的概率,或者采用其他更复杂的算法来生成迷宫
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值